Skip to content

Commit 3214a93

Browse files
committed
Refactor DCM parsing logic and update version to 0.1.5
1 parent 53196ea commit 3214a93

2 files changed

Lines changed: 39 additions & 41 deletions

File tree

dcm/dcm.py

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@
6868
# Patterns: properties
6969
VERSION_PATTERN: Final[Pattern[bytes]] = compile(rb"(\d\.\d)")
7070
PURE_INT_PATTERN: Final[Pattern[str]] = compile(r"[-+]?\d+")
71-
PURE_FLOAT_PATTERN: Final[Pattern[str]] = compile(r"[-+]?(?:\d+\.\d*|\.\d+)")
71+
PURE_FLOAT_PATTERN: Final[Pattern[str]] = compile(
72+
r"[-+]?(?:\d+\.\d*|\.\d+)(?:[eE][-+]?\d+)?"
73+
)
7274
TEXT_PATTERN: Final[Pattern[bytes]] = compile(rb'"(.*?)"')
7375
VARIANT_PATTERN: Final[Pattern[bytes]] = compile(rb"VAR\s+(.*?)=(.*)")
7476
AXIS_X_PATTERN: Final[Pattern[bytes]] = compile(rb"SSTX\s+(.*)")
@@ -219,17 +221,12 @@ def from_bytestream(cls, stream: BytesReadable, line: bytes) -> "Self":
219221
def value_or_text(self) -> str | float:
220222
return self.value if not isnan(self.value) else self.text
221223

222-
def as_number(
223-
self,
224-
raise_on_nan: bool = True,
225-
int_pattern: Pattern[str] = PURE_INT_PATTERN,
226-
float_pattern: Pattern[str] = PURE_FLOAT_PATTERN,
227-
) -> int | float | bool:
224+
def as_number(self, raise_on_nan: bool = True) -> int | float | bool:
228225
if isnan(self.value):
229226
text: str = self.text
230-
if int_pattern.fullmatch(text):
227+
if PURE_INT_PATTERN.fullmatch(text):
231228
return int(text)
232-
elif float_pattern.fullmatch(text):
229+
elif PURE_FLOAT_PATTERN.fullmatch(text):
233230
return float(text)
234231
elif text == "true":
235232
return True
@@ -1415,48 +1412,46 @@ def shallow_transfer(
14151412
)
14161413

14171414

1415+
@dataclass
14181416
class SystemConstants:
1419-
__constants__: dict[str, int | float | bool]
1420-
1421-
def __init__(self) -> None:
1422-
self.__constants__ = {}
1417+
__constants__: dict[str, int | float | bool] = field(
1418+
default_factory=dict
1419+
)
14231420

14241421
def __getattr__(self, name: str) -> int | float | bool:
1425-
value: int | float | bool | None = self.__constants__.get(name)
1422+
value: Optional[int | float | bool] = self.__constants__.get(name)
14261423
if value is not None:
14271424
return value
14281425
warnings.warn(
1429-
f"{name}라는 SYSTEM_CONSTANT가 없습니다. 대신 0을 반환합니다."
1426+
f"No System Constant found with name: {name}. Returning 0."
14301427
)
14311428
return 0
14321429

1433-
def from_a2l(self, a2l_filepath: str) -> int:
1430+
def from_a2l(self, a2l_filepath: FileDescriptorOrPath) -> int:
14341431
total_constants: int = 0
1435-
pattern = compile(r'SYSTEM_CONSTANT\s+"(\w+)"\s+"([^"]+)"')
1436-
with open(a2l_filepath, "r") as f:
1432+
pattern: Pattern[bytes] = compile(
1433+
rb'SYSTEM_CONSTANT\s+"(\w+)"\s+"([^"]+)"'
1434+
)
1435+
with open(a2l_filepath, "rb") as f:
14371436
for line in f:
1438-
match = pattern.search(line.strip())
1439-
if match:
1440-
value: float | int | str | bool
1441-
key, value = match.groups()
1442-
value = str(value).strip('"')
1443-
if "." in value:
1444-
try:
1445-
value = float(value)
1446-
except ValueError:
1447-
pass
1448-
else:
1449-
try:
1450-
value = int(value)
1451-
except ValueError:
1452-
lower_value = value.lower()
1453-
if lower_value == "true":
1454-
value = True
1455-
elif lower_value == "false":
1456-
value = False
1457-
if isinstance(value, (int, float, bool)):
1458-
self.__constants__[key] = value
1459-
total_constants += 1
1437+
match: Optional[Match[bytes]] = pattern.search(line.strip())
1438+
if match is None:
1439+
continue
1440+
bname, bvalue = match.groups()
1441+
name: str = bname.decode(errors="replace")
1442+
value: str = bvalue.decode(errors="replace")
1443+
if PURE_INT_PATTERN.fullmatch(value):
1444+
self.__constants__[name] = int(value)
1445+
elif PURE_FLOAT_PATTERN.fullmatch(value):
1446+
self.__constants__[name] = float(value)
1447+
elif value == "true":
1448+
self.__constants__[name] = True
1449+
elif value == "false":
1450+
self.__constants__[name] = False
1451+
else:
1452+
warnings.warn(f"Invalid SYSTEM_CONSTANT {name}: {value}")
1453+
continue
1454+
total_constants += 1
14601455
return total_constants
14611456

14621457

@@ -1529,3 +1524,6 @@ def _parse_name_without_keyword(line: bytes) -> str:
15291524

15301525
def _parse_values_without_keyword(line: bytes) -> Iterable[float]:
15311526
return (float(value) for value in line.strip().split()[1:])
1527+
1528+
1529+
SC = SystemConstants()

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "python-dcm"
3-
version = "0.1.4"
3+
version = "0.1.5"
44
description = "A high-performance Python package for handling ETAS DCM(Data Conversion Format) files used in engine calibration tools like INCA, MDA, EHANDBOOK, and CANape."
55
authors = ["c0sogi <dcas@naver.com>"]
66
license = "MIT"

0 commit comments

Comments
 (0)