Skip to content

Commit 533db96

Browse files
arwas11tswastgcf-owl-bot[bot]
authored
deps: Add support for Python 3.13 for everything but remote functions (#1307)
* chore: Add support for Python 3.13 * update contibuting.rst with the the new version * skip sklearn import * skip api coverage tests because of sklearn NameError * skip remote function tests * skip all remote function tests and doctests * update doctest python version to 3.12 in noxfile * Update noxfile.py * fix the system_pre-release error * skip remote functions notebooks on 3.13 tests * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Tim Sweña (Swast) <swast@google.com> Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent c22126b commit 533db96

File tree

15 files changed

+154
-38
lines changed

15 files changed

+154
-38
lines changed

.github/workflows/unittest.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
runs-on: ubuntu-22.04
1212
strategy:
1313
matrix:
14-
python: ['3.9', '3.10', '3.11', '3.12']
14+
python: ['3.9', '3.10', '3.11', '3.12', '3.13']
1515
steps:
1616
- name: Checkout
1717
uses: actions/checkout@v4

CONTRIBUTING.rst

+6-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ In order to add a feature:
2222
documentation.
2323

2424
- The feature must work fully on the following CPython versions:
25-
3.9, 3.10, 3.11 and 3.12 on both UNIX and Windows.
25+
3.9, 3.10, 3.11, 3.12 and 3.13 on both UNIX and Windows.
2626

2727
- The feature must not add unnecessary dependencies (where
2828
"unnecessary" is of course subjective, but new dependencies should
@@ -72,7 +72,7 @@ We use `nox <https://nox.readthedocs.io/en/latest/>`__ to instrument our tests.
7272

7373
- To run a single unit test::
7474

75-
$ nox -s unit-3.12 -- -k <name of test>
75+
$ nox -s unit-3.13 -- -k <name of test>
7676

7777

7878
.. note::
@@ -143,12 +143,12 @@ Running System Tests
143143
$ nox -s system
144144

145145
# Run a single system test
146-
$ nox -s system-3.12 -- -k <name of test>
146+
$ nox -s system-3.13 -- -k <name of test>
147147

148148

149149
.. note::
150150

151-
System tests are only configured to run under Python 3.9, 3.11 and 3.12.
151+
System tests are only configured to run under Python 3.9, 3.11, 3.12 and 3.13.
152152
For expediency, we do not run them in older versions of Python 3.
153153

154154
This alone will not run the tests. You'll need to change some local
@@ -262,11 +262,13 @@ We support:
262262
- `Python 3.10`_
263263
- `Python 3.11`_
264264
- `Python 3.12`_
265+
- `Python 3.13`_
265266

266267
.. _Python 3.9: https://docs.python.org/3.9/
267268
.. _Python 3.10: https://docs.python.org/3.10/
268269
.. _Python 3.11: https://docs.python.org/3.11/
269270
.. _Python 3.12: https://docs.python.org/3.12/
271+
.. _Python 3.13: https://docs.python.org/3.13/
270272

271273

272274
Supported versions can be found in our ``noxfile.py`` `config`_.

bigframes/core/expression.py

+13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import typing
2121
from typing import Mapping, TypeVar, Union
2222

23+
import pandas as pd
24+
2325
import bigframes.core.identifiers as ids
2426
import bigframes.dtypes as dtypes
2527
import bigframes.operations
@@ -253,6 +255,17 @@ def is_bijective(self) -> bool:
253255
# () <-> value
254256
return True
255257

258+
def __eq__(self, other):
259+
if not isinstance(other, ScalarConstantExpression):
260+
return False
261+
262+
# With python 3.13 and the pre-release version of pandas,
263+
# NA == NA is NA instead of True
264+
if pd.isna(self.value) and pd.isna(other.value): # type: ignore
265+
return self.dtype == other.dtype
266+
267+
return self.value == other.value and self.dtype == other.dtype
268+
256269

257270
@dataclasses.dataclass(frozen=True)
258271
class UnboundVariableExpression(Expression):

bigframes/session/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1482,7 +1482,7 @@ def read_gbq_function(
14821482
2 TestCad$123456Str
14831483
dtype: string
14841484
1485-
Another use case is to define your own remote funtion and use it later.
1485+
Another use case is to define your own remote function and use it later.
14861486
For example, define the remote function:
14871487
14881488
>>> @bpd.remote_function()

notebooks/getting_started/getting_started_bq_dataframes.ipynb

+14
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,20 @@
14481448
"Running your own Python functions (or being able to bring your packages) and using them at scale is a challenge many data scientists face. BigQuery DataFrames makes it easy to deploy [remote functions](https://cloud.google.com/python/docs/reference/bigframes/latest/bigframes.pandas#bigframes_pandas_remote_function) that run scalar Python functions at BigQuery scale. These functions are persisted as [BigQuery remote functions](https://cloud.google.com/bigquery/docs/remote-functions) that you can then re-use."
14491449
]
14501450
},
1451+
{
1452+
"cell_type": "code",
1453+
"execution_count": null,
1454+
"metadata": {},
1455+
"outputs": [],
1456+
"source": [
1457+
"import sys\n",
1458+
"\n",
1459+
"# Python 3.13 is not yet a supported runtime for remote functions.\n",
1460+
"# See: https://cloud.google.com/functions/docs/runtime-support#python for the supported runtimes.\n",
1461+
"if sys.version_info >= (3, 13, 0):\n",
1462+
" sys.exit(0)"
1463+
]
1464+
},
14511465
{
14521466
"cell_type": "markdown",
14531467
"metadata": {

notebooks/location/regionalized.ipynb

+14
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,20 @@
13391339
"# Using the Remote Functions"
13401340
]
13411341
},
1342+
{
1343+
"cell_type": "code",
1344+
"execution_count": null,
1345+
"metadata": {},
1346+
"outputs": [],
1347+
"source": [
1348+
"import sys\n",
1349+
"\n",
1350+
"# Python 3.13 is not yet a supported runtime for remote functions.\n",
1351+
"# See: https://cloud.google.com/functions/docs/runtime-support#python for the supported runtimes.\n",
1352+
"if sys.version_info >= (3, 13, 0):\n",
1353+
" sys.exit(0)"
1354+
]
1355+
},
13421356
{
13431357
"attachments": {},
13441358
"cell_type": "markdown",

notebooks/remote_functions/remote_function.ipynb

+15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
{
22
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"id": "bcff4fc4",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"import sys\n",
11+
"\n",
12+
"# Python 3.13 is not yet a supported runtime for remote functions.\n",
13+
"# See: https://cloud.google.com/functions/docs/runtime-support#python for the supported runtimes.\n",
14+
"if sys.version_info >= (3, 13, 0):\n",
15+
" sys.exit(0)"
16+
]
17+
},
318
{
419
"cell_type": "code",
520
"execution_count": 19,

notebooks/remote_functions/remote_function_usecases.ipynb

+14
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@
2121
"# limitations under the License."
2222
]
2323
},
24+
{
25+
"cell_type": "code",
26+
"execution_count": null,
27+
"metadata": {},
28+
"outputs": [],
29+
"source": [
30+
"import sys\n",
31+
"\n",
32+
"# Python 3.13 is not yet a supported runtime for remote functions.\n",
33+
"# See: https://cloud.google.com/functions/docs/runtime-support#python for the supported runtimes.\n",
34+
"if sys.version_info >= (3, 13, 0):\n",
35+
" sys.exit(0)"
36+
]
37+
},
2438
{
2539
"cell_type": "markdown",
2640
"metadata": {},

notebooks/remote_functions/remote_function_vertex_claude_model.ipynb

+14
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@
2828
"</table>"
2929
]
3030
},
31+
{
32+
"cell_type": "code",
33+
"execution_count": null,
34+
"metadata": {},
35+
"outputs": [],
36+
"source": [
37+
"import sys\n",
38+
"\n",
39+
"# Python 3.13 is not yet a supported runtime for remote functions.\n",
40+
"# See: https://cloud.google.com/functions/docs/runtime-support#python for the supported runtimes.\n",
41+
"if sys.version_info >= (3, 13, 0):\n",
42+
" sys.exit(0)"
43+
]
44+
},
3145
{
3246
"cell_type": "markdown",
3347
"metadata": {},

noxfile.py

+42-28
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,16 @@
2424
import shutil
2525
import time
2626
from typing import Dict, List
27-
import warnings
2827

2928
import nox
3029
import nox.sessions
3130

3231
BLACK_VERSION = "black==22.3.0"
3332
ISORT_VERSION = "isort==5.12.0"
3433

34+
# TODO: switch to 3.13 once remote functions / cloud run adds a runtime for it (internal issue 333742751)
35+
LATEST_FULLY_SUPPORTED_PYTHON = "3.12"
36+
3537
# pytest-retry is not yet compatible with pytest 8.x.
3638
# https://github.com/str0zzapreti/pytest-retry/issues/32
3739
PYTEST_VERSION = "pytest<8.0.0dev"
@@ -47,7 +49,7 @@
4749

4850
DEFAULT_PYTHON_VERSION = "3.10"
4951

50-
UNIT_TEST_PYTHON_VERSIONS = ["3.9", "3.10", "3.11", "3.12"]
52+
UNIT_TEST_PYTHON_VERSIONS = ["3.9", "3.10", "3.11", "3.12", "3.13"]
5153
UNIT_TEST_STANDARD_DEPENDENCIES = [
5254
"mock",
5355
"asyncmock",
@@ -57,15 +59,14 @@
5759
"pytest-asyncio",
5860
"pytest-mock",
5961
]
60-
UNIT_TEST_EXTERNAL_DEPENDENCIES: List[str] = []
6162
UNIT_TEST_LOCAL_DEPENDENCIES: List[str] = []
6263
UNIT_TEST_DEPENDENCIES: List[str] = []
6364
UNIT_TEST_EXTRAS: List[str] = []
6465
UNIT_TEST_EXTRAS_BY_PYTHON: Dict[str, List[str]] = {"3.12": ["polars"]}
6566

6667
# There are 4 different ibis-framework 9.x versions we want to test against.
6768
# 3.10 is needed for Windows tests.
68-
SYSTEM_TEST_PYTHON_VERSIONS = ["3.9", "3.10", "3.11", "3.12"]
69+
SYSTEM_TEST_PYTHON_VERSIONS = ["3.9", "3.10", "3.12", "3.13"]
6970
SYSTEM_TEST_STANDARD_DEPENDENCIES = [
7071
"jinja2",
7172
"mock",
@@ -169,14 +170,6 @@ def install_unittest_dependencies(session, install_test_extra, *constraints):
169170
standard_deps = UNIT_TEST_STANDARD_DEPENDENCIES + UNIT_TEST_DEPENDENCIES
170171
session.install(*standard_deps, *constraints)
171172

172-
if UNIT_TEST_EXTERNAL_DEPENDENCIES:
173-
msg = (
174-
"'unit_test_external_dependencies' is deprecated. Instead, please "
175-
"use 'unit_test_dependencies' or 'unit_test_local_dependencies'."
176-
)
177-
warnings.warn(msg, DeprecationWarning)
178-
session.install(*UNIT_TEST_EXTERNAL_DEPENDENCIES, *constraints)
179-
180173
if UNIT_TEST_LOCAL_DEPENDENCIES:
181174
session.install(*UNIT_TEST_LOCAL_DEPENDENCIES, *constraints)
182175

@@ -375,7 +368,7 @@ def system(session: nox.sessions.Session):
375368
)
376369

377370

378-
@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS[-1])
371+
@nox.session(python=LATEST_FULLY_SUPPORTED_PYTHON)
379372
def system_noextras(session: nox.sessions.Session):
380373
"""Run the system test suite."""
381374
run_system(
@@ -386,7 +379,7 @@ def system_noextras(session: nox.sessions.Session):
386379
)
387380

388381

389-
@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS[-1])
382+
@nox.session(python=LATEST_FULLY_SUPPORTED_PYTHON)
390383
def doctest(session: nox.sessions.Session):
391384
"""Run the system test suite."""
392385
run_system(
@@ -762,27 +755,48 @@ def notebook(session: nox.Session):
762755
"notebooks/apps/synthetic_data_generation.ipynb",
763756
]
764757

758+
# TODO: remove exception for Python 3.13 cloud run adds a runtime for it (internal issue 333742751)
759+
# TODO: remove exception for Python 3.13 if nbmake adds support for
760+
# sys.exit(0) or pytest.skip(...).
761+
# See: https://github.com/treebeardtech/nbmake/issues/134
762+
if session.python == "3.13":
763+
denylist.extend(
764+
[
765+
"notebooks/getting_started/getting_started_bq_dataframes.ipynb",
766+
"notebooks/remote_functions/remote_function_usecases.ipynb",
767+
"notebooks/remote_functions/remote_function_vertex_claude_model.ipynb",
768+
"notebooks/remote_functions/remote_function.ipynb",
769+
]
770+
)
771+
765772
# Convert each Path notebook object to a string using a list comprehension.
766773
notebooks = [str(nb) for nb in notebooks_list]
767774

768775
# Remove tests that we choose not to test.
769776
notebooks = list(filter(lambda nb: nb not in denylist, notebooks))
770777

771778
# Regionalized notebooks
772-
notebooks_reg = {
773-
"regionalized.ipynb": [
774-
"asia-southeast1",
775-
"eu",
776-
"europe-west4",
777-
"southamerica-west1",
778-
"us",
779-
"us-central1",
780-
]
781-
}
782-
notebooks_reg = {
783-
os.path.join("notebooks/location", nb): regions
784-
for nb, regions in notebooks_reg.items()
785-
}
779+
# TODO: remove exception for Python 3.13 cloud run adds a runtime for it (internal issue 333742751)
780+
# TODO: remove exception for Python 3.13 if nbmake adds support for
781+
# sys.exit(0) or pytest.skip(...).
782+
# See: https://github.com/treebeardtech/nbmake/issues/134
783+
if session.python == "3.13":
784+
notebooks_reg = {}
785+
else:
786+
notebooks_reg = {
787+
"regionalized.ipynb": [
788+
"asia-southeast1",
789+
"eu",
790+
"europe-west4",
791+
"southamerica-west1",
792+
"us",
793+
"us-central1",
794+
]
795+
}
796+
notebooks_reg = {
797+
os.path.join("notebooks/location", nb): regions
798+
for nb, regions in notebooks_reg.items()
799+
}
786800

787801
# The pytest --nbmake exits silently with "no tests ran" message if
788802
# one of the notebook paths supplied does not exist. Let's make sure that

owlbot.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
# ----------------------------------------------------------------------------
3232
templated_files = common.py_library(
3333
default_python_version="3.10",
34-
unit_test_python_versions=["3.9", "3.10", "3.11", "3.12"],
35-
system_test_python_versions=["3.9", "3.11", "3.12"],
34+
unit_test_python_versions=["3.9", "3.10", "3.11", "3.12", "3.13"],
35+
system_test_python_versions=["3.9", "3.11", "3.12", "3.13"],
3636
cov_level=35,
3737
intersphinx_dependencies={
3838
"pandas": "https://pandas.pydata.org/pandas-docs/stable/",

scripts/test_publish_api_coverage.py

+8
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ def api_coverage_df():
2525
return publish_api_coverage.build_api_coverage_table("my_bf_ver", "my_release_ver")
2626

2727

28+
@pytest.mark.skipif(
29+
sys.version_info >= (3, 13),
30+
reason="Issues with installing sklearn for this test in python 3.13",
31+
)
2832
def test_api_coverage_produces_expected_schema(api_coverage_df):
2933
if sys.version.split(".")[:2] == ["3", "9"]:
3034
pytest.skip(
@@ -54,6 +58,10 @@ def test_api_coverage_produces_expected_schema(api_coverage_df):
5458
)
5559

5660

61+
@pytest.mark.skipif(
62+
sys.version_info >= (3, 13),
63+
reason="Issues with installing sklearn for this test in python 3.13",
64+
)
5765
def test_api_coverage_produces_missing_parameters(api_coverage_df):
5866
"""Make sure at least some functions have reported missing parameters."""
5967
assert (api_coverage_df["missing_parameters"].str.len() > 0).any()

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
"Programming Language :: Python :: 3.10",
127127
"Programming Language :: Python :: 3.11",
128128
"Programming Language :: Python :: 3.12",
129+
"Programming Language :: Python :: 3.13",
129130
"Operating System :: OS Independent",
130131
"Topic :: Internet",
131132
],

tests/system/large/test_remote_function.py

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import math # must keep this at top level to test udf referring global import
1919
import os.path
2020
import shutil
21+
import sys
2122
import tempfile
2223
import textwrap
2324

@@ -47,6 +48,12 @@
4748
_team_euler = "Team Euler"
4849

4950

51+
pytestmark = pytest.mark.skipif(
52+
sys.version_info >= (3, 13),
53+
reason="Runtime 'python313' is not supported yet. Skip for now.",
54+
)
55+
56+
5057
def cleanup_remote_function_assets(
5158
bigquery_client, cloudfunctions_client, remote_udf, ignore_failures=True
5259
):

0 commit comments

Comments
 (0)