Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
15 changes: 15 additions & 0 deletions databricks/sdk/common/types/fieldmask.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class FieldMask(object):
"""Class for FieldMask message type."""

def ToJsonString(self):
"""Converts FieldMask to string."""
return ",".join(self.paths)

def FromJsonString(self, value):
"""Converts string to FieldMask."""
if not isinstance(value, str):
raise ValueError("FieldMask JSON value not a string: {!r}".format(value))
if value:
self.paths = value.split(",")
else:
self.paths = []
64 changes: 63 additions & 1 deletion databricks/sdk/service/_internal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import datetime
import urllib.parse
from typing import Callable, Dict, Generic, Optional, Type, TypeVar
from typing import Callable, Dict, Generic, List, Optional, Type, TypeVar

from google.protobuf.duration_pb2 import Duration
from google.protobuf.timestamp_pb2 import Timestamp

from databricks.sdk.common.types.fieldmask import FieldMask


def _from_dict(d: Dict[str, any], field: str, cls: Type) -> any:
Expand Down Expand Up @@ -46,6 +51,63 @@ def _escape_multi_segment_path_parameter(param: str) -> str:
return urllib.parse.quote(param)


def _timestamp(d: Dict[str, any], field: str) -> Optional[Timestamp]:
if field not in d or not d[field]:
return None
ts = Timestamp()
ts.FromJsonString(d[field])
return ts


def _repeated_timestamp(d: Dict[str, any], field: str) -> Optional[List[Timestamp]]:
if field not in d or not d[field]:
return None
result = []
for v in d[field]:
ts = Timestamp()
ts.FromJsonString(v)
result.append(ts)
return result


def _duration(d: Dict[str, any], field: str) -> Optional[Duration]:
if field not in d or not d[field]:
return None
dur = Duration()
dur.FromJsonString(d[field])
return dur


def _repeated_duration(d: Dict[str, any], field: str) -> Optional[List[Duration]]:
if field not in d or not d[field]:
return None
result = []
for v in d[field]:
dur = Duration()
dur.FromJsonString(v)
result.append(dur)
return result


def _fieldmask(d: Dict[str, any], field: str) -> Optional[FieldMask]:
if field not in d or not d[field]:
return None
fm = FieldMask()
fm.FromJsonString(d[field])
return fm


def _repeated_fieldmask(d: Dict[str, any], field: str) -> Optional[List[FieldMask]]:
if field not in d or not d[field]:
return None
result = []
for v in d[field]:
fm = FieldMask()
fm.FromJsonString(v)
result.append(fm)
return result


ReturnType = TypeVar("ReturnType")


Expand Down
80 changes: 80 additions & 0 deletions tests/test_fieldmask.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import pytest

from databricks.sdk.common.types.fieldmask import FieldMask


@pytest.mark.parametrize(
"input_paths,expected_result,description",
[
(["field1", "field2", "field3"], "field1,field2,field3", "basic list of paths"),
(["single_field"], "single_field", "single path"),
([], "", "empty paths list"),
(["user.name", "user.email", "address.street"], "user.name,user.email,address.street", "nested field paths"),
],
)
def test_to_json_string(input_paths, expected_result, description):
"""Test ToJsonString with various path configurations."""
field_mask = FieldMask()
field_mask.paths = input_paths

result = field_mask.ToJsonString()

assert result == expected_result


@pytest.mark.parametrize(
"input_string,expected_paths,description",
[
("field1,field2,field3", ["field1", "field2", "field3"], "basic comma-separated string"),
("single_field", ["single_field"], "single field"),
("", [], "empty string"),
("user.name,user.email,address.street", ["user.name", "user.email", "address.street"], "nested field paths"),
("field1, field2 , field3", ["field1", " field2 ", " field3"], "spaces around commas"),
],
)
def test_from_json_string_success_cases(input_string, expected_paths, description):
"""Test FromJsonString with various valid input strings."""
field_mask = FieldMask()

field_mask.FromJsonString(input_string)

assert field_mask.paths == expected_paths


@pytest.mark.parametrize(
"invalid_input,expected_error_substring,description",
[
(123, "FieldMask JSON value not a string: 123", "non-string integer input"),
(None, "FieldMask JSON value not a string: None", "None input"),
(["field1", "field2"], "FieldMask JSON value not a string:", "list input"),
({"field": "value"}, "FieldMask JSON value not a string:", "dict input"),
],
)
def test_from_json_string_error_cases(invalid_input, expected_error_substring, description):
"""Test FromJsonString raises ValueError for invalid input types."""
field_mask = FieldMask()

with pytest.raises(ValueError) as exc_info:
field_mask.FromJsonString(invalid_input)

assert expected_error_substring in str(exc_info.value)


@pytest.mark.parametrize(
"original_paths,description",
[
(["user.name", "user.email", "profile.settings"], "multiple nested fields"),
(["single_field"], "single field"),
([], "empty paths"),
],
)
def test_roundtrip_conversion(original_paths, description):
"""Test that ToJsonString and FromJsonString are inverse operations."""
field_mask = FieldMask()
field_mask.paths = original_paths

# Convert to string and back.
json_string = field_mask.ToJsonString()
field_mask.FromJsonString(json_string)

assert field_mask.paths == original_paths
148 changes: 146 additions & 2 deletions tests/test_internal.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
from dataclasses import dataclass
from enum import Enum

import pytest
from google.protobuf.duration_pb2 import Duration
from google.protobuf.timestamp_pb2 import Timestamp

from databricks.sdk.common.types.fieldmask import FieldMask
from databricks.sdk.service._internal import (
_enum, _escape_multi_segment_path_parameter, _from_dict, _repeated_dict,
_repeated_enum)
_duration, _enum, _escape_multi_segment_path_parameter, _fieldmask,
_from_dict, _repeated_dict, _repeated_duration, _repeated_enum,
_repeated_fieldmask, _repeated_timestamp, _timestamp)


class A(Enum):
Expand Down Expand Up @@ -52,3 +58,141 @@ def test_escape_multi_segment_path_parameter():
assert _escape_multi_segment_path_parameter("a/b") == "a/b"
assert _escape_multi_segment_path_parameter("a?b") == "a%3Fb"
assert _escape_multi_segment_path_parameter("a#b") == "a%23b"


@pytest.mark.parametrize(
"input_dict,field_name,expected_result,expected_json,description",
[
({"field": "2023-01-01T12:00:00Z"}, "field", "timestamp_object", "2023-01-01T12:00:00Z", "valid timestamp"),
({}, "field", None, None, "missing field"),
({"field": None}, "field", None, None, "None value"),
({"field": ""}, "field", None, None, "empty value"),
],
)
def test_timestamp(input_dict, field_name, expected_result, expected_json, description):
"""Test _timestamp function with various input scenarios."""
result = _timestamp(input_dict, field_name)

if expected_result is None:
assert result is None
else:
assert isinstance(result, Timestamp)
assert result.ToJsonString() == expected_json


@pytest.mark.parametrize(
"input_dict,field_name,expected_length,expected_json_list,description",
[
(
{"field": ["2023-01-01T12:00:00Z", "2023-01-02T12:00:00Z"]},
"field",
2,
["2023-01-01T12:00:00Z", "2023-01-02T12:00:00Z"],
"valid repeated timestamps",
),
({}, "field", None, None, "missing field"),
({"field": None}, "field", None, None, "None value"),
({"field": []}, "field", None, None, "empty list"),
],
)
def test_repeated_timestamp(input_dict, field_name, expected_length, expected_json_list, description):
"""Test _repeated_timestamp function with various input scenarios."""
result = _repeated_timestamp(input_dict, field_name)

if expected_length is None:
assert result is None
else:
assert len(result) == expected_length
assert all(isinstance(ts, Timestamp) for ts in result)
for i, expected_json in enumerate(expected_json_list):
assert result[i].ToJsonString() == expected_json


@pytest.mark.parametrize(
"input_dict,field_name,expected_result,expected_json,description",
[
({"field": "3600s"}, "field", "duration_object", "3600s", "valid duration"),
({}, "field", None, None, "missing field"),
({"field": None}, "field", None, None, "None value"),
({"field": ""}, "field", None, None, "empty value"),
],
)
def test_duration(input_dict, field_name, expected_result, expected_json, description):
"""Test _duration function with various input scenarios."""
result = _duration(input_dict, field_name)

if expected_result is None:
assert result is None
else:
assert isinstance(result, Duration)
assert result.ToJsonString() == expected_json


@pytest.mark.parametrize(
"input_dict,field_name,expected_length,expected_json_list,description",
[
({"field": ["3600s", "7200s"]}, "field", 2, ["3600s", "7200s"], "valid repeated durations"),
({}, "field", None, None, "missing field"),
({"field": None}, "field", None, None, "None value"),
({"field": []}, "field", None, None, "empty list"),
],
)
def test_repeated_duration(input_dict, field_name, expected_length, expected_json_list, description):
"""Test _repeated_duration function with various input scenarios."""
result = _repeated_duration(input_dict, field_name)

if expected_length is None:
assert result is None
else:
assert len(result) == expected_length
assert all(isinstance(dur, Duration) for dur in result)
for i, expected_json in enumerate(expected_json_list):
assert result[i].ToJsonString() == expected_json


@pytest.mark.parametrize(
"input_dict,field_name,expected_result,expected_json,description",
[
({"field": "path1,path2"}, "field", "fieldmask_object", "path1,path2", "valid fieldmask"),
({}, "field", None, None, "missing field"),
({"field": None}, "field", None, None, "None value"),
({"field": ""}, "field", None, None, "empty value"),
],
)
def test_fieldmask(input_dict, field_name, expected_result, expected_json, description):
"""Test _fieldmask function with various input scenarios."""
result = _fieldmask(input_dict, field_name)

if expected_result is None:
assert result is None
else:
assert isinstance(result, FieldMask)
assert result.ToJsonString() == expected_json


@pytest.mark.parametrize(
"input_dict,field_name,expected_length,expected_json_list,description",
[
(
{"field": ["path1,path2", "path3,path4"]},
"field",
2,
["path1,path2", "path3,path4"],
"valid repeated fieldmasks",
),
({}, "field", None, None, "missing field"),
({"field": None}, "field", None, None, "None value"),
({"field": []}, "field", None, None, "empty list"),
],
)
def test_repeated_fieldmask(input_dict, field_name, expected_length, expected_json_list, description):
"""Test _repeated_fieldmask function with various input scenarios."""
result = _repeated_fieldmask(input_dict, field_name)

if expected_length is None:
assert result is None
else:
assert len(result) == expected_length
assert all(isinstance(fm, FieldMask) for fm in result)
for i, expected_json in enumerate(expected_json_list):
assert result[i].ToJsonString() == expected_json
Loading