Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ jobs:
py: 3.11.5
- os: ubuntu-latest
py: 3.10.13
- os: ubuntu-latest
py: 3.9.18
runs-on: ${{ matrix.os }}
steps:
- uses: mhils/workflows/checkout@cc6add7a662663ad7ad3017a86bcb91c361c9cc9
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

- pdoc has a new logo. 🐍
([#838](https://github.com/mitmproxy/pdoc/pull/838), @mhils)
- Drop support for Python 3.9, which as reached
[end of life](https://devguide.python.org/versions/).
([#842](https://github.com/mitmproxy/pdoc/pull/842), @mhils)
- Fix linking of identifiers that contain unicode characters.
([#831](https://github.com/mitmproxy/pdoc/issues/831), @iFreilicht)
- Replace vendored version of `markdown2` with the [official
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ API Documentation for Python Projects.
pip install pdoc
```

pdoc is compatible with Python 3.9 and newer.
pdoc is compatible with Python 3.10 and newer.


# Usage
Expand Down
27 changes: 1 addition & 26 deletions pdoc/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,7 @@ class ast_TypeAlias:
class TypeAliasType:
"""Placeholder class for TypeAliasType"""

if sys.version_info >= (3, 10):
from typing import TypeAlias
else: # pragma: no cover
class TypeAlias:
pass

if sys.version_info >= (3, 10):
from types import UnionType # type: ignore
else: # pragma: no cover
class UnionType:
pass


if (3, 9) <= sys.version_info < (3, 9, 8) or (3, 10) <= sys.version_info < (3, 10, 1): # pragma: no cover
if (3, 10) <= sys.version_info < (3, 10, 1): # pragma: no cover
import inspect
import types

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

if sys.version_info >= (3, 10):
from typing import is_typeddict
else: # pragma: no cover
def is_typeddict(tp):
try:
return tp.__orig_bases__[-1].__name__ == "TypedDict"
except Exception:
return False


__all__ = [
"ast_TypeAlias",
"TypeAliasType",
"TypeAlias",
"UnionType",
"formatannotation",
"is_typeddict",
]
10 changes: 3 additions & 7 deletions pdoc/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,18 @@
from typing import Any
from typing import ClassVar
from typing import Generic
from typing import TypeAlias
from typing import TypedDict
from typing import TypeVar
from typing import Union
from typing import get_origin
from typing import is_typeddict
import warnings

from pdoc import doc_ast
from pdoc import doc_pyi
from pdoc import extract
from pdoc._compat import TypeAlias
from pdoc._compat import TypeAliasType
from pdoc._compat import formatannotation
from pdoc._compat import is_typeddict
from pdoc.doc_types import GenericAlias
from pdoc.doc_types import NonUserDefinedCallables
from pdoc.doc_types import empty
Expand Down Expand Up @@ -868,10 +867,7 @@ def methods(self) -> list[Function]:
]


if sys.version_info >= (3, 10):
WrappedFunction = types.FunctionType | staticmethod | classmethod
else: # pragma: no cover
WrappedFunction = Union[types.FunctionType, staticmethod, classmethod]
WrappedFunction = types.FunctionType | staticmethod | classmethod


class Function(Doc[types.FunctionType]):
Expand Down
18 changes: 2 additions & 16 deletions pdoc/doc_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from types import BuiltinFunctionType
from types import GenericAlias
from types import ModuleType
from types import UnionType
import typing
from typing import TYPE_CHECKING
from typing import Any
Expand All @@ -25,7 +26,6 @@
import warnings

from . import extract
from ._compat import UnionType
from .doc_ast import type_checking_sections

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

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

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

if get_origin(t) is Literal:
Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "pdoc"
description = "API Documentation for Python Projects"
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.10"
license = { text="MIT-0" }
authors = [{name = "Maximilian Hils", email = "[email protected]"}]
dynamic = ["version"]
Expand All @@ -23,7 +23,6 @@ classifiers = [
"Environment :: Console",
"Intended Audience :: Developers",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand Down
11 changes: 0 additions & 11 deletions test/test_doc_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,6 @@ def test_eval_fail_import_nonexistent(monkeypatch):
assert safe_eval_type("xyz", a.__dict__, None, a, "a") == "xyz"


def test_eval_union_types_on_old_python(monkeypatch):
monkeypatch.setattr(sys, "version_info", (3, 9, 0))
with pytest.warns(
UserWarning,
match=r"You are likely attempting to use Python 3.10 syntax \(PEP 604 union types\) "
r"with an older Python release.",
):
# str never implements `|`, so we can use that to trigger the error on newer versions.
safe_eval_type('"foo" | "bar"', {}, None, None, "example")


def test_recurse(monkeypatch):
def get_source(mod):
if mod == a:
Expand Down
13 changes: 5 additions & 8 deletions test/test_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ def outfile(self, format: str) -> Path:

snapshots = [
Snapshot("ast_parsing"),
Snapshot("collections_abc", min_version=(3, 9)),
Snapshot("demo", min_version=(3, 9)),
Snapshot("collections_abc"),
Snapshot("demo"),
Snapshot("enums", min_version=(3, 13)),
Snapshot("flavors_google"),
Snapshot("flavors_numpy"),
Expand All @@ -106,22 +106,19 @@ def outfile(self, format: str) -> Path:
"example_customtemplate",
["demo.py"],
{"template_directory": here / ".." / "examples" / "custom-template"},
min_version=(3, 9),
),
Snapshot(
"example_darkmode",
["demo.py"],
{"template_directory": here / ".." / "examples" / "dark-mode"},
min_version=(3, 9),
),
Snapshot(
"example_mkdocs",
["demo.py"],
{"template_directory": here / ".." / "examples" / "mkdocs" / "pdoc-template"},
min_version=(3, 9),
),
Snapshot("demo_long", min_version=(3, 9)),
Snapshot("demo_eager", min_version=(3, 9)),
Snapshot("demo_long"),
Snapshot("demo_eager"),
Snapshot("demopackage", ["demopackage", "!demopackage.child_excluded"]),
Snapshot(
"demopackage_dir",
Expand All @@ -141,7 +138,7 @@ def outfile(self, format: str) -> Path:
Snapshot("misc_py313", min_version=(3, 13)),
Snapshot("math_demo", render_options={"math": True}),
Snapshot("math_misc", render_options={"math": True}),
Snapshot("mermaid_demo", render_options={"mermaid": True}, min_version=(3, 9)),
Snapshot("mermaid_demo", render_options={"mermaid": True}),
Snapshot(
"render_options",
["render_options", "math_demo"],
Expand Down
Loading