Skip to content

Commit bfcab86

Browse files
committed
chore: drop support for Python 3.8
1 parent 98f03f4 commit bfcab86

33 files changed

+190
-239
lines changed

.github/workflows/build.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@ jobs:
1818
strategy:
1919
matrix:
2020
python:
21-
- "3.8"
2221
- "3.9"
2322
- "3.10"
2423
- "3.11"
2524
- "3.12"
2625
- "3.13"
27-
- "pypy-3.8"
2826
- "pypy-3.9"
2927
- "pypy-3.10"
3028
steps:

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ For the purpose of determining breaking changes:
2424

2525
### :house: Internal
2626

27+
- End of Python 3.8 support
2728
- Add tests for CPython 3.13
2829
- Use CPython 3.13 for misc. tests
2930
- Upgrade dev dependencies

docs/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
from collections.abc import Iterator
12
from os import chdir, getcwd
23
from pathlib import Path
34
import re
45
from tempfile import TemporaryDirectory
5-
from typing import Dict, Iterator
66
from unittest.mock import Mock
77

88
import pytest
@@ -18,7 +18,7 @@
1818

1919

2020
@pytest.fixture(scope="module", autouse=True)
21-
def _import_pytest(doctest_namespace: Dict[str, object]) -> None:
21+
def _import_pytest(doctest_namespace: dict[str, object]) -> None:
2222
doctest_namespace["HandlerTypeHelper"] = HandlerTypeHelper
2323
doctest_namespace["Parser"] = Parser
2424
doctest_namespace["XMLElement"] = XMLElement

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ classifiers = [
1313
"Programming Language :: Python",
1414
"Programming Language :: Python :: 3",
1515
"Programming Language :: Python :: 3 :: Only",
16-
"Programming Language :: Python :: 3.8",
1716
"Programming Language :: Python :: 3.9",
1817
"Programming Language :: Python :: 3.10",
1918
"Programming Language :: Python :: 3.11",
@@ -22,7 +21,7 @@ classifiers = [
2221
"Topic :: Utilities",
2322
"Topic :: Text Processing :: Markup :: XML",
2423
]
25-
requires-python = ">=3.8"
24+
requires-python = ">=3.9"
2625
dependencies = [
2726
"defusedxml>=0.7.1",
2827
"typing-extensions>=4.6.0 ; python_version<'3.12'",
@@ -139,7 +138,7 @@ testpaths = ["docs", "tests"]
139138

140139
[tool.ruff]
141140
src = ["src"]
142-
target-version = "py38"
141+
target-version = "py39"
143142

144143
[tool.ruff.lint]
145144
select = ["ALL"]

src/bigxml/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Iterable, Iterator
1+
from collections.abc import Iterable, Iterator
22

33
from defusedxml import DefusedXmlException
44
from defusedxml.ElementTree import ParseError

src/bigxml/handle_mgr.py

Lines changed: 34 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
1+
from collections.abc import Iterable, Iterator
12
import sys
2-
from typing import (
3-
TYPE_CHECKING,
4-
Any,
5-
Callable,
6-
Iterable,
7-
Iterator,
8-
List,
9-
Optional,
10-
Tuple,
11-
Type,
12-
Union,
13-
overload,
14-
)
3+
from typing import TYPE_CHECKING, Any, Callable, Optional, Union, overload
154

165
from bigxml.handler_creator import create_handler
176
from bigxml.typing import (
@@ -50,8 +39,8 @@ def iter_from(
5039
self,
5140
*handlers: Union[
5241
str,
53-
List[str],
54-
Tuple[str, ...],
42+
list[str],
43+
tuple[str, ...],
5544
],
5645
) -> Iterator["XMLElement"]: ...
5746

@@ -62,8 +51,8 @@ def iter_from(
6251
Callable[[Union["XMLElement", "XMLText"]], Optional[Iterable[T]]],
6352
ClassHandlerWithCustomWrapper0[T],
6453
ClassHandlerWithCustomWrapper1[T],
65-
Type[ClassHandlerWithCustomWrapper0[T]],
66-
Type[ClassHandlerWithCustomWrapper1[T]],
54+
type[ClassHandlerWithCustomWrapper0[T]],
55+
type[ClassHandlerWithCustomWrapper1[T]],
6756
],
6857
) -> Iterator[T]: ...
6958

@@ -74,9 +63,9 @@ def iter_from(
7463
Callable[[Union["XMLElement", "XMLText"]], Optional[Iterable[T]]],
7564
ClassHandlerWithCustomWrapper0[T],
7665
ClassHandlerWithCustomWrapper1[T],
77-
Type[ClassHandlerWithCustomWrapper0[T]],
78-
Type[ClassHandlerWithCustomWrapper1[T]],
79-
Type[T],
66+
type[ClassHandlerWithCustomWrapper0[T]],
67+
type[ClassHandlerWithCustomWrapper1[T]],
68+
type[T],
8069
],
8170
) -> Iterator[T]: ...
8271

@@ -87,11 +76,11 @@ def iter_from(
8776
Callable[[Union["XMLElement", "XMLText"]], Optional[Iterable[T]]],
8877
ClassHandlerWithCustomWrapper0[T],
8978
ClassHandlerWithCustomWrapper1[T],
90-
Type[ClassHandlerWithCustomWrapper0[T]],
91-
Type[ClassHandlerWithCustomWrapper1[T]],
79+
type[ClassHandlerWithCustomWrapper0[T]],
80+
type[ClassHandlerWithCustomWrapper1[T]],
9281
str,
93-
List[str],
94-
Tuple[str, ...],
82+
list[str],
83+
tuple[str, ...],
9584
],
9685
) -> Iterator[Union["XMLElement", T]]: ...
9786

@@ -102,12 +91,12 @@ def iter_from(
10291
Callable[[Union["XMLElement", "XMLText"]], Optional[Iterable[T]]],
10392
ClassHandlerWithCustomWrapper0[T],
10493
ClassHandlerWithCustomWrapper1[T],
105-
Type[ClassHandlerWithCustomWrapper0[T]],
106-
Type[ClassHandlerWithCustomWrapper1[T]],
107-
Type[T],
94+
type[ClassHandlerWithCustomWrapper0[T]],
95+
type[ClassHandlerWithCustomWrapper1[T]],
96+
type[T],
10897
str,
109-
List[str],
110-
Tuple[str, ...],
98+
list[str],
99+
tuple[str, ...],
111100
],
112101
) -> Iterator[Union["XMLElement", T]]: ...
113102

@@ -135,8 +124,8 @@ def return_from(
135124
self,
136125
*handlers: Union[
137126
str,
138-
List[str],
139-
Tuple[str, ...],
127+
list[str],
128+
tuple[str, ...],
140129
],
141130
) -> Optional["XMLElement"]: ...
142131

@@ -147,8 +136,8 @@ def return_from(
147136
Callable[[Union["XMLElement", "XMLText"]], Optional[Iterable[T]]],
148137
ClassHandlerWithCustomWrapper0[T],
149138
ClassHandlerWithCustomWrapper1[T],
150-
Type[ClassHandlerWithCustomWrapper0[T]],
151-
Type[ClassHandlerWithCustomWrapper1[T]],
139+
type[ClassHandlerWithCustomWrapper0[T]],
140+
type[ClassHandlerWithCustomWrapper1[T]],
152141
],
153142
) -> Optional[T]: ...
154143

@@ -159,9 +148,9 @@ def return_from(
159148
Callable[[Union["XMLElement", "XMLText"]], Optional[Iterable[T]]],
160149
ClassHandlerWithCustomWrapper0[T],
161150
ClassHandlerWithCustomWrapper1[T],
162-
Type[ClassHandlerWithCustomWrapper0[T]],
163-
Type[ClassHandlerWithCustomWrapper1[T]],
164-
Type[T],
151+
type[ClassHandlerWithCustomWrapper0[T]],
152+
type[ClassHandlerWithCustomWrapper1[T]],
153+
type[T],
165154
],
166155
) -> Optional[T]: ...
167156

@@ -172,11 +161,11 @@ def return_from(
172161
Callable[[Union["XMLElement", "XMLText"]], Optional[Iterable[T]]],
173162
ClassHandlerWithCustomWrapper0[T],
174163
ClassHandlerWithCustomWrapper1[T],
175-
Type[ClassHandlerWithCustomWrapper0[T]],
176-
Type[ClassHandlerWithCustomWrapper1[T]],
164+
type[ClassHandlerWithCustomWrapper0[T]],
165+
type[ClassHandlerWithCustomWrapper1[T]],
177166
str,
178-
List[str],
179-
Tuple[str, ...],
167+
list[str],
168+
tuple[str, ...],
180169
],
181170
) -> Optional[Union["XMLElement", T]]: ...
182171

@@ -187,12 +176,12 @@ def return_from(
187176
Callable[[Union["XMLElement", "XMLText"]], Optional[Iterable[T]]],
188177
ClassHandlerWithCustomWrapper0[T],
189178
ClassHandlerWithCustomWrapper1[T],
190-
Type[ClassHandlerWithCustomWrapper0[T]],
191-
Type[ClassHandlerWithCustomWrapper1[T]],
179+
type[ClassHandlerWithCustomWrapper0[T]],
180+
type[ClassHandlerWithCustomWrapper1[T]],
192181
str,
193-
List[str],
194-
Tuple[str, ...],
195-
Type[T],
182+
list[str],
183+
tuple[str, ...],
184+
type[T],
196185
],
197186
) -> Optional[Union["XMLElement", T]]: ...
198187

src/bigxml/handler_creator.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,7 @@
1+
from collections.abc import Iterable, Iterator
12
from dataclasses import is_dataclass
23
from inspect import getmembers, isclass
3-
from typing import (
4-
TYPE_CHECKING,
5-
Any,
6-
Callable,
7-
Dict,
8-
Iterable,
9-
Iterator,
10-
Optional,
11-
Tuple,
12-
Type,
13-
Union,
14-
cast,
15-
)
4+
from typing import TYPE_CHECKING, Any, Callable, Optional, Union, cast
165
import warnings
176

187
from bigxml.marks import get_marks, has_marks
@@ -26,7 +15,7 @@
2615

2716

2817
def _assert_one_mandatory_param(
29-
mandatory_params: Tuple[str, ...], klass: Type[Any], method_name: str
18+
mandatory_params: tuple[str, ...], klass: type[Any], method_name: str
3019
) -> None:
3120
if len(mandatory_params) > 1:
3221
raise TypeError(
@@ -37,7 +26,7 @@ def _assert_one_mandatory_param(
3726

3827

3928
def _assert_iterable_or_none(
40-
item: object, klass: Type[Any], method_name: str
29+
item: object, klass: type[Any], method_name: str
4130
) -> Optional[Iterable[object]]:
4231
if item is None or isinstance(item, Iterable):
4332
return item
@@ -52,14 +41,14 @@ def _handler_identity(node: T) -> Iterator[T]:
5241

5342

5443
class _HandlerTree:
55-
def __init__(self, path: Tuple[str, ...] = ()) -> None:
56-
self.path: Tuple[str, ...] = path
57-
self.children: Dict[str, _HandlerTree] = {}
44+
def __init__(self, path: tuple[str, ...] = ()) -> None:
45+
self.path: tuple[str, ...] = path
46+
self.children: dict[str, _HandlerTree] = {}
5847
self.handler: Optional[Callable[..., Iterable[object]]] = None
5948

6049
def add_handler(
6150
self,
62-
path: Tuple[str, ...],
51+
path: tuple[str, ...],
6352
handler: object,
6453
*,
6554
ignore_direct_marks: bool,
@@ -105,7 +94,7 @@ def add_handler(
10594

10695
def add_handler_callable(
10796
self,
108-
path: Tuple[str, ...],
97+
path: tuple[str, ...],
10998
handler: Callable[..., Iterable[object]],
11099
) -> None:
111100
if self.handler:
@@ -147,7 +136,7 @@ def handle(
147136

148137
@staticmethod
149138
def _handle_from_class( # type: ignore[misc]
150-
klass: Type[Any], node: Union["XMLElement", "XMLText"]
139+
klass: type[Any], node: Union["XMLElement", "XMLText"]
151140
) -> Optional[Iterable[object]]:
152141
# instantiate class
153142
init_mandatory_params = get_mandatory_params(klass)

src/bigxml/handler_marker.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from typing import Any, Callable, Generic, Iterable, Optional, Union, cast, overload
1+
from collections.abc import Iterable
2+
from typing import Any, Callable, Generic, Optional, Union, cast, overload
23

34
from bigxml.marks import add_mark
45
from bigxml.nodes import XMLElement, XMLText

src/bigxml/marks.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
1-
from typing import Tuple
2-
31
__ATTR_MARK_NAME = "_xml_handlers_on"
42

53

64
def has_marks(obj: object) -> bool:
75
return hasattr(obj, __ATTR_MARK_NAME)
86

97

10-
def get_marks(obj: object) -> Tuple[Tuple[str, ...], ...]:
8+
def get_marks(obj: object) -> tuple[tuple[str, ...], ...]:
119
return getattr(obj, __ATTR_MARK_NAME, ())
1210

1311

14-
def add_mark(obj: object, mark: Tuple[str, ...]) -> None:
12+
def add_mark(obj: object, mark: tuple[str, ...]) -> None:
1513
marks = get_marks(obj)
1614
marks += (mark,)
1715
setattr(obj, __ATTR_MARK_NAME, marks)

src/bigxml/nodes.py

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,16 @@
1+
from collections.abc import Iterator, Mapping
12
from dataclasses import dataclass
2-
import sys
3-
from typing import Dict, Iterator, Optional, Tuple, Union
3+
from typing import Optional, Union
44
import warnings
55

66
from bigxml.handle_mgr import HandleMgr
77
from bigxml.utils import extract_namespace_name
88

9-
if sys.version_info < (3, 9): # pragma: no cover
10-
from typing import Mapping
11-
12-
def removeprefix(data: str, prefix: str) -> str:
13-
if data.startswith(prefix):
14-
return data[len(prefix) :]
15-
return data
16-
17-
else: # pragma: no cover
18-
from collections.abc import Mapping
19-
209

2110
class XMLElementAttributes(Mapping[str, str]):
2211
def __init__(self, attributes: Mapping[str, str]) -> None:
23-
self._items: Dict[
24-
str, Tuple[Optional[int], str]
12+
self._items: dict[
13+
str, tuple[Optional[int], str]
2514
] = {} # key -> (alternatives, value)
2615
self._len = 0
2716
for key, value in attributes.items():
@@ -53,10 +42,7 @@ def __getitem__(self, key: str) -> str:
5342
def __iter__(self) -> Iterator[str]:
5443
for key in self._items:
5544
if key.startswith("{"):
56-
if sys.version_info < (3, 9): # pragma: no cover
57-
yield removeprefix(key, r"{}")
58-
else: # pragma: no cover
59-
yield key.removeprefix(r"{}")
45+
yield key.removeprefix(r"{}")
6046

6147
def __len__(self) -> int:
6248
return self._len
@@ -81,7 +67,7 @@ def _handler_get_text(node: Union["XMLElement", "XMLText"]) -> Iterator[str]:
8167
class XMLElement(HandleMgr):
8268
name: str
8369
attributes: XMLElementAttributes
84-
parents: Tuple["XMLElement", ...]
70+
parents: tuple["XMLElement", ...]
8571
namespace: str = ""
8672

8773
def __post_init__(self) -> None:
@@ -118,7 +104,7 @@ def text(self) -> str:
118104
@dataclass
119105
class XMLText:
120106
text: str
121-
parents: Tuple[XMLElement, ...]
107+
parents: tuple[XMLElement, ...]
122108

123109
# classname attribute name to be easily switched on with XMLElement
124110
name = "\0text" # \0 makes sure it is an invalid element name

0 commit comments

Comments
 (0)