Skip to content

Commit f1c5e85

Browse files
committed
Minor fixes to get code up to date
* Use __future__ import annotation to avoid "Node" quotes * Simplify main * Add odg list --minus function
1 parent 3ecc247 commit f1c5e85

File tree

10 files changed

+50
-40
lines changed

10 files changed

+50
-40
lines changed

src/objdictgen/__main__.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,22 @@
1616
# License along with this library; if not, write to the Free Software
1717
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
1818
# USA
19+
from __future__ import annotations
1920

2021
import argparse
2122
import functools
22-
import getopt
2323
import logging
2424
import sys
2525
from dataclasses import dataclass, field
2626
from typing import Callable, Sequence, TypeVar
2727

2828
from colorama import Fore, Style, init
2929

30-
import objdictgen
31-
from objdictgen import jsonod
30+
from objdictgen import ODG_PROGRAM, __version__, jsonod
3231
from objdictgen.node import Node
3332
from objdictgen.printing import format_diff_nodes, format_node
3433
from objdictgen.typing import TPath
34+
from objdictgen.utils import exc_amend
3535

3636
T = TypeVar('T')
3737

@@ -66,13 +66,13 @@ def inner(*args, **kw):
6666
except Exception as exc: # pylint: disable=broad-except
6767
if opts.show_debug:
6868
raise
69-
print(f"{objdictgen.ODG_PROGRAM}: {exc.__class__.__name__}: {exc}")
69+
print(f"{ODG_PROGRAM}: {exc.__class__.__name__}: {exc}")
7070
sys.exit(1)
7171
return inner
7272
return decorator
7373

7474

75-
def open_od(fname: TPath|str, validate=True, fix=False) -> "Node":
75+
def open_od(fname: TPath|str, validate=True, fix=False) -> Node:
7676
""" Open and validate the OD file"""
7777

7878
try:
@@ -83,7 +83,7 @@ def open_od(fname: TPath|str, validate=True, fix=False) -> "Node":
8383

8484
return od
8585
except Exception as exc:
86-
jsonod.exc_amend(exc, f"{fname}: ")
86+
exc_amend(exc, f"{fname}: ")
8787
raise
8888

8989

@@ -92,7 +92,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
9292
""" Main command dispatcher """
9393

9494
parser = argparse.ArgumentParser(
95-
prog=objdictgen.ODG_PROGRAM,
95+
prog=ODG_PROGRAM,
9696
description="""
9797
A tool to read and convert object dictionary files for the
9898
CAN festival library
@@ -113,7 +113,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
113113
opt_novalidate = dict(action='store_true', help="Don't validate input files")
114114
opt_nocolor = dict(action='store_true', help="Disable colored output")
115115

116-
parser.add_argument('--version', action='version', version='%(prog)s ' + objdictgen.__version__)
116+
parser.add_argument('--version', action='version', version='%(prog)s ' + __version__)
117117
parser.add_argument('--no-color', action='store_true', help="Disable colored output")
118118
parser.add_argument('-D', '--debug', **opt_debug) # type: ignore[arg-type]
119119

@@ -214,6 +214,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
214214
else:
215215
init()
216216

217+
217218
# -- HELP command --
218219
if opts.command == "help":
219220
if opts.subcommand:
@@ -288,9 +289,9 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
288289

289290
errcode = 1 if lines else 0
290291
if errcode:
291-
print(f"{objdictgen.ODG_PROGRAM}: '{opts.od1}' and '{opts.od2}' differ")
292+
print(f"{ODG_PROGRAM}: '{opts.od1}' and '{opts.od2}' differ")
292293
else:
293-
print(f"{objdictgen.ODG_PROGRAM}: '{opts.od1}' and '{opts.od2}' are equal")
294+
print(f"{ODG_PROGRAM}: '{opts.od1}' and '{opts.od2}' are equal")
294295

295296
if errcode:
296297
parser.exit(errcode)

src/objdictgen/eds_utils.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
# License along with this library; if not, write to the Free Software
1818
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
1919
# USA
20+
from __future__ import annotations
2021

2122
import logging
2223
import re
@@ -98,7 +99,7 @@
9899
}
99100

100101

101-
def get_default_value(node: "Node", index: int, subindex: int = -1):
102+
def get_default_value(node: Node, index: int, subindex: int = -1):
102103
"""Function that search into Node Mappings the informations about an index
103104
or a subindex and return the default value."""
104105
infos = node.GetEntryInfos(index)
@@ -484,7 +485,7 @@ def verify_value(values: dict[str, Any], section_name: str, param: str):
484485
raise ValueError(f"Error on section '[{section_name}]': '{param}' incompatible with DataType") from None
485486

486487

487-
def generate_eds_content(node: "Node", filepath: TPath):
488+
def generate_eds_content(node: Node, filepath: TPath):
488489
"""Generate the EDS file content for the current node in the manager."""
489490

490491
filepath = Path(filepath)
@@ -683,7 +684,7 @@ def generate_index_contents(name: str, entries: list[int]):
683684
return fileContent
684685

685686

686-
def generate_cpj_content(nodelist: "NodeList"):
687+
def generate_cpj_content(nodelist: NodeList):
687688
"""Generate the CPJ file content for the nodelist."""
688689
nodes = nodelist.SlaveNodes
689690

@@ -700,7 +701,7 @@ def generate_cpj_content(nodelist: "NodeList"):
700701
return filecontent
701702

702703

703-
def generate_node(filepath: TPath, nodeid: int = 0) -> "Node":
704+
def generate_node(filepath: TPath, nodeid: int = 0) -> Node:
704705
"""Generate a Node from an EDS file."""
705706
# Create a new node
706707
node = nodelib.Node(id=nodeid)

src/objdictgen/gen_cfile.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
# License along with this library; if not, write to the Free Software
1818
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
1919
# USA
20+
from __future__ import annotations
2021

2122
import re
2223
from collections import UserDict
@@ -67,20 +68,20 @@ class Text:
6768

6869
# FIXME: Remove all %= entries, use f-strings instead, and delete this class
6970

70-
def __init__(self, context: "CFileContext", text: str):
71+
def __init__(self, context: CFileContext, text: str):
7172
self.text: str = text
72-
self.context: "CFileContext" = context
73+
self.context: CFileContext = context
7374

74-
def __iadd__(self, other: "str|Text") -> "Text":
75+
def __iadd__(self, other: str|Text) -> Text:
7576
"""Add a string to the text without formatting."""
7677
self.text += str(other)
7778
return self
7879

79-
def __add__(self, other: "str|Text") -> "Text":
80+
def __add__(self, other: str|Text) -> Text:
8081
"""Add a string to the text without formatting."""
8182
return Text(self.context, self.text + str(other))
8283

83-
def __imod__(self, other: str) -> "Text":
84+
def __imod__(self, other: str) -> Text:
8485
"""Add a string to the text with formatting."""
8586
self.text += other.format(**self.context)
8687
return self
@@ -813,7 +814,7 @@ def generate_file_content(node: NodeProtocol, headerfile: str, pointers_dict=Non
813814
# Main Function
814815
# ------------------------------------------------------------------------------
815816

816-
def GenerateFile(filepath: TPath, node: "NodeProtocol", pointers_dict=None):
817+
def GenerateFile(filepath: TPath, node: NodeProtocol, pointers_dict=None):
817818
"""Main function to generate the C file from a object dictionary node."""
818819
filepath = Path(filepath)
819820
headerpath = filepath.with_suffix(".h")

src/objdictgen/jsonod.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,20 @@
2424
import logging
2525
import re
2626
from datetime import datetime
27-
from typing import (TYPE_CHECKING, Any, Iterable, Mapping, Sequence, TypeVar, cast)
27+
from typing import TYPE_CHECKING, Any, Iterable, Mapping, TypeVar, cast
2828

2929
import deepdiff # type: ignore[import] # Due to missing typing stubs for deepdiff
30-
import deepdiff.model # type: ignore[import] # Due to missing typing stubs for deepdiff
30+
import deepdiff.model # type: ignore[import] # Due to missing typing stubs for deepdiff
3131
import jsonschema
3232

3333
import objdictgen
3434
# Accessed by node.py, so we need to import node as module to avoid circular references
3535
from objdictgen import maps
3636
from objdictgen import node as nodelib
3737
from objdictgen.maps import OD, ODMapping, ODMappingList
38-
from objdictgen.typing import (TDiffNodes, TIndexEntry, TODJson, TODObjJson,
39-
TODObj, TODSubObj, TODSubObjJson, TODValue, TParamEntry, TPath, TProfileMenu)
38+
from objdictgen.typing import (TDiffNodes, TIndexEntry, TODJson, TODObj,
39+
TODObjJson, TODSubObj, TODSubObjJson, TODValue,
40+
TParamEntry, TPath, TProfileMenu)
4041
from objdictgen.utils import (copy_in_order, exc_amend, maybe_number,
4142
str_to_int, strip_brackets)
4243

@@ -255,7 +256,7 @@ def member_compare(
255256

256257

257258
def get_object_types(
258-
node: "Node|None" = None,
259+
node: Node|None = None,
259260
dictionary: list[TODObjJson]|None = None
260261
) -> tuple[dict[int, str], dict[str, int]]:
261262
""" Return two dicts with the object type mapping """
@@ -320,7 +321,7 @@ def compare_profile(profilename: TPath, params: ODMapping, menu: TProfileMenu|No
320321
return False, False
321322

322323

323-
def generate_jsonc(node: "Node", compact=False, sort=False, internal=False,
324+
def generate_jsonc(node: Node, compact=False, sort=False, internal=False,
324325
validate=True, jsonc=True) -> str:
325326
""" Export a JSONC string representation of the node """
326327

@@ -372,7 +373,7 @@ def generate_jsonc(node: "Node", compact=False, sort=False, internal=False,
372373
return text
373374

374375

375-
def generate_node(contents: str|TODJson, validate: bool = True) -> "Node":
376+
def generate_node(contents: str|TODJson, validate: bool = True) -> Node:
376377
""" Import from JSON string or objects """
377378

378379
if isinstance(contents, str):
@@ -413,7 +414,7 @@ def generate_node(contents: str|TODJson, validate: bool = True) -> "Node":
413414
return node_fromdict(jd, objtypes_s2i)
414415

415416

416-
def node_todict(node: "Node", sort=False, rich=True, internal=False, validate=True) -> TODJson:
417+
def node_todict(node: Node, sort=False, rich=True, internal=False, validate=True) -> TODJson:
417418
"""
418419
Convert a node to dict representation for serialization.
419420
@@ -666,7 +667,7 @@ def indexentry_to_jsondict(ientry: TIndexEntry) -> TODObjJson:
666667
return obj
667668

668669

669-
def rearrage_for_json(obj: TODObjJson, node: "Node", objtypes_i2s: dict[int, str], rich=True) -> TODObjJson:
670+
def rearrage_for_json(obj: TODObjJson, node: Node, objtypes_i2s: dict[int, str], rich=True) -> TODObjJson:
670671
""" Rearrange the object to fit the wanted JSON format """
671672

672673
# The struct describes what kind of object structure this object have
@@ -903,7 +904,7 @@ def validate_indexentry(ientry: TIndexEntry):
903904
raise ValidationError(f"Unexpexted count of subindexes in mapping object, found {len(nbmax)}")
904905

905906

906-
def node_fromdict(jd: TODJson, objtypes_s2i: dict[str, int]) -> "Node":
907+
def node_fromdict(jd: TODJson, objtypes_s2i: dict[str, int]) -> Node:
907908
""" Convert a dict jd into a Node """
908909

909910
# Create the node and fill the most basic data

src/objdictgen/maps.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
# License along with this library; if not, write to the Free Software
1818
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
1919
# USA
20+
from __future__ import annotations
2021

2122
import ast
2223
import itertools
@@ -500,7 +501,7 @@ def FindSubentryInfos(self, index: int, subindex: int, compute=True) -> TODSubOb
500501
return infos
501502
raise ValueError(f"Index 0x{index:04x} does not have subentries")
502503

503-
def FindMapVariableList(self, node: "Node", compute=True) -> Generator[tuple[int, int, int, str], None, None]:
504+
def FindMapVariableList(self, node: Node, compute=True) -> Generator[tuple[int, int, int, str], None, None]:
504505
"""
505506
Generator of all variables that can be mapped to in pdos.
506507
It yields tuple of (index, subindex, size, name)
@@ -615,7 +616,7 @@ def FindSubentryInfos(self, index: int, subindex: int, compute=True) -> TODSubOb
615616
except StopIteration:
616617
raise ValueError(f"Subindex 0x{index:04x}.{subindex:x} does not exist") from None
617618

618-
def FindMapVariableList(self, node: "Node", compute=True) -> Generator[tuple[int, int, int, str], None, None]:
619+
def FindMapVariableList(self, node: Node, compute=True) -> Generator[tuple[int, int, int, str], None, None]:
619620
"""
620621
Generator of all variables that can be mapped to in pdos.
621622
It yields tuple of (index, subindex, size, name)

src/objdictgen/node.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
# License along with this library; if not, write to the Free Software
1818
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
1919
# USA
20+
from __future__ import annotations
2021

2122
import copy
2223
import logging
@@ -171,7 +172,7 @@ def isEds(filepath: TPath) -> bool:
171172
return header == "[FileInfo]"
172173

173174
@staticmethod
174-
def LoadFile(filepath: TPath, **kwargs) -> "Node":
175+
def LoadFile(filepath: TPath, **kwargs) -> Node:
175176
""" Open a file and create a new node """
176177
if Node.isXml(filepath):
177178
log.debug("Loading XML OD '%s'", filepath)
@@ -187,7 +188,7 @@ def LoadFile(filepath: TPath, **kwargs) -> "Node":
187188
return Node.LoadJson(f.read(), **kwargs)
188189

189190
@staticmethod
190-
def LoadJson(contents: str, validate=True) -> "Node":
191+
def LoadJson(contents: str, validate=True) -> Node:
191192
""" Import a new Node from a JSON string """
192193
return jsonod.generate_node(contents, validate=validate)
193194

@@ -241,7 +242,7 @@ def asdict(self) -> dict[str, Any]:
241242
""" Return the class data as a dict """
242243
return copy.deepcopy(self.__dict__)
243244

244-
def copy(self) -> "Node":
245+
def copy(self) -> Node:
245246
"""
246247
Return a copy of the node
247248
"""

src/objdictgen/nosis.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
# License along with this library; if not, write to the Free Software
2323
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
2424
# USA
25+
from __future__ import annotations
2526

2627
import ast
2728
import io
@@ -306,10 +307,10 @@ def xmldump(filehandle: io.TextIOWrapper|None, py_obj: object,
306307
return None
307308

308309

309-
def xmlload(filehandle: "SupportsRead[str|bytes]|bytes|str") -> Any:
310+
def xmlload(filehandle: SupportsRead[str|bytes]|bytes|str) -> Any:
310311
"""Load pickled object from file fh."""
311312

312-
fh: "SupportsRead[str|bytes]" = filehandle # type: ignore[assignment]
313+
fh: SupportsRead[str|bytes] = filehandle # type: ignore[assignment]
313314
if isinstance(filehandle, str):
314315
fh = io.StringIO(filehandle)
315316
elif isinstance(filehandle, bytes):

src/objdictgen/typing.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# License along with this library; if not, write to the Free Software
1717
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
1818
# USA
19+
from __future__ import annotations
1920

2021
import os
2122
from typing import TYPE_CHECKING, Iterator, Protocol, TypedDict
@@ -108,7 +109,7 @@ class NodeProtocol(Protocol):
108109
ProfileName: str
109110
"""Name of any loaded profiles. "None" if no profile is loaded."""
110111

111-
Profile: "ODMapping"
112+
Profile: ODMapping
112113
"""Mapping containing the object definitions for the profile."""
113114

114115
DefaultStringSize: int

src/objdictgen/ui/commondialogs.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
# License along with this library; if not, write to the Free Software
1818
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
1919
# USA
20+
from __future__ import annotations
2021

2122
import logging
2223
import os
@@ -1411,7 +1412,7 @@ class DCFEntryValuesTable(wx.grid.GridTableBase):
14111412
"""
14121413
A custom wxGrid Table using user supplied data
14131414
"""
1414-
def __init__(self, parent: "DCFEntryValuesDialog", data, colnames):
1415+
def __init__(self, parent: DCFEntryValuesDialog, data, colnames):
14151416
# The base class must be initialized *first*
14161417
wx.grid.GridTableBase.__init__(self)
14171418
self.data = data

src/objdictgen/ui/subindextable.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
# License along with this library; if not, write to the Free Software
1818
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
1919
# USA
20+
from __future__ import annotations
2021

2122
import codecs
2223
import os
@@ -115,7 +116,7 @@ class SubindexTable(wx.grid.GridTableBase):
115116
# Typing definitions
116117
CurrentIndex: int
117118

118-
def __init__(self, parent: "EditingPanel", data, editors, colnames):
119+
def __init__(self, parent: EditingPanel, data, editors, colnames):
119120
# The base class must be initialized *first*
120121
wx.grid.GridTableBase.__init__(self)
121122
self.data = data

0 commit comments

Comments
 (0)