diff --git a/tests/emscripten_runner.js b/tests/emscripten_runner.js index 054a88380..c3c53834e 100644 --- a/tests/emscripten_runner.js +++ b/tests/emscripten_runner.js @@ -86,7 +86,7 @@ async function main() { FS.mkdir('/test_dir'); FS.mount(FS.filesystems.NODEFS, {root: path.join(root_dir, 'tests')}, '/test_dir'); FS.chdir('/test_dir'); - await pyodide.loadPackage(['micropip', 'pytest', 'pytz']); + await pyodide.loadPackage(['micropip', 'pytest']); // language=python errcode = await pyodide.runPythonAsync(` import micropip @@ -101,6 +101,7 @@ await micropip.install([ 'hypothesis', 'pytest-speed', 'pytest-mock', + 'tzdata', 'file:${wheel_path}', 'typing-extensions', ]) diff --git a/tests/requirements.txt b/tests/requirements.txt index 1a6c3c1d5..6fa5882c4 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,3 +1,4 @@ +backports.zoneinfo==0.2.1;python_version<"3.9" coverage==7.5.0 dirty-equals==0.7.1.post0 hypothesis==6.100.2 @@ -16,7 +17,7 @@ pytest-speed==0.3.5 pytest-mock==3.14.0 pytest-pretty==1.2.0 pytest-timeout==2.3.1 -pytz==2024.1 # numpy doesn't offer prebuilt wheels for all versions and platforms we test in CI e.g. aarch64 musllinux numpy==1.26.2; python_version >= "3.9" and python_version < "3.13" and implementation_name == "cpython" and platform_machine == 'x86_64' exceptiongroup==1.1; python_version < "3.11" +tzdata==2024.1 diff --git a/tests/validators/test_datetime.py b/tests/validators/test_datetime.py index 33ebb1250..9e1eef086 100644 --- a/tests/validators/test_datetime.py +++ b/tests/validators/test_datetime.py @@ -7,7 +7,12 @@ from typing import Dict import pytest -import pytz + +try: + import zoneinfo +except ImportError: + # TODO: can remove this once we drop support for python 3.8 + from backports import zoneinfo from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema @@ -81,8 +86,8 @@ def test_datetime_strict(input_value, expected): def test_keep_tz(): - tz = pytz.timezone('Europe/London') - dt = tz.localize(datetime(2022, 6, 14, 12, 13, 14)) + tz = zoneinfo.ZoneInfo('Europe/London') + dt = datetime(2022, 6, 14, 12, 13, 14, tzinfo=tz) v = SchemaValidator({'type': 'datetime'}) output = v.validate_python(dt) @@ -94,8 +99,8 @@ def test_keep_tz(): def test_keep_tz_bound(): - tz = pytz.timezone('Europe/London') - dt = tz.localize(datetime(2022, 6, 14, 12, 13, 14)) + tz = zoneinfo.ZoneInfo('Europe/London') + dt = datetime(2022, 6, 14, 12, 13, 14, tzinfo=tz) v = SchemaValidator({'type': 'datetime', 'gt': datetime(2022, 1, 1)}) output = v.validate_python(dt) @@ -106,7 +111,7 @@ def test_keep_tz_bound(): assert output.tzinfo.dst(datetime(2022, 1, 1)) == timedelta(0) with pytest.raises(ValidationError, match=r'Input should be greater than 2022-01-01T00:00:00 \[type=greater_than'): - v.validate_python(tz.localize(datetime(2021, 6, 14))) + v.validate_python(datetime(2021, 6, 14, tzinfo=tz)) @pytest.mark.parametrize( @@ -186,8 +191,8 @@ def test_custom_timezone_utc_repr(): def test_tz_comparison(): - tz = pytz.timezone('Europe/London') - uk_3pm = tz.localize(datetime(2022, 1, 1, 15, 0, 0)) + tz = zoneinfo.ZoneInfo('Europe/London') + uk_3pm = datetime(2022, 1, 1, 15, 0, 0, tzinfo=tz) # two times are the same instant, therefore le and ge are both ok v = SchemaValidator({'type': 'datetime', 'le': uk_3pm}).validate_python('2022-01-01T16:00:00+01:00') @@ -322,22 +327,22 @@ def test_datetime_past_timezone(): now_utc = datetime.now(timezone.utc) - timedelta(seconds=1) assert v.isinstance_python(now_utc) # "later" in the day - assert v.isinstance_python(now_utc.astimezone(pytz.timezone('Europe/Istanbul'))) + assert v.isinstance_python(now_utc.astimezone(zoneinfo.ZoneInfo('Europe/Istanbul'))) # "earlier" in the day - assert v.isinstance_python(now_utc.astimezone(pytz.timezone('America/Los_Angeles'))) + assert v.isinstance_python(now_utc.astimezone(zoneinfo.ZoneInfo('America/Los_Angeles'))) soon_utc = now_utc + timedelta(minutes=1) assert not v.isinstance_python(soon_utc) # "later" in the day - assert not v.isinstance_python(soon_utc.astimezone(pytz.timezone('Europe/Istanbul'))) + assert not v.isinstance_python(soon_utc.astimezone(zoneinfo.ZoneInfo('Europe/Istanbul'))) # "earlier" in the day - assert not v.isinstance_python(soon_utc.astimezone(pytz.timezone('America/Los_Angeles'))) + assert not v.isinstance_python(soon_utc.astimezone(zoneinfo.ZoneInfo('America/Los_Angeles'))) # input value is timezone naive, so we do a dumb comparison in these terms the istanbul time is later so fails # wile the LA time is earlier so passes - assert not v.isinstance_python(soon_utc.astimezone(pytz.timezone('Europe/Istanbul')).replace(tzinfo=None)) - assert v.isinstance_python(soon_utc.astimezone(pytz.timezone('America/Los_Angeles')).replace(tzinfo=None)) + assert not v.isinstance_python(soon_utc.astimezone(zoneinfo.ZoneInfo('Europe/Istanbul')).replace(tzinfo=None)) + assert v.isinstance_python(soon_utc.astimezone(zoneinfo.ZoneInfo('America/Los_Angeles')).replace(tzinfo=None)) @pytest.mark.parametrize( @@ -368,17 +373,17 @@ def test_datetime_future_timezone(): assert v.isinstance_python(soon_utc) # "later" in the day - assert v.isinstance_python(soon_utc.astimezone(pytz.timezone('Europe/Istanbul'))) + assert v.isinstance_python(soon_utc.astimezone(zoneinfo.ZoneInfo('Europe/Istanbul'))) # "earlier" in the day - assert v.isinstance_python(soon_utc.astimezone(pytz.timezone('America/Los_Angeles'))) + assert v.isinstance_python(soon_utc.astimezone(zoneinfo.ZoneInfo('America/Los_Angeles'))) past_utc = now_utc - timedelta(minutes=1) assert not v.isinstance_python(past_utc) # "later" in the day - assert not v.isinstance_python(past_utc.astimezone(pytz.timezone('Europe/Istanbul'))) + assert not v.isinstance_python(past_utc.astimezone(zoneinfo.ZoneInfo('Europe/Istanbul'))) # "earlier" in the day - assert not v.isinstance_python(past_utc.astimezone(pytz.timezone('America/Los_Angeles'))) + assert not v.isinstance_python(past_utc.astimezone(zoneinfo.ZoneInfo('America/Los_Angeles'))) def test_mock_utc_offset_8_hours(mocker): diff --git a/wasm-preview/run_tests.py b/wasm-preview/run_tests.py index 538c10e49..776f7a8e2 100644 --- a/wasm-preview/run_tests.py +++ b/wasm-preview/run_tests.py @@ -37,7 +37,7 @@ async def main(tests_zip: str, tag_name: str): print(f'Mounted {count} test files, installing dependencies...') - await micropip.install(['dirty-equals', 'hypothesis', 'pytest-speed', 'pytest-mock', pydantic_core_wheel]) + await micropip.install(['dirty-equals', 'hypothesis', 'pytest-speed', 'pytest-mock', pydantic_core_wheel, 'tzdata']) importlib.invalidate_caches() # print('installed packages:') diff --git a/wasm-preview/worker.js b/wasm-preview/worker.js index b769281ef..c6223ecbd 100644 --- a/wasm-preview/worker.js +++ b/wasm-preview/worker.js @@ -97,7 +97,7 @@ async function main() { setupStreams(FS, pyodide._module.TTY); FS.mkdir('/test_dir'); FS.chdir('/test_dir'); - await pyodide.loadPackage(['micropip', 'pytest', 'pytz', 'numpy']); + await pyodide.loadPackage(['micropip', 'pytest', 'numpy']); if (pydantic_core_version < '2.0.0') await pyodide.loadPackage(['typing-extensions']); await pyodide.runPythonAsync(python_code, {globals: pyodide.toPy({pydantic_core_version, tests_zip})}); post();