Skip to content

Commit 7cae208

Browse files
feat: Expose more remote functions options as first class properties
Exposes `maxBatchingRows`, `containerCpu`, and `containerMemory` as first-class properties on the `RemoteFunctionOptions` class. Fixes #2240
1 parent 7cad6cf commit 7cae208

File tree

3 files changed

+86
-2
lines changed

3 files changed

+86
-2
lines changed

google/cloud/bigquery/routine/routine.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,8 @@ class RemoteFunctionOptions(object):
625625
"connection": "connection",
626626
"max_batching_rows": "maxBatchingRows",
627627
"user_defined_context": "userDefinedContext",
628+
"container_cpu": "containerCpu",
629+
"container_memory": "containerMemory",
628630
}
629631

630632
def __init__(
@@ -633,6 +635,8 @@ def __init__(
633635
connection=None,
634636
max_batching_rows=None,
635637
user_defined_context=None,
638+
container_cpu=None,
639+
container_memory=None,
636640
_properties=None,
637641
) -> None:
638642
if _properties is None:
@@ -647,6 +651,10 @@ def __init__(
647651
self.max_batching_rows = max_batching_rows
648652
if user_defined_context is not None:
649653
self.user_defined_context = user_defined_context
654+
if container_cpu is not None:
655+
self.container_cpu = container_cpu
656+
if container_memory is not None:
657+
self.container_memory = container_memory
650658

651659
@property
652660
def connection(self):
@@ -682,7 +690,7 @@ def max_batching_rows(self):
682690

683691
@max_batching_rows.setter
684692
def max_batching_rows(self, value):
685-
self._properties["maxBatchingRows"] = _helpers._str_or_none(value)
693+
self._properties["maxBatchingRows"] = _helpers._int_or_none(value)
686694

687695
@property
688696
def user_defined_context(self):
@@ -699,6 +707,24 @@ def user_defined_context(self, value):
699707
raise ValueError("value must be dictionary")
700708
self._properties["userDefinedContext"] = value
701709

710+
@property
711+
def container_cpu(self):
712+
"""Optional[str]: The container CPU for the remote service."""
713+
return self._properties.get("containerCpu")
714+
715+
@container_cpu.setter
716+
def container_cpu(self, value):
717+
self._properties["containerCpu"] = _helpers._str_or_none(value)
718+
719+
@property
720+
def container_memory(self):
721+
"""Optional[str]: The container memory for the remote service."""
722+
return self._properties.get("containerMemory")
723+
724+
@container_memory.setter
725+
def container_memory(self, value):
726+
self._properties["containerMemory"] = _helpers._str_or_none(value)
727+
702728
@classmethod
703729
def from_api_repr(cls, resource: dict) -> "RemoteFunctionOptions":
704730
"""Factory: construct remote function options given its API representation.

tests/unit/routine/test_remote_function_options.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@ def test_ctor(target_class):
3737
connection=CONNECTION,
3838
max_batching_rows=MAX_BATCHING_ROWS,
3939
user_defined_context=USER_DEFINED_CONTEXT,
40+
container_cpu="1.0",
41+
container_memory="512M",
4042
)
4143
assert options.endpoint == ENDPOINT
4244
assert options.connection == CONNECTION
4345
assert options.max_batching_rows == MAX_BATCHING_ROWS
4446
assert options.user_defined_context == USER_DEFINED_CONTEXT
47+
assert options.container_cpu == "1.0"
48+
assert options.container_memory == "512M"
4549

4650

4751
def test_empty_ctor(target_class):
@@ -64,13 +68,17 @@ def test_from_api_repr(target_class):
6468
"connection": CONNECTION,
6569
"maxBatchingRows": MAX_BATCHING_ROWS,
6670
"userDefinedContext": USER_DEFINED_CONTEXT,
71+
"containerCpu": "1.0",
72+
"containerMemory": "512M",
6773
"someRandomField": "someValue",
6874
}
6975
options = target_class.from_api_repr(resource)
7076
assert options.endpoint == ENDPOINT
7177
assert options.connection == CONNECTION
7278
assert options.max_batching_rows == MAX_BATCHING_ROWS
7379
assert options.user_defined_context == USER_DEFINED_CONTEXT
80+
assert options.container_cpu == "1.0"
81+
assert options.container_memory == "512M"
7482
assert options._properties["someRandomField"] == "someValue"
7583

7684

@@ -81,6 +89,8 @@ def test_from_api_repr_w_minimal_resource(target_class):
8189
assert options.connection is None
8290
assert options.max_batching_rows is None
8391
assert options.user_defined_context is None
92+
assert options.container_cpu is None
93+
assert options.container_memory is None
8494

8595

8696
def test_from_api_repr_w_unknown_fields(target_class):
@@ -95,12 +105,16 @@ def test_eq(target_class):
95105
connection=CONNECTION,
96106
max_batching_rows=MAX_BATCHING_ROWS,
97107
user_defined_context=USER_DEFINED_CONTEXT,
108+
container_cpu="1.0",
109+
container_memory="512M",
98110
)
99111
other_options = target_class(
100112
endpoint=ENDPOINT,
101113
connection=CONNECTION,
102114
max_batching_rows=MAX_BATCHING_ROWS,
103115
user_defined_context=USER_DEFINED_CONTEXT,
116+
container_cpu="1.0",
117+
container_memory="512M",
104118
)
105119
assert options == other_options
106120
assert not (options != other_options)
@@ -120,8 +134,12 @@ def test_repr(target_class):
120134
connection=CONNECTION,
121135
max_batching_rows=MAX_BATCHING_ROWS,
122136
user_defined_context=USER_DEFINED_CONTEXT,
137+
container_cpu="1.0",
138+
container_memory="512M",
123139
)
124140
actual_repr = repr(options)
125141
assert actual_repr == (
126-
"RemoteFunctionOptions(connection='connection_string', endpoint='https://some.endpoint', max_batching_rows=50, user_defined_context={'foo': 'bar'})"
142+
"RemoteFunctionOptions(connection='connection_string', container_cpu='1.0', "
143+
"container_memory='512M', endpoint='https://some.endpoint', "
144+
"max_batching_rows=50, user_defined_context={'foo': 'bar'})"
127145
)

tests/unit/routine/test_routine.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def test_ctor_w_properties(target_class):
8080
connection="connection_string",
8181
max_batching_rows=99,
8282
user_defined_context={"foo": "bar"},
83+
container_cpu="1.0",
84+
container_memory="512M",
8385
)
8486

8587
actual_routine = target_class(
@@ -106,6 +108,8 @@ def test_ctor_w_properties(target_class):
106108
actual_routine.determinism_level == bigquery.DeterminismLevel.NOT_DETERMINISTIC
107109
)
108110
assert actual_routine.remote_function_options == options
111+
assert actual_routine.remote_function_options.container_cpu == "1.0"
112+
assert actual_routine.remote_function_options.container_memory == "512M"
109113

110114

111115
def test_ctor_invalid_remote_function_options(target_class):
@@ -153,6 +157,8 @@ def test_from_api_repr(target_class):
153157
"userDefinedContext": {
154158
"foo": "bar",
155159
},
160+
"containerCpu": "1.0",
161+
"containerMemory": "512M",
156162
},
157163
"dataGovernanceType": "DATA_MASKING",
158164
}
@@ -193,6 +199,8 @@ def test_from_api_repr(target_class):
193199
assert actual_routine.remote_function_options.connection == "connection_string"
194200
assert actual_routine.remote_function_options.max_batching_rows == 50
195201
assert actual_routine.remote_function_options.user_defined_context == {"foo": "bar"}
202+
assert actual_routine.remote_function_options.container_cpu == "1.0"
203+
assert actual_routine.remote_function_options.container_memory == "512M"
196204
assert actual_routine.data_governance_type == "DATA_MASKING"
197205

198206

@@ -489,6 +497,28 @@ def test_from_api_repr_w_unknown_fields(target_class):
489497
},
490498
},
491499
),
500+
(
501+
{
502+
"routineType": "SCALAR_FUNCTION",
503+
"remoteFunctionOptions": {
504+
"endpoint": "https://some_endpoint",
505+
"connection": "connection_string",
506+
"max_batching_rows": 101,
507+
"containerCpu": "1.0",
508+
"containerMemory": "512M",
509+
},
510+
},
511+
["remote_function_options"],
512+
{
513+
"remoteFunctionOptions": {
514+
"endpoint": "https://some_endpoint",
515+
"connection": "connection_string",
516+
"max_batching_rows": 101,
517+
"containerCpu": "1.0",
518+
"containerMemory": "512M",
519+
},
520+
},
521+
),
492522
],
493523
)
494524
def test_build_resource(object_under_test, resource, filter_fields, expected):
@@ -605,3 +635,13 @@ def test_repr(target_class):
605635
model = target_class("my-proj.my_dset.my_routine")
606636
actual_routine = repr(model)
607637
assert actual_routine == "Routine('my-proj.my_dset.my_routine')"
638+
639+
640+
def test_remote_function_options_max_batching_rows_setter():
641+
options = bigquery.RemoteFunctionOptions()
642+
options.max_batching_rows = 10
643+
assert options.max_batching_rows == 10
644+
assert options._properties["maxBatchingRows"] == 10
645+
options.max_batching_rows = None
646+
assert options.max_batching_rows is None
647+
assert options._properties["maxBatchingRows"] is None

0 commit comments

Comments
 (0)