From 47628103fbc07ed71112606d2afa1caf7b92f975 Mon Sep 17 00:00:00 2001 From: Steve Canny Date: Wed, 1 May 2024 11:10:48 -0700 Subject: [PATCH] Python 3.12 fixes --- features/steps/coreprops.py | 18 +++++++++--------- pyproject.toml | 11 +++++++++++ pyrightconfig.json | 21 --------------------- src/docx/opc/parts/coreprops.py | 2 +- src/docx/oxml/coreprops.py | 4 ++-- tests/opc/parts/test_coreprops.py | 9 ++++++--- tests/opc/test_coreprops.py | 4 ++-- tox.ini | 2 +- 8 files changed, 32 insertions(+), 39 deletions(-) delete mode 100644 pyrightconfig.json diff --git a/features/steps/coreprops.py b/features/steps/coreprops.py index 0d4e55eb7..90467fb67 100644 --- a/features/steps/coreprops.py +++ b/features/steps/coreprops.py @@ -1,6 +1,6 @@ """Gherkin step implementations for core properties-related features.""" -from datetime import datetime, timedelta +import datetime as dt from behave import given, then, when from behave.runner import Context @@ -38,13 +38,13 @@ def when_I_assign_new_values_to_the_properties(context: Context): ("category", "Category"), ("comments", "Description"), ("content_status", "Content Status"), - ("created", datetime(2013, 6, 15, 12, 34, 56)), + ("created", dt.datetime(2013, 6, 15, 12, 34, 56, tzinfo=dt.timezone.utc)), ("identifier", "Identifier"), ("keywords", "key; word; keyword"), ("language", "Language"), ("last_modified_by", "Last Modified By"), - ("last_printed", datetime(2013, 6, 15, 12, 34, 56)), - ("modified", datetime(2013, 6, 15, 12, 34, 56)), + ("last_printed", dt.datetime(2013, 6, 15, 12, 34, 56, tzinfo=dt.timezone.utc)), + ("modified", dt.datetime(2013, 6, 15, 12, 34, 56, tzinfo=dt.timezone.utc)), ("revision", 9), ("subject", "Subject"), ("title", "Title"), @@ -66,8 +66,8 @@ def then_a_core_properties_part_with_default_values_is_added(context: Context): assert core_properties.revision == 1 # core_properties.modified only stores time with seconds resolution, so # comparison needs to be a little loose (within two seconds) - modified_timedelta = datetime.utcnow() - core_properties.modified - max_expected_timedelta = timedelta(seconds=2) + modified_timedelta = dt.datetime.now(dt.timezone.utc) - core_properties.modified + max_expected_timedelta = dt.timedelta(seconds=2) assert modified_timedelta < max_expected_timedelta @@ -85,13 +85,13 @@ def then_the_core_property_values_match_the_known_values(context: Context): ("category", "Category"), ("comments", "Description"), ("content_status", "Content Status"), - ("created", datetime(2014, 12, 13, 22, 2, 0)), + ("created", dt.datetime(2014, 12, 13, 22, 2, 0, tzinfo=dt.timezone.utc)), ("identifier", "Identifier"), ("keywords", "key; word; keyword"), ("language", "Language"), ("last_modified_by", "Steve Canny"), - ("last_printed", datetime(2014, 12, 13, 22, 2, 42)), - ("modified", datetime(2014, 12, 13, 22, 6, 0)), + ("last_printed", dt.datetime(2014, 12, 13, 22, 2, 42, tzinfo=dt.timezone.utc)), + ("modified", dt.datetime(2014, 12, 13, 22, 6, 0, tzinfo=dt.timezone.utc)), ("revision", 2), ("subject", "Subject"), ("title", "Title"), diff --git a/pyproject.toml b/pyproject.toml index 8d483f00b..91bac83d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,17 @@ Repository = "https://github.com/python-openxml/python-docx" line-length = 100 target-version = ["py37", "py38", "py39", "py310", "py311"] +[tool.pyright] +include = ["src/docx", "tests"] +pythonPlatform = "All" +pythonVersion = "3.8" +reportImportCycles = true +reportUnnecessaryCast = true +reportUnnecessaryTypeIgnoreComment = true +stubPath = "./typings" +typeCheckingMode = "strict" +verboseOutput = true + [tool.pytest.ini_options] filterwarnings = [ # -- exit on any warning not explicitly ignored here -- diff --git a/pyrightconfig.json b/pyrightconfig.json deleted file mode 100644 index 21afeb97b..000000000 --- a/pyrightconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "exclude": [ - "**/__pycache__", - "**/.*" - ], - "ignore": [ - ], - "include": [ - "src/docx", - "tests" - ], - "pythonPlatform": "All", - "pythonVersion": "3.7", - "reportImportCycles": true, - "reportUnnecessaryCast": true, - "reportUnnecessaryTypeIgnoreComment": true, - "stubPath": "./typings", - "typeCheckingMode": "strict", - "useLibraryCodeForTypes": true, - "verboseOutput": true -} diff --git a/src/docx/opc/parts/coreprops.py b/src/docx/opc/parts/coreprops.py index 0d818f18d..fda011218 100644 --- a/src/docx/opc/parts/coreprops.py +++ b/src/docx/opc/parts/coreprops.py @@ -31,7 +31,7 @@ def default(cls, package: OpcPackage): core_properties.title = "Word Document" core_properties.last_modified_by = "python-docx" core_properties.revision = 1 - core_properties.modified = dt.datetime.utcnow() + core_properties.modified = dt.datetime.now(dt.timezone.utc) return core_properties_part @property diff --git a/src/docx/oxml/coreprops.py b/src/docx/oxml/coreprops.py index 93f8890c7..8ba9ff42e 100644 --- a/src/docx/oxml/coreprops.py +++ b/src/docx/oxml/coreprops.py @@ -254,8 +254,8 @@ def _parse_W3CDTF_to_datetime(cls, w3cdtf_str: str) -> dt.datetime: tmpl = "could not parse W3CDTF datetime string '%s'" raise ValueError(tmpl % w3cdtf_str) if len(offset_str) == 6: - return cls._offset_dt(dt_, offset_str) - return dt_ + dt_ = cls._offset_dt(dt_, offset_str) + return dt_.replace(tzinfo=dt.timezone.utc) def _set_element_datetime(self, prop_name: str, value: dt.datetime): """Set date/time value of child element having `prop_name` to `value`.""" diff --git a/tests/opc/parts/test_coreprops.py b/tests/opc/parts/test_coreprops.py index 5bcf49651..b754d2d7e 100644 --- a/tests/opc/parts/test_coreprops.py +++ b/tests/opc/parts/test_coreprops.py @@ -1,6 +1,8 @@ """Unit test suite for the docx.opc.parts.coreprops module.""" -from datetime import datetime, timedelta +from __future__ import annotations + +import datetime as dt import pytest @@ -35,8 +37,9 @@ def it_can_create_a_default_core_properties_part(self, package_: Mock): assert core_properties.title == "Word Document" assert core_properties.last_modified_by == "python-docx" assert core_properties.revision == 1 - delta = datetime.utcnow() - core_properties.modified - max_expected_delta = timedelta(seconds=2) + assert core_properties.modified is not None + delta = dt.datetime.now(dt.timezone.utc) - core_properties.modified + max_expected_delta = dt.timedelta(seconds=2) assert delta < max_expected_delta # fixtures --------------------------------------------- diff --git a/tests/opc/test_coreprops.py b/tests/opc/test_coreprops.py index 0214cdbdf..5d9743397 100644 --- a/tests/opc/test_coreprops.py +++ b/tests/opc/test_coreprops.py @@ -68,8 +68,8 @@ def it_can_change_the_string_property_values(self, prop_name: str, tagname: str, @pytest.mark.parametrize( ("prop_name", "expected_datetime"), [ - ("created", dt.datetime(2012, 11, 17, 16, 37, 40)), - ("last_printed", dt.datetime(2014, 6, 4, 4, 28)), + ("created", dt.datetime(2012, 11, 17, 16, 37, 40, tzinfo=dt.timezone.utc)), + ("last_printed", dt.datetime(2014, 6, 4, 4, 28, tzinfo=dt.timezone.utc)), ("modified", None), ], ) diff --git a/tox.ini b/tox.ini index f8595ba45..37acaa5fa 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py38, py39, py310, py311 +envlist = py38, py39, py310, py311, py312 [testenv] deps = -rrequirements-test.txt