From 6a068e2acf2237c09f8e10d1d997243807f71f4a Mon Sep 17 00:00:00 2001 From: Shay Hill Date: Thu, 29 Jan 2026 10:42:47 -0600 Subject: [PATCH 1/4] feat: remove 3.9 support --- .github/workflows/pypi-project.yml | 2 +- .pre-commit-config.yaml | 4 ++-- docx2python/attribute_register.py | 4 ++-- docx2python/bullets_and_numbering.py | 4 +++- pyproject.toml | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pypi-project.yml b/.github/workflows/pypi-project.yml index cd9d4b6..d5c953b 100644 --- a/.github/workflows/pypi-project.yml +++ b/.github/workflows/pypi-project.yml @@ -17,7 +17,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] os: [ubuntu-latest, macos-latest, windows-latest] # if: startsWith(github.event.head_commit.message, 'bump:') == false steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af6f63f..0699fe8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -70,14 +70,14 @@ repos: rev: 25.1.0 hooks: - id: black - language_version: python3.9 + language_version: python3.10 args: ["--skip-magic-trailing-comma"] - repo: https://github.com/asottile/pyupgrade rev: v3.19.1 hooks: - args: - - --py39-plus + - --py310-plus id: pyupgrade - repo: https://github.com/Lucas-C/pre-commit-hooks diff --git a/docx2python/attribute_register.py b/docx2python/attribute_register.py index 34d93e7..e5012c0 100644 --- a/docx2python/attribute_register.py +++ b/docx2python/attribute_register.py @@ -16,12 +16,12 @@ import uuid import warnings from enum import Enum -from typing import TYPE_CHECKING, Callable, NamedTuple +from typing import TYPE_CHECKING, NamedTuple from lxml import etree if TYPE_CHECKING: - from collections.abc import Iterator + from collections.abc import Callable, Iterator from lxml.etree import _Element as EtreeElement # type: ignore diff --git a/docx2python/bullets_and_numbering.py b/docx2python/bullets_and_numbering.py index ffc6471..61c498e 100644 --- a/docx2python/bullets_and_numbering.py +++ b/docx2python/bullets_and_numbering.py @@ -19,12 +19,14 @@ import warnings from collections import defaultdict from contextlib import suppress -from typing import TYPE_CHECKING, Callable +from typing import TYPE_CHECKING from docx2python import numbering_formats as nums from docx2python.namespace import get_attrib_by_qn, iterfind_by_qn if TYPE_CHECKING: + from collections.abc import Callable + from lxml.etree import _Element as EtreeElement # type: ignore from docx2python.docx_context import NumIdAttrs diff --git a/pyproject.toml b/pyproject.toml index 92ba2fd..89f8b1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ description = "Extract content from docx files" authors = [{ name = "Shay Hill", email = "shay_public@hotmail.com" }] license = {text = "MIT"} readme = "README.md" -requires-python = ">=3.9.0" +requires-python = ">=3.10.0" dependencies = ["lxml", "paragraphs", "typing_extensions", "types-lxml"] [project.optional-dependencies] @@ -32,7 +32,7 @@ profile = "black" [tool.tox] legacy_tox_ini = """ [tox] -envlist = py{313,312,311,310,39} +envlist = py{314,313,312,311,310} [testenv] deps = pytest From a4015d659234ea76c93b084e36bbf3ec09b21792 Mon Sep 17 00:00:00 2001 From: Shay Hill Date: Thu, 29 Jan 2026 10:43:47 -0600 Subject: [PATCH 2/4] test: test Python 3.14 support From 4adf3a72dd192c4b26bdbfd149b516f0abc8adbf Mon Sep 17 00:00:00 2001 From: Shay Hill Date: Thu, 29 Jan 2026 11:06:06 -0600 Subject: [PATCH 3/4] chore: update pre-commit hooks Black formatter updates caused diffs in test files. --- .pre-commit-config.yaml | 17 +++++++------- tests/test_comments.py | 48 +++++++++++++-------------------------- tests/test_docx2python.py | 30 ++++++++---------------- tests/test_more_html.py | 22 +++++------------- tests/test_toc_support.py | 32 +++++++------------------- 5 files changed, 48 insertions(+), 101 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0699fe8..88a4ba2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ exclude: 'scripts/.*' repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-added-large-files - id: check-ast @@ -32,7 +32,6 @@ repos: - id: mixed-line-ending - id: requirements-txt-fixer - id: trailing-whitespace - - id: fix-encoding-pragma args: - --remove # - id: name-tests-test @@ -45,7 +44,7 @@ repos: # files: .pre-commit-config.yaml - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.15.0 + rev: v1.19.1 hooks: - id: mypy name: mypy @@ -61,27 +60,27 @@ repos: # files: ^(src/|tests/) - repo: https://github.com/PyCQA/isort - rev: 6.0.1 + rev: 7.0.0 hooks: - id: isort args: ["--profile", "black", "--filter-files", "--combine-as", "honor--noqa"] - repo: https://github.com/psf/black - rev: 25.1.0 + rev: 26.1.0 hooks: - id: black language_version: python3.10 args: ["--skip-magic-trailing-comma"] - repo: https://github.com/asottile/pyupgrade - rev: v3.19.1 + rev: v3.21.2 hooks: - args: - --py310-plus id: pyupgrade - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.5 + rev: v1.5.6 hooks: - id: remove-tabs @@ -133,7 +132,7 @@ repos: # C901 function is too complex # for iter_at_depth # PLR0912 too many branches # for iter_at_depth # - rev: 'v0.11.9' + rev: 'v0.14.14' hooks: - id: ruff exclude: "tests" @@ -145,6 +144,6 @@ repos: # reads pyproject.toml for additional config - repo: https://github.com/RobertCraigie/pyright-python - rev: v1.1.400 + rev: v1.1.408 hooks: - id: pyright diff --git a/tests/test_comments.py b/tests/test_comments.py index 91b55fb..1469f9f 100644 --- a/tests/test_comments.py +++ b/tests/test_comments.py @@ -30,28 +30,22 @@ def test_comments() -> None: pars.close() assert comments == [ ( - par( - """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua.""" - ), + par("""Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua."""), "Randy Bartels", "2024-03-28T17:22:00Z", "COMMENT", ), ( - par( - """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua.""" - ), + par("""Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua."""), "Randy Bartels", "2024-03-28T17:22:00Z", "RESPONSE", ), ( - par( - """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua.""" - ), + par("""Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua."""), "Shay Hill", "2024-03-29T12:10:00Z", "Response from Shay Hill", @@ -63,28 +57,22 @@ def test_comments() -> None: "Comment on subset starting with tempor", ), ( - par( - """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua.""" - ), + par("""Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua."""), "Randy Bartels", "2024-03-28T17:22:00Z", "COMMENT on par 5", ), ( - par( - """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua.""" - ), + par("""Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua."""), "Randy Bartels", "2024-03-28T17:22:00Z", "RESPONSE to comment on par 5", ), ( - par( - """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua.""" - ), + par("""Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua."""), "Shay Hill", "2024-03-29T12:10:00Z", "Response from Shay Hill on par 5", @@ -190,8 +178,7 @@ def test_long_comment( "Amet ", "Randy Bartels", "2024-04-02T17:00:00Z", - par( - """Comment 6 with a long comment.\n\nmagna fringilla urna porttitor + par("""Comment 6 with a long comment.\n\nmagna fringilla urna porttitor rhoncus dolor purus non enim praesent elementum facilisis leo vel fringilla est ullamcorper eget nulla facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus in ornare quam @@ -201,8 +188,7 @@ def test_long_comment( vitae congue eu consequat ac felis donec et odio pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate sapien nec sagittis - aliquam malesuada bibendum""" - ), + aliquam malesuada bibendum"""), ) def test_comment_7( @@ -226,8 +212,7 @@ def test_long_response( "suspendisse ", "Randy Bartels", "2024-04-02T17:00:00Z", - par( - """Long response: magna fringilla urna porttitor rhoncus dolor purus + par("""Long response: magna fringilla urna porttitor rhoncus dolor purus non enim praesent elementum facilisis leo vel fringilla est ullamcorper eget nulla facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus in ornare quam viverra @@ -237,8 +222,7 @@ def test_long_response( congue eu consequat ac felis donec et odio pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate sapien nec sagittis aliquam - malesuada bibendum""" - ), + malesuada bibendum"""), ) def comment_8( diff --git a/tests/test_docx2python.py b/tests/test_docx2python.py index 34c56ed..6eca6b5 100644 --- a/tests/test_docx2python.py +++ b/tests/test_docx2python.py @@ -14,10 +14,8 @@ from docx2python.main import docx2python from tests.conftest import RESOURCES -ALT_TEXT = par( - """----Image alt text---->A close up of a logo\n\n - Description automatically generated<""" -) +ALT_TEXT = par("""----Image alt text---->A close up of a logo\n\n + Description automatically generated<""") class TestFormatting: @@ -52,10 +50,8 @@ def test_footnotes(self) -> None: [ "footnote2)\t", " Second footnote", - par( - """----Image alt text---->A close up of a - logo\n\nDescription automatically generated<""" - ), + par("""----Image alt text---->A close up of a + logo\n\nDescription automatically generated<"""), "----media/image1.png----", ] ], @@ -76,10 +72,8 @@ def test_endnotes(self) -> None: [ "endnote2)\t", " Second endnote", - par( - """----Image alt text---->A close up of a - logo\n\nDescription automatically generated<""" - ), + par("""----Image alt text---->A close up of a + logo\n\nDescription automatically generated<"""), "----media/image1.png----", ] ], @@ -202,10 +196,8 @@ def test_formatting_captured(self) -> None: 'Colored', 'Large Colored', 'Large Bold', - par( - """Large Bold Italics - Underlined""" - ), + par("""Large Bold Italics + Underlined"""), ] def test_paragraph_formatting(self) -> None: @@ -223,10 +215,8 @@ def test_paragraph_formatting(self) -> None: ["

", "Heading 2", "

"], [], [ - par( - """----Image alt text---->A jellyfish in - water\n\nDescription automatically generated<""" - ), + par("""----Image alt text---->A jellyfish in + water\n\nDescription automatically generated<"""), "----media/image2.jpg----", ], ] diff --git a/tests/test_more_html.py b/tests/test_more_html.py index 3acd305..3c45855 100644 --- a/tests/test_more_html.py +++ b/tests/test_more_html.py @@ -93,30 +93,21 @@ def test_paragraphs_only() -> None: expect = [ ( "", - [ - par( - """[Grab your reader’s attention with a great quote from the + [par("""[Grab your reader’s attention with a great quote from the document or use this space to emphasize a key point. To place - this text box anywhere on the page, just drag it.]""" - ) - ], + this text box anywhere on the page, just drag it.]""")], ), ( "", - [ - par( - """[Grab your reader’s attention with a great quote from the + [par("""[Grab your reader’s attention with a great quote from the document or use this space to emphasize a key point. To place - this text box anywhere on the page, just drag it.]""" - ) - ], + this text box anywhere on the page, just drag it.]""")], ), ( "Heading1", [ "

", - par( - """aaa aab aac aad aae aaf aag aah aai aaj aak aal aam aan aao + par("""aaa aab aac aad aae aaf aag aah aai aaj aak aal aam aan aao aap aaq aar aas aat aau aav aaw aax aay aaz aba abb abc abd abe abf abg abh abi abj abk abl abm abn abo abp abq abr abs abt abu abv abw abx aby abz aca acb acc acd ace acf acg ach aci acj ack @@ -158,8 +149,7 @@ def test_paragraphs_only() -> None: axz aya ayb ayc ayd aye ayf ayg ayh ayi ayj ayk ayl aym ayn ayo ayp ayq ayr ays ayt ayu ayv ayw ayx ayy ayz aza azb azc azd aze azf azg azh azi azj azk azl azm azn azo azp azq azr azs azt azu - azv azw azx azy azz""" - ), + azv azw azx azy azz"""), "

", ], ), diff --git a/tests/test_toc_support.py b/tests/test_toc_support.py index 9874750..d86432a 100644 --- a/tests/test_toc_support.py +++ b/tests/test_toc_support.py @@ -53,33 +53,17 @@ def test_get_toc_text(self) -> None: ["Errors should never pass silently."], ["Unless explicitly silenced."], ["In the face of ambiguity, refuse the temptation to guess."], - [ - par( - """There should be one-- and preferably only one - --obvious way to do it.""" - ) - ], - [ - par( - """Although that way may not be obvious at first - unless you're Dutch.""" - ) - ], + [par("""There should be one-- and preferably only one + --obvious way to do it.""")], + [par("""Although that way may not be obvious at first + unless you're Dutch.""")], ["Now is better than never."], ["Although never is often better than *right* now."], ["If the implementation is hard to explain, it's a bad idea."], - [ - par( - """If the implementation is easy to explain, it may - be a good idea.""" - ) - ], - [ - par( - """Namespaces are one honking great idea -- let's do - more of those!""" - ) - ], + [par("""If the implementation is easy to explain, it may + be a good idea.""")], + [par("""Namespaces are one honking great idea -- let's do + more of those!""")], ] ], ] From 0e04b8d3816b0a8a62ba27a56f2ac1a9ed0c7c4b Mon Sep 17 00:00:00 2001 From: Shay Hill Date: Thu, 29 Jan 2026 11:18:38 -0600 Subject: [PATCH 4/4] =?UTF-8?q?bump:=20version=203.5.0=20=E2=86=92=203.6.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 89f8b1d..82acc6b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "docx2python" -version = "3.5.0" +version = "3.6.0" description = "Extract content from docx files" authors = [{ name = "Shay Hill", email = "shay_public@hotmail.com" }] license = {text = "MIT"} @@ -19,7 +19,7 @@ build-backend = "setuptools.build_meta" [tool.commitizen] name = "cz_conventional_commits" -version = "3.5.0" +version = "3.6.0" tag_format = "$version" major-version-zero = true version_files = ["pyproject.toml:^version"]