Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e5a2992

Browse files
authoredMay 30, 2024
feat: support type annotations with bpd.remote_function() and axis=1 (a preview feature) (#730)
* feat: support type annotations with `bpd.remote_function()` and `axis=1` (a preview feature) * add missing parentheses
1 parent f12c906 commit e5a2992

File tree

5 files changed

+52
-4
lines changed

5 files changed

+52
-4
lines changed
 

‎bigframes/functions/remote_function.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from __future__ import annotations
1616

17+
import collections.abc
1718
import hashlib
1819
import inspect
1920
import logging
@@ -1043,6 +1044,8 @@ def wrapper(func):
10431044
"Types are required to use @remote_function."
10441045
)
10451046
input_types.append(param_type)
1047+
elif not isinstance(input_types, collections.abc.Sequence):
1048+
input_types = [input_types]
10461049

10471050
if output_type is None:
10481051
if (output_type := signature.return_annotation) is inspect.Signature.empty:
@@ -1055,9 +1058,12 @@ def wrapper(func):
10551058
# The function will actually be receiving a pandas Series, but allow both
10561059
# BigQuery DataFrames and pandas object types for compatibility.
10571060
is_row_processor = False
1058-
if input_types == bigframes.series.Series or input_types == pandas.Series:
1061+
if len(input_types) == 1 and (
1062+
(input_type := input_types[0]) == bigframes.series.Series
1063+
or input_type == pandas.Series
1064+
):
10591065
warnings.warn(
1060-
"input_types=Series scenario is in preview.",
1066+
"input_types=Series is in preview.",
10611067
stacklevel=1,
10621068
category=bigframes.exceptions.PreviewWarning,
10631069
)

‎tests/system/small/test_remote_function.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ def add_ints(row):
727727

728728
with pytest.warns(
729729
bigframes.exceptions.PreviewWarning,
730-
match="input_types=Series scenario is in preview.",
730+
match="input_types=Series is in preview.",
731731
):
732732
add_ints_remote = session.remote_function(bigframes.series.Series, int)(
733733
add_ints

‎tests/unit/resources.py

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import pytest
2424

2525
import bigframes
26+
import bigframes.clients
2627
import bigframes.core as core
2728
import bigframes.core.ordering
2829
import bigframes.dataframe
@@ -97,6 +98,9 @@ def query_mock(query, *args, **kwargs):
9798

9899
bqoptions = bigframes.BigQueryOptions(credentials=credentials, location=location)
99100
session = bigframes.Session(context=bqoptions, clients_provider=clients_provider)
101+
session._bq_connection_manager = mock.create_autospec(
102+
bigframes.clients.BqConnectionManager, instance=True
103+
)
100104
return session
101105

102106

‎tests/unit/test_remote_function.py

+38
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,53 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import re
16+
1517
import bigframes_vendored.ibis.backends.bigquery.datatypes as third_party_ibis_bqtypes
1618
from ibis.expr import datatypes as ibis_types
19+
import pandas
1720
import pytest
1821

1922
import bigframes.dtypes
2023
import bigframes.functions.remote_function
24+
import bigframes.series
2125
from tests.unit import resources
2226

2327

28+
@pytest.mark.parametrize(
29+
"series_type",
30+
(
31+
pytest.param(
32+
pandas.Series,
33+
id="pandas.Series",
34+
),
35+
pytest.param(
36+
bigframes.series.Series,
37+
id="bigframes.series.Series",
38+
),
39+
),
40+
)
41+
def test_series_input_types_to_str(series_type):
42+
"""Check that is_row_processor=True uses str as the input type to serialize a row."""
43+
session = resources.create_bigquery_session()
44+
remote_function_decorator = bigframes.functions.remote_function.remote_function(
45+
session=session
46+
)
47+
48+
with pytest.warns(
49+
bigframes.exceptions.PreviewWarning,
50+
match=re.escape("input_types=Series is in preview."),
51+
):
52+
53+
@remote_function_decorator
54+
def axis_1_function(myparam: series_type) -> str: # type: ignore
55+
return "Hello, " + myparam["str_col"] + "!" # type: ignore
56+
57+
# Still works as a normal function.
58+
assert axis_1_function(pandas.Series({"str_col": "World"})) == "Hello, World!"
59+
assert axis_1_function.ibis_node is not None
60+
61+
2462
def test_supported_types_correspond():
2563
# The same types should be representable by the supported Python and BigQuery types.
2664
ibis_types_from_python = {

‎third_party/bigframes_vendored/pandas/core/series.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3969,7 +3969,7 @@ def map(
39693969
39703970
It also accepts a remote function:
39713971
3972-
>>> @bpd.remote_function
3972+
>>> @bpd.remote_function()
39733973
... def my_mapper(val: str) -> str:
39743974
... vowels = ["a", "e", "i", "o", "u"]
39753975
... if val:

0 commit comments

Comments
 (0)
Failed to load comments.