diff --git a/.github/workflows/Bench.yml b/.github/workflows/Bench.yml index 376305c..ec4cae4 100644 --- a/.github/workflows/Bench.yml +++ b/.github/workflows/Bench.yml @@ -37,4 +37,4 @@ jobs: --token "${{ secrets.BENCHER_API_TOKEN }}" \ --adapter python_pytest \ --err \ - "pytest --benchmark-json results.json tests/test_bench.py" + "pytest --benchmark-json results.json --benchmark-warmup=on --benchmark-warmup-iterations=100 tests/test_bench.py" diff --git a/.github/workflows/CodSpeed.yml b/.github/workflows/CodSpeed.yml index 5795eb8..a54d5fe 100644 --- a/.github/workflows/CodSpeed.yml +++ b/.github/workflows/CodSpeed.yml @@ -33,7 +33,7 @@ jobs: - name: Run benchmarks uses: CodSpeedHQ/action@v3 with: - run: uv run pytest tests/ --codspeed + run: uv run pytest --benchmark-warmup=on --benchmark-warmup-iterations=100 --codspeed tests/test_bench.py - name: Minimize uv cache run: uv cache prune --ci diff --git a/README.md b/README.md index e4f96cb..bf3df17 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ > borders. > 2. Rust use lazy init, so first calling will be a little slow. > 3. Use about 40MB memory. -> 4. It's tested under Python 3.9+ but support 3.8+(noqa). +> 4. It's tested under Python 3.9+. > 5. Try it online: ## Usage @@ -48,25 +48,25 @@ conda install -c conda-forge tzfpy ## Performance Benchmark runs under -[`v0.15.3`](https://github.com/ringsaturn/tzfpy/releases/tag/v0.15.3) on my +[`v0.16.0`](https://github.com/ringsaturn/tzfpy/releases/tag/v0.16.0) on my MacBook Pro with Apple M3 Max. ```bash -pytest tests/test_bench.py +pytest --benchmark-warmup=on --benchmark-warmup-iterations=100 tests/test_bench.py ``` ``` ------------------------------------------------------------- benchmark: 1 tests ------------------------------------------------------------ -Name (time in ns) Min Max Mean StdDev Median IQR Outliers OPS (Kops/s) Rounds Iterations --------------------------------------------------------------------------------------------------------------------------------------------- -test_tzfpy_random_cities 837.4918 11,183.2982 1,973.3456 833.9543 1,820.9103 1,066.7020 6422;511 506.7536 20000 10 --------------------------------------------------------------------------------------------------------------------------------------------- +----------------------------------------------------------- benchmark: 1 tests ----------------------------------------------------------- +Name (time in ns) Min Max Mean StdDev Median IQR Outliers OPS (Kops/s) Rounds Iterations +------------------------------------------------------------------------------------------------------------------------------------------ +test_tzfpy_random_cities 699.9937 7,175.0022 1,562.1433 646.9249 1,441.6990 833.3940 13716;984 640.1461 41026 10 +------------------------------------------------------------------------------------------------------------------------------------------ Legend: Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile. OPS: Operations Per Second, computed as 1 / Mean -Results (1.95s): - 4 passed +Results (1.81s): + 1 passed ``` Or you can view more benchmark results on diff --git a/pyproject.toml b/pyproject.toml index c847b5c..339c5b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,12 +39,8 @@ Documentation = "https://github.com/ringsaturn/tzfpy" Issues = "https://github.com/ringsaturn/tzfpy/issues" "Source Code" = "https://github.com/ringsaturn/tzfpy" -[tool.maturin] -# "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so) -features = ["pyo3/extension-module"] - -[tool.uv] -dev-dependencies = [ +[dependency-groups] +dev = [ "ruff>=0.7.1", "citiespy>=0.6.5", "maturin>=1.7.4", @@ -56,3 +52,7 @@ dev-dependencies = [ "tzdata>=2024.2", "pytest-codspeed>=2.2.1", ] + +[tool.maturin] +# "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so) +features = ["pyo3/extension-module"] diff --git a/tests/test_basic.py b/tests/test_basic.py new file mode 100644 index 0000000..bbd625b --- /dev/null +++ b/tests/test_basic.py @@ -0,0 +1,18 @@ +from pytest import mark +from tzfpy import get_tz + + +@mark.parametrize( + "lng, lat, tz", + [ + (116.3883, 39.9289, "Asia/Shanghai"), + (120.347287, 22.598127, "Asia/Taipei"), + (2.3522, 48.8566, "Europe/Paris"), + (-0.1276, 51.5074, "Europe/London"), + (13.4049, 52.5200, "Europe/Berlin"), + (-74.0060, 40.7128, "America/New_York"), + (-118.2437, 34.0522, "America/Los_Angeles"), + ], +) +def test_get_tz(lng, lat, tz): + assert get_tz(lng, lat) == tz diff --git a/tests/test_compatibility.py b/tests/test_compatibility.py index 094bb9a..7a5aecf 100644 --- a/tests/test_compatibility.py +++ b/tests/test_compatibility.py @@ -1,30 +1,26 @@ -from unittest import TestCase, main - from citiespy import all_cities from tzfpy import data_version, get_tzs, timezonenames -class TestCompatibility(TestCase): - def test_with_pytz(self): - from pytz import timezone +def test_with_pytz(): + from pytz import timezone + + for tz in timezonenames(): + timezone(tz) - for tz in timezonenames(): - timezone(tz) - def test_with_tzdata(self): - from zoneinfo import ZoneInfo +def test_with_tzdata(): + from zoneinfo import ZoneInfo - for tz in timezonenames(): - ZoneInfo(tz) + for tz in timezonenames(): + ZoneInfo(tz) - def test_no_empty(self): - for city in all_cities(): - tznames = get_tzs(city.lng, city.lat) - self.assertTrue(len(tznames) != 0) - def test_version_support(self): - self.assertTrue(data_version() not in [None, ""]) +def test_no_empty(): + for city in all_cities(): + tznames = get_tzs(city.lng, city.lat) + assert len(tznames) != 0 -if __name__ == "__main___": - main() +def test_version_support(): + assert data_version() not in [None, ""] diff --git a/uv.lock b/uv.lock index d8c8684..01fd3cb 100644 --- a/uv.lock +++ b/uv.lock @@ -186,6 +186,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 }, ] +[[package]] +name = "importlib-metadata" +version = "8.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7", size = 55304 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", size = 26514 }, +] + [[package]] name = "iniconfig" version = "2.0.0" @@ -303,43 +315,45 @@ wheels = [ [[package]] name = "pytest-benchmark" -version = "4.0.0" +version = "5.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "py-cpuinfo" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/28/08/e6b0067efa9a1f2a1eb3043ecd8a0c48bfeb60d3255006dcc829d72d5da2/pytest-benchmark-4.0.0.tar.gz", hash = "sha256:fb0785b83efe599a6a956361c0691ae1dbb5318018561af10f3e915caa0048d1", size = 334641 } +sdist = { url = "https://files.pythonhosted.org/packages/39/d0/a8bd08d641b393db3be3819b03e2d9bb8760ca8479080a26a5f6e540e99c/pytest-benchmark-5.1.0.tar.gz", hash = "sha256:9ea661cdc292e8231f7cd4c10b0319e56a2118e2c09d9f50e1b3d150d2aca105", size = 337810 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/a1/3b70862b5b3f830f0422844f25a823d0470739d994466be9dbbbb414d85a/pytest_benchmark-4.0.0-py3-none-any.whl", hash = "sha256:fdb7db64e31c8b277dff9850d2a2556d8b60bcb0ea6524e36e28ffd7c87f71d6", size = 43951 }, + { url = "https://files.pythonhosted.org/packages/9e/d6/b41653199ea09d5969d4e385df9bbfd9a100f28ca7e824ce7c0a016e3053/pytest_benchmark-5.1.0-py3-none-any.whl", hash = "sha256:922de2dfa3033c227c96da942d1878191afa135a29485fb942e85dff1c592c89", size = 44259 }, ] [[package]] name = "pytest-codspeed" -version = "2.2.1" +version = "3.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi" }, { name = "filelock" }, + { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "pytest" }, + { name = "rich" }, { name = "setuptools", marker = "python_full_version >= '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/6a/ba0b067dba286443a04c9d32ff75ef3bc169617ee347d1a97972ada62665/pytest_codspeed-2.2.1.tar.gz", hash = "sha256:0adc24baf01c64a6ca0a0b83b3cd704351708997e09ec086b7776c32227d4e0a", size = 9163 } +sdist = { url = "https://files.pythonhosted.org/packages/ba/78/40e613268cce75b11cd35ea9fdc280fb648e2233fc4187c76112377b1869/pytest_codspeed-3.0.0.tar.gz", hash = "sha256:c5b80100ea32dd44079bb2db298288763eb8fe859eafa1650a8711bd2c32fd06", size = 12540 } wheels = [ - { url = "https://files.pythonhosted.org/packages/03/0b/e3541064afcf24ed54bcabfa6eb5f8083eb335d5c58c7b5b95bc31127f86/pytest_codspeed-2.2.1-py3-none-any.whl", hash = "sha256:aad08033015f3e6c8c14c8bf0eca475921a9b088e92c98b626bf8af8f516471e", size = 10126 }, + { url = "https://files.pythonhosted.org/packages/a6/79/fa067436033410ac16e5d14b61b1a5f355688930ca8c6a8c61a52b2cbe0a/pytest_codspeed-3.0.0-py3-none-any.whl", hash = "sha256:ab1b8cb9da72e0d394718333d1abc7bea38524e09fd4854bc70a91abbcdcb20e", size = 15640 }, ] [[package]] name = "pytest-cov" -version = "5.0.0" +version = "6.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/67/00efc8d11b630c56f15f4ad9c7f9223f1e5ec275aaae3fa9118c6a223ad2/pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857", size = 63042 } +sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/3a/af5b4fa5961d9a1e6237b530eb87dd04aea6eb83da09d2a4073d81b54ccf/pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652", size = 21990 }, + { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, ] [[package]] @@ -405,11 +419,11 @@ wheels = [ [[package]] name = "setuptools" -version = "75.2.0" +version = "75.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/07/37/b31be7e4b9f13b59cde9dcaeff112d401d49e0dc5b37ed4a9fc8fb12f409/setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec", size = 1350308 } +sdist = { url = "https://files.pythonhosted.org/packages/ed/22/a438e0caa4576f8c383fa4d35f1cc01655a46c75be358960d815bfbb12bd/setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686", size = 1351577 } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/2d/90165d51ecd38f9a02c6832198c13a4e48652485e2ccf863ebb942c531b6/setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8", size = 1249825 }, + { url = "https://files.pythonhosted.org/packages/90/12/282ee9bce8b58130cb762fbc9beabd531549952cac11fc56add11dcb7ea0/setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd", size = 1251070 }, ] [[package]] @@ -452,7 +466,7 @@ tzdata = [ { name = "tzdata" }, ] -[package.dev-dependencies] +[package.dependency-groups] dev = [ { name = "citiespy" }, { name = "maturin" }, @@ -472,7 +486,7 @@ requires-dist = [ { name = "tzdata", marker = "extra == 'tzdata'", specifier = ">=2024.2" }, ] -[package.metadata.requires-dev] +[package.metadata.dependency-groups] dev = [ { name = "citiespy", specifier = ">=0.6.5" }, { name = "maturin", specifier = ">=1.7.4" }, @@ -485,3 +499,12 @@ dev = [ { name = "ruff", specifier = ">=0.7.1" }, { name = "tzdata", specifier = ">=2024.2" }, ] + +[[package]] +name = "zipp" +version = "3.20.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29", size = 24199 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", size = 9200 }, +]