From b3feb8ca26af196abf6faaa81cb583675587ba50 Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Wed, 20 May 2020 14:19:56 -0400 Subject: [PATCH 1/3] Explicitly list third party modules for isort Not doing this was causing some inconsistencies and preventing commits. --- pyproject.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index cdc7b30c..c0b6c4d3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,16 @@ skip_covered = true atomic=true force_grid_wrap=0 include_trailing_comma=true +known_first_party = ["backports.zoneinfo"] +known_third_party=[ + "click", + "dateutil", + "hypothesis", + "pint", + "pytest", + "pytz", + "requests", +] multi_line_output=3 not_skip="__init__.py" use_parentheses=true From 2e13fd7214269165fbc82b8c29ad16be25939ef0 Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Mon, 18 May 2020 14:13:44 -0400 Subject: [PATCH 2/3] Move module into backports namespace This will make it somewhat more difficult to keep the backport version in sync with the standard library version, but it is an important preparation for a PyPI release. --- MANIFEST.in | 2 +- docs/conf.py | 2 +- lib/zoneinfo_module.c | 9 +++++---- pyproject.toml | 1 - scripts/benchmark.py | 6 +++--- scripts/update_test_data.py | 2 +- setup.cfg | 4 ++-- setup.py | 2 +- src/backports/__init__.py | 5 +++++ src/{ => backports}/zoneinfo/__init__.py | 0 src/{ => backports}/zoneinfo/__init__.pyi | 0 src/{ => backports}/zoneinfo/_common.py | 0 src/{ => backports}/zoneinfo/_tzpath.py | 0 src/{ => backports}/zoneinfo/_version.py | 0 src/{ => backports}/zoneinfo/_zoneinfo.py | 2 +- src/{ => backports}/zoneinfo/py.typed | 0 tests/_support.py | 14 ++++++++------ tests/test_zoneinfo_property.py | 3 ++- tests/typing_example.py | 2 +- tox.ini | 4 ++-- 20 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 src/backports/__init__.py rename src/{ => backports}/zoneinfo/__init__.py (100%) rename src/{ => backports}/zoneinfo/__init__.pyi (100%) rename src/{ => backports}/zoneinfo/_common.py (100%) rename src/{ => backports}/zoneinfo/_tzpath.py (100%) rename src/{ => backports}/zoneinfo/_version.py (100%) rename src/{ => backports}/zoneinfo/_zoneinfo.py (99%) rename src/{ => backports}/zoneinfo/py.typed (100%) diff --git a/MANIFEST.in b/MANIFEST.in index 28aa6e59..132b66eb 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,7 +3,7 @@ recursive-include licenses * graft .github # Stubs -include src/zoneinfo/py.typed +include src/backports/zoneinfo/py.typed recursive-include src *.pyi # Tests diff --git a/docs/conf.py b/docs/conf.py index 5c467169..75753678 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,7 +6,7 @@ # -- Project information ----------------------------------------------------- -project = "zoneinfo" +project = "backports.zoneinfo" author = "Paul Ganssle" copyright = f"2020, {author}" diff --git a/lib/zoneinfo_module.c b/lib/zoneinfo_module.c index 2a98101f..46b1315b 100644 --- a/lib/zoneinfo_module.c +++ b/lib/zoneinfo_module.c @@ -2570,7 +2570,7 @@ static PyMemberDef zoneinfo_members[] = { static PyTypeObject PyZoneInfo_ZoneInfoType = { PyVarObject_HEAD_INIT(NULL, 0) // - .tp_name = "zoneinfo.ZoneInfo", + .tp_name = "backports.zoneinfo.ZoneInfo", .tp_basicsize = sizeof(PyZoneInfo_ZoneInfo), .tp_weaklistoffset = offsetof(PyZoneInfo_ZoneInfo, weakreflist), .tp_repr = (reprfunc)zoneinfo_repr, @@ -2628,7 +2628,8 @@ zoneinfomodule_exec(PyObject *m) PyModule_AddObject(m, "ZoneInfo", (PyObject *)&PyZoneInfo_ZoneInfoType); /* Populate imports */ - PyObject *_tzpath_module = PyImport_ImportModule("zoneinfo._tzpath"); + PyObject *_tzpath_module = + PyImport_ImportModule("backports.zoneinfo._tzpath"); if (_tzpath_module == NULL) { goto error; } @@ -2651,7 +2652,7 @@ zoneinfomodule_exec(PyObject *m) goto error; } - _common_mod = PyImport_ImportModule("zoneinfo._common"); + _common_mod = PyImport_ImportModule("backports.zoneinfo._common"); if (_common_mod == NULL) { goto error; } @@ -2681,7 +2682,7 @@ static PyModuleDef_Slot zoneinfomodule_slots[] = { static struct PyModuleDef zoneinfomodule = { PyModuleDef_HEAD_INIT, - .m_name = "zoneinfo._czoneinfo", + .m_name = "backports.zoneinfo._czoneinfo", .m_doc = "C implementation of the zoneinfo module", .m_size = 0, .m_methods = module_methods, diff --git a/pyproject.toml b/pyproject.toml index c0b6c4d3..0d155b0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,6 @@ build-backend = "setuptools.build_meta" line-length = 80 [tool.coverage.run] -source = ["zoneinfo"] omit = ["tests/typing_example.py"] [tool.coverage.paths] diff --git a/scripts/benchmark.py b/scripts/benchmark.py index 0b18d922..27c8c713 100644 --- a/scripts/benchmark.py +++ b/scripts/benchmark.py @@ -5,12 +5,12 @@ from datetime import datetime, timedelta, timezone import click - import pint import pytz from dateutil import tz -from zoneinfo import ZoneInfo -from zoneinfo._zoneinfo import ZoneInfo as PyZoneInfo + +from backports.zoneinfo import ZoneInfo +from backports.zoneinfo._zoneinfo import ZoneInfo as PyZoneInfo _PINT_REGISTRY = pint.UnitRegistry() S = _PINT_REGISTRY.s diff --git a/scripts/update_test_data.py b/scripts/update_test_data.py index 23cf01fa..03529ddd 100644 --- a/scripts/update_test_data.py +++ b/scripts/update_test_data.py @@ -19,7 +19,7 @@ import textwrap import typing -import zoneinfo +import backports.zoneinfo as zoneinfo KEYS = [ "Africa/Abidjan", diff --git a/setup.cfg b/setup.cfg index ab3f9ab6..7403e925 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] -name = zoneinfo -version = attr:zoneinfo._version.__version__ +name = backports.zoneinfo +version = attr:backports.zoneinfo._version.__version__ description = Backport of the standard library zoneinfo module long_description = file: README.md long_description_content_type = text/markdown diff --git a/setup.py b/setup.py index da104f49..af05347e 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import Extension c_extension = Extension( - "zoneinfo._czoneinfo", sources=["lib/zoneinfo_module.c"], + "backports.zoneinfo._czoneinfo", sources=["lib/zoneinfo_module.c"], ) setuptools.setup(ext_modules=[c_extension]) diff --git a/src/backports/__init__.py b/src/backports/__init__.py new file mode 100644 index 00000000..b09491b2 --- /dev/null +++ b/src/backports/__init__.py @@ -0,0 +1,5 @@ +# A Python "namespace package" http://www.python.org/dev/peps/pep-0382/ +# This always goes inside of a namespace package's __init__.py +from pkgutil import extend_path + +__path__ = extend_path(__path__, __name__) # type: ignore diff --git a/src/zoneinfo/__init__.py b/src/backports/zoneinfo/__init__.py similarity index 100% rename from src/zoneinfo/__init__.py rename to src/backports/zoneinfo/__init__.py diff --git a/src/zoneinfo/__init__.pyi b/src/backports/zoneinfo/__init__.pyi similarity index 100% rename from src/zoneinfo/__init__.pyi rename to src/backports/zoneinfo/__init__.pyi diff --git a/src/zoneinfo/_common.py b/src/backports/zoneinfo/_common.py similarity index 100% rename from src/zoneinfo/_common.py rename to src/backports/zoneinfo/_common.py diff --git a/src/zoneinfo/_tzpath.py b/src/backports/zoneinfo/_tzpath.py similarity index 100% rename from src/zoneinfo/_tzpath.py rename to src/backports/zoneinfo/_tzpath.py diff --git a/src/zoneinfo/_version.py b/src/backports/zoneinfo/_version.py similarity index 100% rename from src/zoneinfo/_version.py rename to src/backports/zoneinfo/_version.py diff --git a/src/zoneinfo/_zoneinfo.py b/src/backports/zoneinfo/_zoneinfo.py similarity index 99% rename from src/zoneinfo/_zoneinfo.py rename to src/backports/zoneinfo/_zoneinfo.py index 69133ae8..082bd7ee 100644 --- a/src/zoneinfo/_zoneinfo.py +++ b/src/backports/zoneinfo/_zoneinfo.py @@ -34,7 +34,7 @@ class ZoneInfo(tzinfo): _strong_cache_size = 8 _strong_cache = collections.OrderedDict() _weak_cache = weakref.WeakValueDictionary() - __module__ = "zoneinfo" + __module__ = "backports.zoneinfo" def __init_subclass__(cls): cls._strong_cache = collections.OrderedDict() diff --git a/src/zoneinfo/py.typed b/src/backports/zoneinfo/py.typed similarity index 100% rename from src/zoneinfo/py.typed rename to src/backports/zoneinfo/py.typed diff --git a/tests/_support.py b/tests/_support.py index 6c85afd0..f5d389bc 100644 --- a/tests/_support.py +++ b/tests/_support.py @@ -36,10 +36,12 @@ def get_modules(): # The standard import_fresh_module approach seems to be somewhat buggy # when it comes to C imports, so in the short term, we will do a little # module surgery to test this. - py_module, c_module = (import_fresh_module("zoneinfo") for _ in range(2)) + py_module, c_module = ( + import_fresh_module("backports.zoneinfo") for _ in range(2) + ) - from zoneinfo import _zoneinfo as py_zoneinfo - from zoneinfo import _czoneinfo as c_zoneinfo + from backports.zoneinfo import _zoneinfo as py_zoneinfo + from backports.zoneinfo import _czoneinfo as c_zoneinfo py_module.ZoneInfo = py_zoneinfo.ZoneInfo c_module.ZoneInfo = c_zoneinfo.ZoneInfo @@ -57,11 +59,11 @@ def set_zoneinfo_module(module): """ NOT_PRESENT = object() - old_zoneinfo = sys.modules.get("zoneinfo", NOT_PRESENT) - sys.modules["zoneinfo"] = module + old_zoneinfo = sys.modules.get("backports.zoneinfo", NOT_PRESENT) + sys.modules["backports.zoneinfo"] = module yield if old_zoneinfo is not NOT_PRESENT: - sys.modules["zoneinfo"] = old_zoneinfo + sys.modules["backports.zoneinfo"] = old_zoneinfo class ZoneInfoTestBase(unittest.TestCase): diff --git a/tests/test_zoneinfo_property.py b/tests/test_zoneinfo_property.py index 617aea69..ae7f81a1 100644 --- a/tests/test_zoneinfo_property.py +++ b/tests/test_zoneinfo_property.py @@ -7,7 +7,8 @@ import hypothesis import pytest -import zoneinfo + +from backports import zoneinfo from . import _support as test_support from ._support import ZoneInfoTestBase diff --git a/tests/typing_example.py b/tests/typing_example.py index 16165a19..13f571b1 100644 --- a/tests/typing_example.py +++ b/tests/typing_example.py @@ -7,7 +7,7 @@ from pathlib import Path from typing import Callable, Optional, Sequence, Set, Tuple -import zoneinfo +import backports.zoneinfo as zoneinfo REGISTERED_FUNCTIONS = [] diff --git a/tox.ini b/tox.ini index d9edc265..87c5b258 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,7 @@ setenv = COVERAGE_FILE={toxworkdir}/.coverage/.coverage.{envname} CFLAGS={env:CFLAGS:-UNDEBUG} commands = - pytest {toxinidir} {posargs: --cov=zoneinfo --cov=tests} + pytest {toxinidir} {posargs: --cov=backports.zoneinfo --cov=tests} # This should probably be integrated into the main testenv as an option if such # a thing is possible, but because it's more important that it runs on CI and @@ -115,7 +115,7 @@ description = Run mypy on the testing example deps = mypy commands = - mypy src/zoneinfo/__init__.pyi + mypy src/backports/zoneinfo/__init__.pyi mypy tests/typing_example.py mypy scripts/update_test_data.py From e06878f74f0c1931574c049c1b97e50d8f4615cb Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Mon, 18 May 2020 14:23:02 -0400 Subject: [PATCH 3/3] Update package metadata to reflect backport The previous package metadata was assuming that the module was itself in the standard library, but it is preferable for this to refer to the backport itself. --- setup.cfg | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index 7403e925..145be30f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,7 +4,7 @@ version = attr:backports.zoneinfo._version.__version__ description = Backport of the standard library zoneinfo module long_description = file: README.md long_description_content_type = text/markdown -url = https://github.com/python/cpython +url = https://github.com/pganssle/zoneinfo author = Python Software Foundation author_email = datetime-sig@python.org license = Apache-2.0 @@ -20,8 +20,9 @@ classifiers = Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3.8 project_urls = - Bug Reports = https://bugs.python.org - Source = https://github.com/python/cpython + Source = https://github.com/pganssle/zoneinfo + Documentation = https://zoneinfo.readthedocs.io/en/latest/ + Bug Reports = https://github.com/pganssle/zoneinfo/issues [options] packages = find: