Skip to content

Commit 34c7759

Browse files
Drop Support for Python 3.9 (#842)
* drop support for Python 3.9 * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 0f27371 commit 34c7759

File tree

10 files changed

+278
-362
lines changed

10 files changed

+278
-362
lines changed

.github/workflows/main.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ jobs:
5151
py: 3.11.5
5252
- os: ubuntu-latest
5353
py: 3.10.13
54-
- os: ubuntu-latest
55-
py: 3.9.18
5654
runs-on: ${{ matrix.os }}
5755
steps:
5856
- uses: mhils/workflows/checkout@cc6add7a662663ad7ad3017a86bcb91c361c9cc9

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
- pdoc has a new logo. 🐍
88
([#838](https://github.com/mitmproxy/pdoc/pull/838), @mhils)
9+
- Drop support for Python 3.9, which as reached
10+
[end of life](https://devguide.python.org/versions/).
11+
([#842](https://github.com/mitmproxy/pdoc/pull/842), @mhils)
912
- Fix linking of identifiers that contain unicode characters.
1013
([#831](https://github.com/mitmproxy/pdoc/issues/831), @iFreilicht)
1114
- Replace vendored version of `markdown2` with the [official

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ API Documentation for Python Projects.
2121
pip install pdoc
2222
```
2323

24-
pdoc is compatible with Python 3.9 and newer.
24+
pdoc is compatible with Python 3.10 and newer.
2525

2626

2727
# Usage

pdoc/_compat.py

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,7 @@ class ast_TypeAlias:
1313
class TypeAliasType:
1414
"""Placeholder class for TypeAliasType"""
1515

16-
if sys.version_info >= (3, 10):
17-
from typing import TypeAlias
18-
else: # pragma: no cover
19-
class TypeAlias:
20-
pass
21-
22-
if sys.version_info >= (3, 10):
23-
from types import UnionType # type: ignore
24-
else: # pragma: no cover
25-
class UnionType:
26-
pass
27-
28-
29-
if (3, 9) <= sys.version_info < (3, 9, 8) or (3, 10) <= sys.version_info < (3, 10, 1): # pragma: no cover
16+
if (3, 10) <= sys.version_info < (3, 10, 1): # pragma: no cover
3017
import inspect
3118
import types
3219

@@ -40,21 +27,9 @@ def formatannotation(annotation) -> str:
4027
else:
4128
from inspect import formatannotation
4229

43-
if sys.version_info >= (3, 10):
44-
from typing import is_typeddict
45-
else: # pragma: no cover
46-
def is_typeddict(tp):
47-
try:
48-
return tp.__orig_bases__[-1].__name__ == "TypedDict"
49-
except Exception:
50-
return False
51-
5230

5331
__all__ = [
5432
"ast_TypeAlias",
5533
"TypeAliasType",
56-
"TypeAlias",
57-
"UnionType",
5834
"formatannotation",
59-
"is_typeddict",
6035
]

pdoc/doc.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,18 @@
3838
from typing import Any
3939
from typing import ClassVar
4040
from typing import Generic
41+
from typing import TypeAlias
4142
from typing import TypedDict
4243
from typing import TypeVar
43-
from typing import Union
4444
from typing import get_origin
45+
from typing import is_typeddict
4546
import warnings
4647

4748
from pdoc import doc_ast
4849
from pdoc import doc_pyi
4950
from pdoc import extract
50-
from pdoc._compat import TypeAlias
5151
from pdoc._compat import TypeAliasType
5252
from pdoc._compat import formatannotation
53-
from pdoc._compat import is_typeddict
5453
from pdoc.doc_types import GenericAlias
5554
from pdoc.doc_types import NonUserDefinedCallables
5655
from pdoc.doc_types import empty
@@ -868,10 +867,7 @@ def methods(self) -> list[Function]:
868867
]
869868

870869

871-
if sys.version_info >= (3, 10):
872-
WrappedFunction = types.FunctionType | staticmethod | classmethod
873-
else: # pragma: no cover
874-
WrappedFunction = Union[types.FunctionType, staticmethod, classmethod]
870+
WrappedFunction = types.FunctionType | staticmethod | classmethod
875871

876872

877873
class Function(Doc[types.FunctionType]):

pdoc/doc_types.py

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from types import BuiltinFunctionType
1717
from types import GenericAlias
1818
from types import ModuleType
19+
from types import UnionType
1920
import typing
2021
from typing import TYPE_CHECKING
2122
from typing import Any
@@ -25,7 +26,6 @@
2526
import warnings
2627

2728
from . import extract
28-
from ._compat import UnionType
2929
from .doc_ast import type_checking_sections
3030

3131
if TYPE_CHECKING:
@@ -108,19 +108,7 @@ def safe_eval_type(
108108
err = str(e)
109109
_, mod, _ = err.split("'")
110110
except Exception as e:
111-
if "unsupported operand type(s) for |" in str(e) and sys.version_info < (3, 10):
112-
py_ver = ".".join(str(x) for x in sys.version_info[:3])
113-
warnings.warn(
114-
f"Error parsing type annotation {t} for {fullname}: {e}. "
115-
f"You are likely attempting to use Python 3.10 syntax (PEP 604 union types) with an older Python "
116-
f"release. `X | Y`-style type annotations are invalid syntax on Python {py_ver}, which is what your "
117-
f"pdoc instance is using. `from __future__ import annotations` (PEP 563) postpones evaluation of "
118-
f"annotations, which is why your program won't crash right away. However, pdoc needs to evaluate your "
119-
f"type annotations and is unable to do so on Python {py_ver}. To fix this issue, either invoke pdoc "
120-
f"from Python 3.10+, or switch to `typing.Union[]` syntax."
121-
)
122-
else:
123-
warnings.warn(f"Error parsing type annotation {t} for {fullname}: {e}")
111+
warnings.warn(f"Error parsing type annotation {t} for {fullname}: {e}")
124112
return t
125113

126114
# Simple _eval_type has failed. We now execute all TYPE_CHECKING sections in the module and try again.
@@ -185,8 +173,6 @@ def _eval_type(t, globalns, localns, recursive_guard=frozenset()):
185173
# Added a special check for typing.Literal, whose literal strings would otherwise be evaluated.
186174

187175
if isinstance(t, str):
188-
if sys.version_info < (3, 9): # pragma: no cover
189-
t = t.strip("\"'")
190176
t = typing.ForwardRef(t)
191177

192178
if get_origin(t) is Literal:

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "pdoc"
33
description = "API Documentation for Python Projects"
44
readme = "README.md"
5-
requires-python = ">=3.9"
5+
requires-python = ">=3.10"
66
license = { text="MIT-0" }
77
authors = [{name = "Maximilian Hils", email = "[email protected]"}]
88
dynamic = ["version"]
@@ -23,7 +23,6 @@ classifiers = [
2323
"Environment :: Console",
2424
"Intended Audience :: Developers",
2525
"Operating System :: OS Independent",
26-
"Programming Language :: Python :: 3.9",
2726
"Programming Language :: Python :: 3.10",
2827
"Programming Language :: Python :: 3.11",
2928
"Programming Language :: Python :: 3.12",

test/test_doc_types.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,6 @@ def test_eval_fail_import_nonexistent(monkeypatch):
5656
assert safe_eval_type("xyz", a.__dict__, None, a, "a") == "xyz"
5757

5858

59-
def test_eval_union_types_on_old_python(monkeypatch):
60-
monkeypatch.setattr(sys, "version_info", (3, 9, 0))
61-
with pytest.warns(
62-
UserWarning,
63-
match=r"You are likely attempting to use Python 3.10 syntax \(PEP 604 union types\) "
64-
r"with an older Python release.",
65-
):
66-
# str never implements `|`, so we can use that to trigger the error on newer versions.
67-
safe_eval_type('"foo" | "bar"', {}, None, None, "example")
68-
69-
7059
def test_recurse(monkeypatch):
7160
def get_source(mod):
7261
if mod == a:

test/test_snapshot.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ def outfile(self, format: str) -> Path:
9696

9797
snapshots = [
9898
Snapshot("ast_parsing"),
99-
Snapshot("collections_abc", min_version=(3, 9)),
100-
Snapshot("demo", min_version=(3, 9)),
99+
Snapshot("collections_abc"),
100+
Snapshot("demo"),
101101
Snapshot("enums", min_version=(3, 13)),
102102
Snapshot("flavors_google"),
103103
Snapshot("flavors_numpy"),
@@ -106,22 +106,19 @@ def outfile(self, format: str) -> Path:
106106
"example_customtemplate",
107107
["demo.py"],
108108
{"template_directory": here / ".." / "examples" / "custom-template"},
109-
min_version=(3, 9),
110109
),
111110
Snapshot(
112111
"example_darkmode",
113112
["demo.py"],
114113
{"template_directory": here / ".." / "examples" / "dark-mode"},
115-
min_version=(3, 9),
116114
),
117115
Snapshot(
118116
"example_mkdocs",
119117
["demo.py"],
120118
{"template_directory": here / ".." / "examples" / "mkdocs" / "pdoc-template"},
121-
min_version=(3, 9),
122119
),
123-
Snapshot("demo_long", min_version=(3, 9)),
124-
Snapshot("demo_eager", min_version=(3, 9)),
120+
Snapshot("demo_long"),
121+
Snapshot("demo_eager"),
125122
Snapshot("demopackage", ["demopackage", "!demopackage.child_excluded"]),
126123
Snapshot(
127124
"demopackage_dir",
@@ -141,7 +138,7 @@ def outfile(self, format: str) -> Path:
141138
Snapshot("misc_py313", min_version=(3, 13)),
142139
Snapshot("math_demo", render_options={"math": True}),
143140
Snapshot("math_misc", render_options={"math": True}),
144-
Snapshot("mermaid_demo", render_options={"mermaid": True}, min_version=(3, 9)),
141+
Snapshot("mermaid_demo", render_options={"mermaid": True}),
145142
Snapshot(
146143
"render_options",
147144
["render_options", "math_demo"],

0 commit comments

Comments
 (0)