Skip to content

Commit bc20567

Browse files
added support for Python 3.14
1 parent 45e7084 commit bc20567

File tree

7 files changed

+38
-43
lines changed

7 files changed

+38
-43
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
python-version: [3.11, 3.12, 3.13]
13+
python-version: [3.11, 3.12, 3.13, 3.14]
1414
steps:
1515
- uses: actions/checkout@v4
1616
- name: Set up Python ${{ matrix.python-version }}

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# Changelog
2+
## Pedantic 2.3.0
3+
- added support for Python 3.14
4+
- updated dependencies
5+
26
## Pedantic 2.2.3
37
- remove support for deprecated `typing.ByteString`
48
- fix `WithDecoratedMethods`

pedantic/decorators/class_decorators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def decorate(cls: C) -> C:
3838
for attr in cls.__dict__:
3939
attr_value = getattr(cls, attr)
4040

41-
if isinstance(attr_value, (types.FunctionType, types.MethodType)):
41+
if isinstance(attr_value, (types.FunctionType, types.MethodType)) and attr != '__annotate_func__':
4242
setattr(cls, attr, decorator(attr_value))
4343
elif isinstance(attr_value, property):
4444
prop = attr_value

pedantic/tests/tests_pedantic.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os.path
2-
import sys
32
import types
43
import typing
54
import unittest

pedantic/type_checking_logic/check_types.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Idea is taken from: https://stackoverflow.com/a/55504010/10975692"""
22
import inspect
3+
import logging
4+
import sys
35
import types
46
import typing
57
from io import BytesIO, StringIO, BufferedWriter, TextIOWrapper
@@ -338,7 +340,8 @@ def _is_generic(cls: Any) -> bool:
338340
return True
339341
elif isinstance(cls, typing._SpecialForm):
340342
return cls not in {Any}
341-
343+
elif cls is typing.Union or type(cls) is typing.Union: # for python >= 3.14 Union is no longer a typing._SpecialForm
344+
return True
342345
return False
343346

344347

@@ -405,7 +408,7 @@ def get_type_arguments(cls: Any) -> Tuple[Any, ...]:
405408
>>> get_type_arguments(List[Tuple[Any, ...]])
406409
(typing.Tuple[typing.Any, ...],)
407410
>>> Union[bool, int, float]
408-
typing.Union[bool, int, float]
411+
bool | int | float
409412
>>> get_type_arguments(Union[str, float, int])
410413
(<class 'str'>, <class 'float'>, <class 'int'>)
411414
>>> get_type_arguments(Union[str, float, List[int], int])
@@ -473,9 +476,9 @@ def get_base_generic(cls: Any) -> Any:
473476
>>> get_base_generic(Dict[str, str])
474477
typing.Dict
475478
>>> get_base_generic(Union)
476-
typing.Union
479+
<class 'typing.Union'>
477480
>>> get_base_generic(Union[float, int, str])
478-
typing.Union
481+
<class 'typing.Union'>
479482
>>> get_base_generic(Set)
480483
typing.Set
481484
>>> get_base_generic(Set[int])
@@ -491,7 +494,7 @@ def get_base_generic(cls: Any) -> Any:
491494

492495
if name is not None:
493496
return getattr(typing, name)
494-
elif origin is not None:
497+
elif origin is not None and cls is not typing.Union:
495498
return origin
496499
return cls
497500

@@ -537,10 +540,8 @@ def _is_subtype(sub_type: Any, super_type: Any, context: Dict[str, Any] = None)
537540
False
538541
>>> _is_subtype(List[int], List[Union[int, float]])
539542
True
540-
>>> _is_subtype(List[Union[int, float]], List[int])
541-
Traceback (most recent call last):
542-
...
543-
TypeError: issubclass() arg 1 must be a class
543+
>>> _is_subtype(List[Union[int, float]], List[int]) if sys.version_info >= (3, 14) else False
544+
False
544545
>>> class Parent: pass
545546
>>> class Child(Parent): pass
546547
>>> _is_subtype(List[Child], List[Parent])
@@ -1033,6 +1034,8 @@ def convert_to_typing_types(x: typing.Type) -> typing.Type:
10331034
typing.Tuple[int]
10341035
>>> convert_to_typing_types(type[int])
10351036
typing.Type[int]
1037+
>>> convert_to_typing_types(type[int | float])
1038+
typing.Type[int | float]
10361039
>>> convert_to_typing_types(tuple[int, float])
10371040
typing.Tuple[int, float]
10381041
>>> convert_to_typing_types(dict[int, float])
@@ -1064,6 +1067,8 @@ def convert_to_typing_types(x: typing.Type) -> typing.Type:
10641067
return typing.FrozenSet[tuple(args)]
10651068
elif origin is type:
10661069
return typing.Type[tuple(args)]
1070+
elif origin is typing.Union:
1071+
return x
10671072

10681073
raise RuntimeError(x)
10691074

poetry.lock

Lines changed: 15 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "pedantic"
7-
version = "2.2.3"
7+
version = "2.3.0"
88
description = "Some useful Python decorators for cleaner software development."
99
readme = "README.md"
1010
requires-python = ">=3.11"
@@ -31,8 +31,8 @@ classifiers = [
3131
# pip install .[dev]
3232
dev = [
3333
"docstring-parser==0.17",
34-
"Flask[async]==3.1.1",
35-
"multiprocess==0.70.18",
34+
"Flask[async]==3.1.2",
35+
"multiprocess @ git+https://github.com/uqfoundation/multiprocess.git@02ea4bd36cac5013d70847815c92e1a736ef4a05",
3636
"Werkzeug==3.1.3",
3737
]
3838

0 commit comments

Comments
 (0)