Skip to content

Commit

Permalink
Minor fixes to get code up to date
Browse files Browse the repository at this point in the history
* Use __future__ import annotation to avoid "Node" quotes
* Simplify main
* Add odg list --minus function
  • Loading branch information
sveinse committed Dec 3, 2024
1 parent 3ecc247 commit f1c5e85
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 40 deletions.
21 changes: 11 additions & 10 deletions src/objdictgen/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
from __future__ import annotations

import argparse
import functools
import getopt
import logging
import sys
from dataclasses import dataclass, field
from typing import Callable, Sequence, TypeVar

from colorama import Fore, Style, init

import objdictgen
from objdictgen import jsonod
from objdictgen import ODG_PROGRAM, __version__, jsonod
from objdictgen.node import Node
from objdictgen.printing import format_diff_nodes, format_node
from objdictgen.typing import TPath
from objdictgen.utils import exc_amend

T = TypeVar('T')

Expand Down Expand Up @@ -66,13 +66,13 @@ def inner(*args, **kw):
except Exception as exc: # pylint: disable=broad-except
if opts.show_debug:
raise
print(f"{objdictgen.ODG_PROGRAM}: {exc.__class__.__name__}: {exc}")
print(f"{ODG_PROGRAM}: {exc.__class__.__name__}: {exc}")
sys.exit(1)
return inner
return decorator


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

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

return od
except Exception as exc:
jsonod.exc_amend(exc, f"{fname}: ")
exc_amend(exc, f"{fname}: ")
raise


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

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

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

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


# -- HELP command --
if opts.command == "help":
if opts.subcommand:
Expand Down Expand Up @@ -288,9 +289,9 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):

errcode = 1 if lines else 0
if errcode:
print(f"{objdictgen.ODG_PROGRAM}: '{opts.od1}' and '{opts.od2}' differ")
print(f"{ODG_PROGRAM}: '{opts.od1}' and '{opts.od2}' differ")
else:
print(f"{objdictgen.ODG_PROGRAM}: '{opts.od1}' and '{opts.od2}' are equal")
print(f"{ODG_PROGRAM}: '{opts.od1}' and '{opts.od2}' are equal")

if errcode:
parser.exit(errcode)
Expand Down
9 changes: 5 additions & 4 deletions src/objdictgen/eds_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
from __future__ import annotations

import logging
import re
Expand Down Expand Up @@ -98,7 +99,7 @@
}


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


def generate_eds_content(node: "Node", filepath: TPath):
def generate_eds_content(node: Node, filepath: TPath):
"""Generate the EDS file content for the current node in the manager."""

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


def generate_cpj_content(nodelist: "NodeList"):
def generate_cpj_content(nodelist: NodeList):
"""Generate the CPJ file content for the nodelist."""
nodes = nodelist.SlaveNodes

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


def generate_node(filepath: TPath, nodeid: int = 0) -> "Node":
def generate_node(filepath: TPath, nodeid: int = 0) -> Node:
"""Generate a Node from an EDS file."""
# Create a new node
node = nodelib.Node(id=nodeid)
Expand Down
13 changes: 7 additions & 6 deletions src/objdictgen/gen_cfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
from __future__ import annotations

import re
from collections import UserDict
Expand Down Expand Up @@ -67,20 +68,20 @@ class Text:

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

def __init__(self, context: "CFileContext", text: str):
def __init__(self, context: CFileContext, text: str):
self.text: str = text
self.context: "CFileContext" = context
self.context: CFileContext = context

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

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

def __imod__(self, other: str) -> "Text":
def __imod__(self, other: str) -> Text:
"""Add a string to the text with formatting."""
self.text += other.format(**self.context)
return self
Expand Down Expand Up @@ -813,7 +814,7 @@ def generate_file_content(node: NodeProtocol, headerfile: str, pointers_dict=Non
# Main Function
# ------------------------------------------------------------------------------

def GenerateFile(filepath: TPath, node: "NodeProtocol", pointers_dict=None):
def GenerateFile(filepath: TPath, node: NodeProtocol, pointers_dict=None):
"""Main function to generate the C file from a object dictionary node."""
filepath = Path(filepath)
headerpath = filepath.with_suffix(".h")
Expand Down
21 changes: 11 additions & 10 deletions src/objdictgen/jsonod.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,20 @@
import logging
import re
from datetime import datetime
from typing import (TYPE_CHECKING, Any, Iterable, Mapping, Sequence, TypeVar, cast)
from typing import TYPE_CHECKING, Any, Iterable, Mapping, TypeVar, cast

import deepdiff # type: ignore[import] # Due to missing typing stubs for deepdiff
import deepdiff.model # type: ignore[import] # Due to missing typing stubs for deepdiff
import deepdiff.model # type: ignore[import] # Due to missing typing stubs for deepdiff
import jsonschema

import objdictgen
# Accessed by node.py, so we need to import node as module to avoid circular references
from objdictgen import maps
from objdictgen import node as nodelib
from objdictgen.maps import OD, ODMapping, ODMappingList
from objdictgen.typing import (TDiffNodes, TIndexEntry, TODJson, TODObjJson,
TODObj, TODSubObj, TODSubObjJson, TODValue, TParamEntry, TPath, TProfileMenu)
from objdictgen.typing import (TDiffNodes, TIndexEntry, TODJson, TODObj,
TODObjJson, TODSubObj, TODSubObjJson, TODValue,
TParamEntry, TPath, TProfileMenu)
from objdictgen.utils import (copy_in_order, exc_amend, maybe_number,
str_to_int, strip_brackets)

Expand Down Expand Up @@ -255,7 +256,7 @@ def member_compare(


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


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

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


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

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


def node_todict(node: "Node", sort=False, rich=True, internal=False, validate=True) -> TODJson:
def node_todict(node: Node, sort=False, rich=True, internal=False, validate=True) -> TODJson:
"""
Convert a node to dict representation for serialization.
Expand Down Expand Up @@ -666,7 +667,7 @@ def indexentry_to_jsondict(ientry: TIndexEntry) -> TODObjJson:
return obj


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

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


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

# Create the node and fill the most basic data
Expand Down
5 changes: 3 additions & 2 deletions src/objdictgen/maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
from __future__ import annotations

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

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

def FindMapVariableList(self, node: "Node", compute=True) -> Generator[tuple[int, int, int, str], None, None]:
def FindMapVariableList(self, node: Node, compute=True) -> Generator[tuple[int, int, int, str], None, None]:
"""
Generator of all variables that can be mapped to in pdos.
It yields tuple of (index, subindex, size, name)
Expand Down
7 changes: 4 additions & 3 deletions src/objdictgen/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
from __future__ import annotations

import copy
import logging
Expand Down Expand Up @@ -171,7 +172,7 @@ def isEds(filepath: TPath) -> bool:
return header == "[FileInfo]"

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

@staticmethod
def LoadJson(contents: str, validate=True) -> "Node":
def LoadJson(contents: str, validate=True) -> Node:
""" Import a new Node from a JSON string """
return jsonod.generate_node(contents, validate=validate)

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

def copy(self) -> "Node":
def copy(self) -> Node:
"""
Return a copy of the node
"""
Expand Down
5 changes: 3 additions & 2 deletions src/objdictgen/nosis.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
from __future__ import annotations

import ast
import io
Expand Down Expand Up @@ -306,10 +307,10 @@ def xmldump(filehandle: io.TextIOWrapper|None, py_obj: object,
return None


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

fh: "SupportsRead[str|bytes]" = filehandle # type: ignore[assignment]
fh: SupportsRead[str|bytes] = filehandle # type: ignore[assignment]
if isinstance(filehandle, str):
fh = io.StringIO(filehandle)
elif isinstance(filehandle, bytes):
Expand Down
3 changes: 2 additions & 1 deletion src/objdictgen/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
from __future__ import annotations

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

Profile: "ODMapping"
Profile: ODMapping
"""Mapping containing the object definitions for the profile."""

DefaultStringSize: int
Expand Down
3 changes: 2 additions & 1 deletion src/objdictgen/ui/commondialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
from __future__ import annotations

import logging
import os
Expand Down Expand Up @@ -1411,7 +1412,7 @@ class DCFEntryValuesTable(wx.grid.GridTableBase):
"""
A custom wxGrid Table using user supplied data
"""
def __init__(self, parent: "DCFEntryValuesDialog", data, colnames):
def __init__(self, parent: DCFEntryValuesDialog, data, colnames):
# The base class must be initialized *first*
wx.grid.GridTableBase.__init__(self)
self.data = data
Expand Down
3 changes: 2 additions & 1 deletion src/objdictgen/ui/subindextable.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
from __future__ import annotations

import codecs
import os
Expand Down Expand Up @@ -115,7 +116,7 @@ class SubindexTable(wx.grid.GridTableBase):
# Typing definitions
CurrentIndex: int

def __init__(self, parent: "EditingPanel", data, editors, colnames):
def __init__(self, parent: EditingPanel, data, editors, colnames):
# The base class must be initialized *first*
wx.grid.GridTableBase.__init__(self)
self.data = data
Expand Down

0 comments on commit f1c5e85

Please sign in to comment.