Skip to content

Commit a00ed19

Browse files
authored
Merge pull request #406 from andlaus/python3.10
Bump minimum Python version to 3.10
2 parents f82add5 + f02c63b commit a00ed19

File tree

191 files changed

+1318
-1322
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

191 files changed

+1318
-1322
lines changed

.github/workflows/tests.yml

+3-7
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
matrix:
3939
# restrict the matrix to the oldest and the latest Python
4040
# version being supported by odxtools
41-
python-version: ["3.8", "3"]
41+
python-version: ["3.10", "3"]
4242

4343
steps:
4444
- uses: actions/checkout@v3
@@ -57,10 +57,6 @@ jobs:
5757
5858
- name: Static type checking (mypy)
5959
run: |
60-
# remove '# type:' comments in version.py which mypy-3.8
61-
# stumbles over. for some reason, mypy cannot be
62-
# instructed to ignore 'version.py'
63-
sed -i "s/# type:.*//" odxtools/version.py
6460
python -m mypy .
6561
6662
- name: Lint code quality (ruff)
@@ -73,13 +69,13 @@ jobs:
7369
os: [ubuntu-latest, windows-latest]
7470
# restrict the matrix to the oldest and the latest Python
7571
# version being supported by odxtools
76-
python-version: ["3.8", "3"]
72+
python-version: ["3.10", "3"]
7773

7874
# due to the slow windows runners, we refrain from testing every python
7975
# version on windows-latest
8076
exclude:
8177
- os: windows-latest
82-
python-version: "3.8"
78+
python-version: "3.10"
8379

8480
runs-on: ${{matrix.os}}
8581

examples/mksomersaultmodifiedpdx.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# modified programatically. Note that this is pretty hacky...
77
import argparse
88
from copy import deepcopy
9-
from typing import List, TypeVar
9+
from typing import TypeVar
1010

1111
import odxtools
1212
import odxtools.uds as uds
@@ -25,7 +25,7 @@
2525
T = TypeVar("T")
2626

2727

28-
def find_named_object(item_list: List[T], name: str) -> T:
28+
def find_named_object(item_list: list[T], name: str) -> T:
2929
for x in item_list:
3030
if getattr(x, "short_name", None) == name:
3131
return x

examples/somersaultecu.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from enum import IntEnum
66
from io import BytesIO
77
from itertools import chain
8-
from typing import Any, Dict
8+
from typing import Any
99
from xml.etree import ElementTree
1010

1111
import odxtools.uds as uds
@@ -440,7 +440,7 @@ class SomersaultSID(IntEnum):
440440
}
441441

442442
# computation methods
443-
somersault_compumethods: Dict[str, CompuMethod] = {
443+
somersault_compumethods: dict[str, CompuMethod] = {
444444
"int_passthrough":
445445
IdenticalCompuMethod(
446446
category=CompuCategory.IDENTICAL,

examples/somersaultlazy.py

+13-14
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import logging
99
import random
1010
from socket import socket
11-
from typing import List, Optional, Union, cast
11+
from typing import cast
1212

1313
import isotp
1414
import isotp.tpsock
@@ -26,19 +26,18 @@
2626
ecu_logger = logging.getLogger("somersault_lazy_ecu")
2727

2828
is_sterile = False
29-
can_channel: Optional[str] = None
29+
can_channel: str | None = None
3030
somersault_lazy_diag_layer = somersaultdatabase.ecus.somersault_lazy
3131

3232
# the raw payload data of the telegrams received by the ECU and by the
3333
# tester when in sterile mode (unittest without a CAN channel)
34-
sterile_rx_ecu: List[bytes] = []
35-
sterile_rx_ecu_event: Optional[asyncio.Event] = None
36-
sterile_rx_tester: List[bytes] = []
37-
sterile_rx_tester_event: Optional[asyncio.Event] = None
34+
sterile_rx_ecu: list[bytes] = []
35+
sterile_rx_ecu_event: asyncio.Event | None = None
36+
sterile_rx_tester: list[bytes] = []
37+
sterile_rx_tester_event: asyncio.Event | None = None
3838

3939

40-
def create_isotp_socket(channel: Optional[str], rxid: int,
41-
txid: int) -> Optional[isotp.tpsock.socket]:
40+
def create_isotp_socket(channel: str | None, rxid: int, txid: int) -> isotp.tpsock.socket | None:
4241
if is_sterile:
4342
return None
4443

@@ -66,7 +65,7 @@ def create_isotp_socket(channel: Optional[str], rxid: int,
6665
return result_socket
6766

6867

69-
async def ecu_send(isotp_socket: Optional[isotp.tpsock.socket], payload: bytes) -> None:
68+
async def ecu_send(isotp_socket: isotp.tpsock.socket | None, payload: bytes) -> None:
7069
"""
7170
ECU sends a message, either in "sterile" or in "live" mode.
7271
"""
@@ -87,7 +86,7 @@ async def ecu_send(isotp_socket: Optional[isotp.tpsock.socket], payload: bytes)
8786
await loop.sock_sendall(cast(socket, isotp_socket), payload)
8887

8988

90-
async def ecu_recv(isotp_socket: Optional[isotp.tpsock.socket]) -> bytes:
89+
async def ecu_recv(isotp_socket: isotp.tpsock.socket | None) -> bytes:
9190
"""
9291
ECU receives a message, either in "sterile" or in "live" mode.
9392
"""
@@ -113,7 +112,7 @@ async def ecu_recv(isotp_socket: Optional[isotp.tpsock.socket]) -> bytes:
113112
return await loop.sock_recv(cast(socket, isotp_socket), 4095)
114113

115114

116-
async def tester_send(isotp_socket: Optional[isotp.tpsock.socket], payload: bytes) -> None:
115+
async def tester_send(isotp_socket: isotp.tpsock.socket | None, payload: bytes) -> None:
117116
"""
118117
Tester sends a message, either in "sterile" or in "live" mode.
119118
"""
@@ -133,7 +132,7 @@ async def tester_send(isotp_socket: Optional[isotp.tpsock.socket], payload: byte
133132
await loop.sock_sendall(cast(socket, isotp_socket), payload)
134133

135134

136-
async def tester_recv(isotp_socket: Optional[isotp.tpsock.socket]) -> bytes:
135+
async def tester_recv(isotp_socket: isotp.tpsock.socket | None) -> bytes:
137136
"""
138137
Tester receives a message, either in "sterile" or in "live" mode.
139138
"""
@@ -360,9 +359,9 @@ async def _auto_close_session_task(self) -> None:
360359
continue
361360

362361

363-
async def tester_await_response(isotp_socket: Optional[isotp.tpsock.socket],
362+
async def tester_await_response(isotp_socket: isotp.tpsock.socket | None,
364363
raw_message: bytes,
365-
timeout: float = 0.5) -> Union[bytes, ParameterValueDict]:
364+
timeout: float = 0.5) -> bytes | ParameterValueDict:
366365
# await the answer from the server (be aware that the maximum
367366
# length of ISO-TP telegrams over the CAN bus is 4095 bytes)
368367
raw_response = await tester_recv(isotp_socket)

odxtools/additionalaudience.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: MIT
22
from dataclasses import dataclass
3-
from typing import Any, Dict, List
3+
from typing import Any
44
from xml.etree import ElementTree
55

66
from .element import IdentifiableElement
@@ -17,12 +17,12 @@ class AdditionalAudience(IdentifiableElement):
1717

1818
@staticmethod
1919
def from_et(et_element: ElementTree.Element,
20-
doc_frags: List[OdxDocFragment]) -> "AdditionalAudience":
20+
doc_frags: list[OdxDocFragment]) -> "AdditionalAudience":
2121
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
2222

2323
return AdditionalAudience(**kwargs)
2424

25-
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
25+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
2626
return {self.odx_id: self}
2727

2828
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:

odxtools/admindata.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: MIT
22
from dataclasses import dataclass
3-
from typing import Any, Dict, List, Optional
3+
from typing import Any, Optional
44
from xml.etree import ElementTree
55

66
from .companydocinfo import CompanyDocInfo
@@ -11,13 +11,13 @@
1111

1212
@dataclass
1313
class AdminData:
14-
language: Optional[str]
15-
company_doc_infos: List[CompanyDocInfo]
16-
doc_revisions: List[DocRevision]
14+
language: str | None
15+
company_doc_infos: list[CompanyDocInfo]
16+
doc_revisions: list[DocRevision]
1717

1818
@staticmethod
19-
def from_et(et_element: Optional[ElementTree.Element],
20-
doc_frags: List[OdxDocFragment]) -> Optional["AdminData"]:
19+
def from_et(et_element: ElementTree.Element | None,
20+
doc_frags: list[OdxDocFragment]) -> Optional["AdminData"]:
2121

2222
if et_element is None:
2323
return None
@@ -37,8 +37,8 @@ def from_et(et_element: Optional[ElementTree.Element],
3737
return AdminData(
3838
language=language, company_doc_infos=company_doc_infos, doc_revisions=doc_revisions)
3939

40-
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
41-
result: Dict[OdxLinkId, Any] = {}
40+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
41+
result: dict[OdxLinkId, Any] = {}
4242

4343
for cdi in self.company_doc_infos:
4444
result.update(cdi._build_odxlinks())

odxtools/audience.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: MIT
22
from dataclasses import dataclass
3-
from typing import Any, Dict, List, Optional
3+
from typing import Any
44
from xml.etree import ElementTree
55

66
from .additionalaudience import AdditionalAudience
@@ -12,14 +12,14 @@
1212

1313
@dataclass
1414
class Audience:
15-
enabled_audience_refs: List[OdxLinkRef]
16-
disabled_audience_refs: List[OdxLinkRef]
15+
enabled_audience_refs: list[OdxLinkRef]
16+
disabled_audience_refs: list[OdxLinkRef]
1717

18-
is_supplier_raw: Optional[bool]
19-
is_development_raw: Optional[bool]
20-
is_manufacturing_raw: Optional[bool]
21-
is_aftersales_raw: Optional[bool]
22-
is_aftermarket_raw: Optional[bool]
18+
is_supplier_raw: bool | None
19+
is_development_raw: bool | None
20+
is_manufacturing_raw: bool | None
21+
is_aftersales_raw: bool | None
22+
is_aftermarket_raw: bool | None
2323

2424
@property
2525
def is_supplier(self) -> bool:
@@ -50,7 +50,7 @@ def disabled_audiences(self) -> NamedItemList[AdditionalAudience]:
5050
return self._disabled_audiences
5151

5252
@staticmethod
53-
def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "Audience":
53+
def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "Audience":
5454

5555
enabled_audience_refs = [
5656
OdxLinkRef.from_et(ref, doc_frags)
@@ -78,7 +78,7 @@ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) ->
7878
is_aftermarket_raw=is_aftermarket_raw,
7979
)
8080

81-
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
81+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
8282
return {}
8383

8484
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:

odxtools/basecomparam.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: MIT
22
from dataclasses import dataclass
3-
from typing import Any, Dict, List, Optional, cast
3+
from typing import Any, cast
44
from xml.etree import ElementTree
55

66
from .element import IdentifiableElement
@@ -16,11 +16,11 @@
1616
class BaseComparam(IdentifiableElement):
1717
param_class: str
1818
cptype: StandardizationLevel
19-
display_level: Optional[int]
20-
cpusage: Optional[Usage] # Required in ODX 2.2, missing in ODX 2.0
19+
display_level: int | None
20+
cpusage: Usage | None # Required in ODX 2.2, missing in ODX 2.0
2121

2222
@staticmethod
23-
def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "BaseComparam":
23+
def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "BaseComparam":
2424
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
2525

2626
param_class = odxrequire(et_element.attrib.get("PARAM-CLASS"))
@@ -52,7 +52,7 @@ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) ->
5252
cpusage=cpusage,
5353
**kwargs)
5454

55-
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
55+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
5656
return {self.odx_id: self}
5757

5858
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:

odxtools/basevariantpattern.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# SPDX-License-Identifier: MIT
22
from dataclasses import dataclass
3-
from typing import List, Union
43
from xml.etree import ElementTree
54

65
from typing_extensions import override
@@ -17,11 +16,11 @@ class BaseVariantPattern(VariantPattern):
1716
"""Base variant patterns are variant patterns used to identify the
1817
base variant of an ECU.
1918
"""
20-
matching_base_variant_parameters: List[MatchingBaseVariantParameter]
19+
matching_base_variant_parameters: list[MatchingBaseVariantParameter]
2120

2221
@staticmethod
2322
def from_et(et_element: ElementTree.Element,
24-
doc_frags: List[OdxDocFragment]) -> "BaseVariantPattern":
23+
doc_frags: list[OdxDocFragment]) -> "BaseVariantPattern":
2524

2625
matching_base_variant_parameters = [
2726
MatchingBaseVariantParameter.from_et(mbvp_el, doc_frags)
@@ -33,6 +32,6 @@ def from_et(et_element: ElementTree.Element,
3332
return BaseVariantPattern(matching_base_variant_parameters=matching_base_variant_parameters)
3433

3534
@override
36-
def get_matching_parameters(
37-
self) -> Union[List[MatchingParameter], List[MatchingBaseVariantParameter]]:
35+
def get_matching_parameters(self
36+
) -> list[MatchingParameter] | list[MatchingBaseVariantParameter]:
3837
return self.matching_base_variant_parameters

odxtools/basicstructure.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: MIT
22
from dataclasses import dataclass
3-
from typing import Any, Dict, List, Optional
3+
from typing import Any
44
from xml.etree import ElementTree
55

66
from typing_extensions import override
@@ -30,20 +30,20 @@ class BasicStructure(ComplexDop):
3030
data objects. All structure-like objects adhere to the
3131
`CompositeCodec` type protocol.
3232
"""
33-
byte_size: Optional[int]
33+
byte_size: int | None
3434
parameters: NamedItemList[Parameter]
3535

3636
@property
37-
def required_parameters(self) -> List[Parameter]:
37+
def required_parameters(self) -> list[Parameter]:
3838
return composite_codec_get_required_parameters(self)
3939

4040
@property
41-
def free_parameters(self) -> List[Parameter]:
41+
def free_parameters(self) -> list[Parameter]:
4242
return composite_codec_get_free_parameters(self)
4343

4444
@staticmethod
4545
def from_et(et_element: ElementTree.Element,
46-
doc_frags: List[OdxDocFragment]) -> "BasicStructure":
46+
doc_frags: list[OdxDocFragment]) -> "BasicStructure":
4747
"""Read a BASIC-STRUCTURE."""
4848
kwargs = dataclass_fields_asdict(ComplexDop.from_et(et_element, doc_frags))
4949

@@ -56,7 +56,7 @@ def from_et(et_element: ElementTree.Element,
5656

5757
return BasicStructure(byte_size=byte_size, parameters=parameters, **kwargs)
5858

59-
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
59+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
6060
result = super()._build_odxlinks()
6161

6262
for param in self.parameters:
@@ -79,7 +79,7 @@ def _resolve_snrefs(self, context: SnRefContext) -> None:
7979

8080
context.parameters = None
8181

82-
def get_static_bit_length(self) -> Optional[int]:
82+
def get_static_bit_length(self) -> int | None:
8383
# Explicit size was specified, so we do not need to look at
8484
# the list of parameters
8585
if self.byte_size is not None:
@@ -96,7 +96,7 @@ def print_free_parameters_info(self) -> None:
9696
print(parameter_info(self.free_parameters), end="")
9797

9898
@override
99-
def encode_into_pdu(self, physical_value: Optional[ParameterValue],
99+
def encode_into_pdu(self, physical_value: ParameterValue | None,
100100
encode_state: EncodeState) -> None:
101101
orig_pos = encode_state.cursor_byte_position
102102

0 commit comments

Comments
 (0)