Skip to content

Commit 7415c53

Browse files
authored
Merge pull request #396 from nada-ben-ali/NaBe/fix_supportsbytes_check_for_py3.12
Fix SupportsBytes Behavior Change in Python 3.12
2 parents 5cc2c95 + 95238a7 commit 7415c53

7 files changed

+29
-22
lines changed

odxtools/dataobjectproperty.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from .physicaltype import PhysicalType
1818
from .snrefcontext import SnRefContext
1919
from .unit import Unit
20-
from .utils import dataclass_fields_asdict
20+
from .utils import BytesTypes, dataclass_fields_asdict
2121

2222

2323
@dataclass
@@ -120,7 +120,7 @@ def encode_into_pdu(self, physical_value: ParameterValue, encode_state: EncodeSt
120120
f"The value {repr(physical_value)} of type {type(physical_value).__name__}"
121121
f" is not a valid.")
122122

123-
if not isinstance(physical_value, (int, float, str, bytes, bytearray)):
123+
if not isinstance(physical_value, (int, float, str, BytesTypes)):
124124
odxraise(f"Invalid type '{type(physical_value).__name__}' for physical value. "
125125
f"(Expect atomic type!)")
126126
internal_value = self.compu_method.convert_physical_to_internal(physical_value)

odxtools/encodestate.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# SPDX-License-Identifier: MIT
22
import warnings
33
from dataclasses import dataclass, field
4-
from typing import TYPE_CHECKING, Dict, List, Optional, SupportsBytes, Tuple
4+
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
55

66
from .encoding import Encoding, get_string_encoding
77
from .exceptions import EncodeError, OdxWarning, odxassert, odxraise
88
from .odxtypes import AtomicOdxType, DataType, ParameterValue
9+
from .utils import BytesTypes
910

1011
try:
1112
import bitstruct.c as bitstruct
@@ -97,7 +98,7 @@ def emplace_atomic_value(
9798

9899
# Deal with raw byte fields, ...
99100
if base_data_type == DataType.A_BYTEFIELD:
100-
if not isinstance(internal_value, (bytes, bytearray, SupportsBytes)):
101+
if not isinstance(internal_value, BytesTypes):
101102
odxraise(f"{internal_value!r} is not a bytefield", EncodeError)
102103
return
103104

odxtools/matchingparameter.py

+3-2
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, SupportsBytes, cast
3+
from typing import Any, Dict, List, Optional, cast
44
from xml.etree import ElementTree
55

66
from .diaglayers.diaglayer import DiagLayer
@@ -10,6 +10,7 @@
1010
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, resolve_snref
1111
from .odxtypes import ParameterValue, ParameterValueDict
1212
from .snrefcontext import SnRefContext
13+
from .utils import BytesTypes
1314

1415

1516
@dataclass
@@ -104,7 +105,7 @@ def __matches(self, param_dict: ParameterValue, snpath_chunks: List[str]) -> boo
104105
# allow a slight tolerance if the expected value is
105106
# floating point
106107
return abs(float(self.expected_value) - parameter_value) < 1e-8
107-
elif isinstance(parameter_value, (bytearray, SupportsBytes)):
108+
elif isinstance(parameter_value, BytesTypes):
108109
return parameter_value.hex().upper() == self.expected_value.upper()
109110
elif isinstance(parameter_value, DiagnosticTroubleCode):
110111
# TODO: what happens if non-numerical DTCs like

odxtools/minmaxlengthtype.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
from .diagcodedtype import DctType, DiagCodedType
1111
from .encodestate import EncodeState
1212
from .encoding import get_string_encoding
13-
from .exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequire
13+
from .exceptions import (DecodeError, EncodeError, odxassert, odxraise, odxrequire)
1414
from .odxlink import OdxDocFragment
1515
from .odxtypes import AtomicOdxType, DataType
16-
from .utils import dataclass_fields_asdict
16+
from .utils import BytesTypes, dataclass_fields_asdict
1717

1818

1919
class Termination(Enum):
@@ -83,7 +83,7 @@ def __termination_sequence(self) -> bytes:
8383
@override
8484
def encode_into_pdu(self, internal_value: AtomicOdxType, encode_state: EncodeState) -> None:
8585

86-
if not isinstance(internal_value, (bytes, str, bytearray)):
86+
if not isinstance(internal_value, (str, BytesTypes)):
8787
odxraise("MinMaxLengthType is currently only implemented for strings and byte arrays",
8888
EncodeError)
8989

odxtools/odxtypes.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from xml.etree import ElementTree
66

77
from .exceptions import odxassert, odxraise, odxrequire
8+
from .utils import BytesTypes
89

910
if TYPE_CHECKING:
1011
from odxtools.diagnostictroublecode import DiagnosticTroubleCode
@@ -135,8 +136,8 @@ def compare_odx_values(a: AtomicOdxType, b: AtomicOdxType) -> int:
135136

136137
# bytefields are treated like long integers: to pad the shorter
137138
# object with zeros and treat the results like strings.
138-
if isinstance(a, (bytes, bytearray)):
139-
if not isinstance(b, (bytes, bytearray)):
139+
if isinstance(a, BytesTypes):
140+
if not isinstance(b, BytesTypes):
140141
odxraise()
141142

142143
obj_len = max(len(a), len(b))
@@ -237,7 +238,7 @@ def isinstance(self, value: Any) -> bool:
237238
return True
238239
elif expected_type is float and isinstance(value, (int, float)):
239240
return True
240-
elif self == DataType.A_BYTEFIELD and isinstance(value, (bytearray, bytes)):
241+
elif self == DataType.A_BYTEFIELD and isinstance(value, BytesTypes):
241242
return True
242243
else:
243244
return False

odxtools/standardlengthtype.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
from typing import List, Literal, Optional
44
from xml.etree import ElementTree
55

6-
from typing_extensions import SupportsBytes, override
6+
from typing_extensions import override
77

88
from .decodestate import DecodeState
99
from .diagcodedtype import DctType, DiagCodedType
1010
from .encodestate import EncodeState
1111
from .exceptions import odxassert, odxraise, odxrequire
1212
from .odxlink import OdxDocFragment
1313
from .odxtypes import AtomicOdxType, DataType, odxstr_to_bool
14-
from .utils import dataclass_fields_asdict
14+
from .utils import BytesTypes, dataclass_fields_asdict
1515

1616

1717
@dataclass
@@ -91,7 +91,7 @@ def __get_used_mask(self, internal_value: AtomicOdxType) -> Optional[bytes]:
9191
return used_mask.to_bytes((bit_sz + 7) // 8, endianness)
9292

9393
sz: int
94-
if isinstance(internal_value, (bytearray, SupportsBytes)):
94+
if isinstance(internal_value, BytesTypes):
9595
sz = len(bytes(internal_value))
9696
else:
9797
sz = (odxrequire(self.get_static_bit_length()) + 7) // 8
@@ -107,7 +107,7 @@ def __apply_mask(self, internal_value: AtomicOdxType) -> AtomicOdxType:
107107

108108
if self.is_condensed:
109109
int_value: int
110-
if isinstance(internal_value, (bytearray, SupportsBytes)):
110+
if isinstance(internal_value, BytesTypes):
111111
int_value = int.from_bytes(internal_value, 'big')
112112
elif isinstance(internal_value, int):
113113
int_value = internal_value
@@ -126,14 +126,14 @@ def __apply_mask(self, internal_value: AtomicOdxType) -> AtomicOdxType:
126126

127127
mask_bit += 1
128128

129-
if isinstance(internal_value, (bytearray, SupportsBytes)):
129+
if isinstance(internal_value, BytesTypes):
130130
return result.to_bytes(len(internal_value), 'big')
131131

132132
return result
133133

134134
if isinstance(internal_value, int):
135135
return internal_value & self.bit_mask
136-
if isinstance(internal_value, (bytearray, SupportsBytes)):
136+
if isinstance(internal_value, BytesTypes):
137137
int_value = int.from_bytes(internal_value, 'big')
138138
int_value &= self.bit_mask
139139
return int_value.to_bytes(len(bytes(internal_value)), 'big')
@@ -146,7 +146,7 @@ def __unapply_mask(self, raw_value: AtomicOdxType) -> AtomicOdxType:
146146
return raw_value
147147
if self.is_condensed:
148148
int_value: int
149-
if isinstance(raw_value, (bytearray, SupportsBytes)):
149+
if isinstance(raw_value, BytesTypes):
150150
int_value = int.from_bytes(raw_value, 'big')
151151
elif isinstance(raw_value, int):
152152
int_value = raw_value
@@ -164,16 +164,16 @@ def __unapply_mask(self, raw_value: AtomicOdxType) -> AtomicOdxType:
164164

165165
mask_bit += 1
166166

167-
if isinstance(raw_value, (bytearray, SupportsBytes)):
167+
if isinstance(raw_value, BytesTypes):
168168
return result.to_bytes(len(raw_value), 'big')
169169

170170
return result
171171
if isinstance(raw_value, int):
172172
return raw_value & self.bit_mask
173-
if isinstance(raw_value, (bytearray, SupportsBytes)):
173+
if isinstance(raw_value, BytesTypes):
174174
int_value = int.from_bytes(raw_value, 'big')
175175
int_value &= self.bit_mask
176-
return int_value
176+
return int_value.to_bytes(len(raw_value), 'big')
177177

178178
odxraise(f'Can not apply a bit_mask on a value of type {type(raw_value)}')
179179
return raw_value

odxtools/utils.py

+4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33
import re
44
from typing import TYPE_CHECKING, Any, Dict, Optional
55

6+
from typing_extensions import SupportsBytes
7+
68
if TYPE_CHECKING:
79
from .database import Database
810
from .diaglayers.diaglayer import DiagLayer
911
from .snrefcontext import SnRefContext
1012

13+
BytesTypes = (bytearray, bytes, SupportsBytes)
14+
1115

1216
def retarget_snrefs(database: "Database",
1317
diag_layer: "DiagLayer",

0 commit comments

Comments
 (0)