Skip to content

Commit

Permalink
Rename Variable, Record and Array (#363) (#368)
Browse files Browse the repository at this point in the history
To create better distinction between the different Variable, Record and Array types used for different purposes. Helps development, as IDE/linters often only display base name of class.
  • Loading branch information
sveinse authored Sep 1, 2023
1 parent 3585837 commit 0285f58
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 128 deletions.
2 changes: 1 addition & 1 deletion canopen/node/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def _find_object(self, index, subindex):
# Index does not exist
raise SdoAbortedError(0x06020000)
obj = self.object_dictionary[index]
if not isinstance(obj, objectdictionary.Variable):
if not isinstance(obj, objectdictionary.ODVariable):
# Group or array
if subindex not in obj:
# Subindex does not exist
Expand Down
8 changes: 4 additions & 4 deletions canopen/node/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from canopen.nmt import NmtMaster
from canopen.emcy import EmcyConsumer
from canopen.pdo import TPDO, RPDO, PDO
from canopen.objectdictionary import Record, Array, Variable, ObjectDictionary
from canopen.objectdictionary import ODRecord, ODArray, ODVariable, ObjectDictionary
from canopen.node.base import BaseNode

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -148,10 +148,10 @@ def __load_configuration_helper(self, index, subindex, name, value):
def load_configuration(self):
''' Load the configuration of the node from the object dictionary.'''
for obj in self.object_dictionary.values():
if isinstance(obj, Record) or isinstance(obj, Array):
if isinstance(obj, ODRecord) or isinstance(obj, ODArray):
for subobj in obj.values():
if isinstance(subobj, Variable) and subobj.writable and (subobj.value is not None):
if isinstance(subobj, ODVariable) and subobj.writable and (subobj.value is not None):
self.__load_configuration_helper(subobj.index, subobj.subindex, subobj.name, subobj.value)
elif isinstance(obj, Variable) and obj.writable and (obj.value is not None):
elif isinstance(obj, ODVariable) and obj.writable and (obj.value is not None):
self.__load_configuration_helper(obj.index, None, obj.name, obj.value)
self.pdo.read() # reads the new configuration from the driver
62 changes: 34 additions & 28 deletions canopen/objectdictionary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def __init__(self):

def __getitem__(
self, index: Union[int, str]
) -> Union["Array", "Record", "Variable"]:
) -> Union["ODArray", "ODRecord", "ODVariable"]:
"""Get object from object dictionary by name or index."""
item = self.names.get(index) or self.indices.get(index)
if item is None:
Expand All @@ -112,7 +112,7 @@ def __getitem__(
return item

def __setitem__(
self, index: Union[int, str], obj: Union["Array", "Record", "Variable"]
self, index: Union[int, str], obj: Union["ODArray", "ODRecord", "ODVariable"]
):
assert index == obj.index or index == obj.name
self.add_object(obj)
Expand All @@ -131,35 +131,35 @@ def __len__(self) -> int:
def __contains__(self, index: Union[int, str]):
return index in self.names or index in self.indices

def add_object(self, obj: Union["Array", "Record", "Variable"]) -> None:
def add_object(self, obj: Union["ODArray", "ODRecord", "ODVariable"]) -> None:
"""Add object to the object dictionary.
:param obj:
Should be either one of
:class:`~canopen.objectdictionary.Variable`,
:class:`~canopen.objectdictionary.Record`, or
:class:`~canopen.objectdictionary.Array`.
:class:`~canopen.objectdictionary.ODVariable`,
:class:`~canopen.objectdictionary.ODRecord`, or
:class:`~canopen.objectdictionary.ODArray`.
"""
obj.parent = self
self.indices[obj.index] = obj
self.names[obj.name] = obj

def get_variable(
self, index: Union[int, str], subindex: int = 0
) -> Optional["Variable"]:
) -> Optional["ODVariable"]:
"""Get the variable object at specified index (and subindex if applicable).
:return: Variable if found, else `None`
:return: ODVariable if found, else `None`
"""
obj = self.get(index)
if isinstance(obj, Variable):
if isinstance(obj, ODVariable):
return obj
elif isinstance(obj, (Record, Array)):
elif isinstance(obj, (ODRecord, ODArray)):
return obj.get(subindex)


class Record(MutableMapping):
"""Groups multiple :class:`~canopen.objectdictionary.Variable` objects using
class ODRecord(MutableMapping):
"""Groups multiple :class:`~canopen.objectdictionary.ODVariable` objects using
subindices.
"""

Expand All @@ -178,13 +178,13 @@ def __init__(self, name: str, index: int):
self.subindices = {}
self.names = {}

def __getitem__(self, subindex: Union[int, str]) -> "Variable":
def __getitem__(self, subindex: Union[int, str]) -> "ODVariable":
item = self.names.get(subindex) or self.subindices.get(subindex)
if item is None:
raise KeyError("Subindex %s was not found" % subindex)
return item

def __setitem__(self, subindex: Union[int, str], var: "Variable"):
def __setitem__(self, subindex: Union[int, str], var: "ODVariable"):
assert subindex == var.subindex
self.add_member(var)

Expand All @@ -202,18 +202,18 @@ def __iter__(self) -> Iterable[int]:
def __contains__(self, subindex: Union[int, str]) -> bool:
return subindex in self.names or subindex in self.subindices

def __eq__(self, other: "Record") -> bool:
def __eq__(self, other: "ODRecord") -> bool:
return self.index == other.index

def add_member(self, variable: "Variable") -> None:
"""Adds a :class:`~canopen.objectdictionary.Variable` to the record."""
def add_member(self, variable: "ODVariable") -> None:
"""Adds a :class:`~canopen.objectdictionary.ODVariable` to the record."""
variable.parent = self
self.subindices[variable.subindex] = variable
self.names[variable.name] = variable


class Array(Mapping):
"""An array of :class:`~canopen.objectdictionary.Variable` objects using
class ODArray(Mapping):
"""An array of :class:`~canopen.objectdictionary.ODVariable` objects using
subindices.
Actual length of array must be read from the node using SDO.
Expand All @@ -234,7 +234,7 @@ def __init__(self, name: str, index: int):
self.subindices = {}
self.names = {}

def __getitem__(self, subindex: Union[int, str]) -> "Variable":
def __getitem__(self, subindex: Union[int, str]) -> "ODVariable":
var = self.names.get(subindex) or self.subindices.get(subindex)
if var is not None:
# This subindex is defined
Expand All @@ -243,7 +243,7 @@ def __getitem__(self, subindex: Union[int, str]) -> "Variable":
# Create a new variable based on first array item
template = self.subindices[1]
name = "%s_%x" % (template.name, subindex)
var = Variable(name, self.index, subindex)
var = ODVariable(name, self.index, subindex)
var.parent = self
for attr in ("data_type", "unit", "factor", "min", "max", "default",
"access_type", "description", "value_descriptions",
Expand All @@ -260,17 +260,17 @@ def __len__(self) -> int:
def __iter__(self) -> Iterable[int]:
return iter(sorted(self.subindices))

def __eq__(self, other: "Array") -> bool:
def __eq__(self, other: "ODArray") -> bool:
return self.index == other.index

def add_member(self, variable: "Variable") -> None:
"""Adds a :class:`~canopen.objectdictionary.Variable` to the record."""
def add_member(self, variable: "ODVariable") -> None:
"""Adds a :class:`~canopen.objectdictionary.ODVariable` to the record."""
variable.parent = self
self.subindices[variable.subindex] = variable
self.names[variable.name] = variable


class Variable:
class ODVariable:
"""Simple variable."""

STRUCT_TYPES = {
Expand All @@ -289,8 +289,8 @@ class Variable:

def __init__(self, name: str, index: int, subindex: int = 0):
#: The :class:`~canopen.ObjectDictionary`,
#: :class:`~canopen.objectdictionary.Record` or
#: :class:`~canopen.objectdictionary.Array` owning the variable
#: :class:`~canopen.objectdictionary.ODRecord` or
#: :class:`~canopen.objectdictionary.ODArray` owning the variable
self.parent = None
#: 16-bit address of the object in the dictionary
self.index = index
Expand Down Expand Up @@ -328,7 +328,7 @@ def __init__(self, name: str, index: int, subindex: int = 0):
self.pdo_mappable = False


def __eq__(self, other: "Variable") -> bool:
def __eq__(self, other: "ODVariable") -> bool:
return (self.index == other.index and
self.subindex == other.subindex)

Expand Down Expand Up @@ -486,3 +486,9 @@ def __init__(self):

class ObjectDictionaryError(Exception):
"""Unsupported operation with the current Object Dictionary."""


# Compatibility for old names
Record = ODRecord
Array = ODArray
Variable = ODVariable
24 changes: 12 additions & 12 deletions canopen/objectdictionary/eds.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def import_eds(source, node_id):
for i in range(1, 8):
key = "Dummy%04d" % i
if eds.getint(section, key) == 1:
var = objectdictionary.Variable(key, i, 0)
var = objectdictionary.ODVariable(key, i, 0)
var.data_type = i
var.access_type = "const"
od.add_object(var)
Expand All @@ -127,20 +127,20 @@ def import_eds(source, node_id):
var = build_variable(eds, section, node_id, index)
od.add_object(var)
elif object_type == ARR and eds.has_option(section, "CompactSubObj"):
arr = objectdictionary.Array(name, index)
last_subindex = objectdictionary.Variable(
arr = objectdictionary.ODArray(name, index)
last_subindex = objectdictionary.ODVariable(
"Number of entries", index, 0)
last_subindex.data_type = datatypes.UNSIGNED8
arr.add_member(last_subindex)
arr.add_member(build_variable(eds, section, node_id, index, 1))
arr.storage_location = storage_location
od.add_object(arr)
elif object_type == ARR:
arr = objectdictionary.Array(name, index)
arr = objectdictionary.ODArray(name, index)
arr.storage_location = storage_location
od.add_object(arr)
elif object_type == RECORD:
record = objectdictionary.Record(name, index)
record = objectdictionary.ODRecord(name, index)
record.storage_location = storage_location
od.add_object(record)

Expand All @@ -152,8 +152,8 @@ def import_eds(source, node_id):
index = int(match.group(1), 16)
subindex = int(match.group(2), 16)
entry = od[index]
if isinstance(entry, (objectdictionary.Record,
objectdictionary.Array)):
if isinstance(entry, (objectdictionary.ODRecord,
objectdictionary.ODArray)):
var = build_variable(eds, section, node_id, index, subindex)
entry.add_member(var)

Expand Down Expand Up @@ -257,7 +257,7 @@ def build_variable(eds, section, node_id, index, subindex=0):
:param subindex: Subindex of the CANOpen object (if presente, else 0)
"""
name = eds.get(section, "ParameterName")
var = objectdictionary.Variable(name, index, subindex)
var = objectdictionary.ODVariable(name, index, subindex)
try:
var.storage_location = eds.get(section, "StorageLocation")
except NoOptionError:
Expand Down Expand Up @@ -344,11 +344,11 @@ def export_dcf(od, dest=None, fileInfo={}):

def export_eds(od, dest=None, file_info={}, device_commisioning=False):
def export_object(obj, eds):
if isinstance(obj, objectdictionary.Variable):
if isinstance(obj, objectdictionary.ODVariable):
return export_variable(obj, eds)
if isinstance(obj, objectdictionary.Record):
if isinstance(obj, objectdictionary.ODRecord):
return export_record(obj, eds)
if isinstance(obj, objectdictionary.Array):
if isinstance(obj, objectdictionary.ODArray):
return export_array(obj, eds)

def export_common(var, eds, section):
Expand Down Expand Up @@ -404,7 +404,7 @@ def export_record(var, eds):
section = "%04X" % var.index
export_common(var, eds, section)
eds.set(section, "SubNumber", "0x%X" % len(var.subindices))
ot = RECORD if isinstance(var, objectdictionary.Record) else ARR
ot = RECORD if isinstance(var, objectdictionary.ODRecord) else ARR
eds.set(section, "ObjectType", "0x%X" % ot)
for i in var:
export_variable(var[i], eds)
Expand Down
6 changes: 3 additions & 3 deletions canopen/objectdictionary/epf.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def import_epf(epf):
od.add_object(var)
elif len(parameters) == 2 and parameters[1].get("ObjectType") == "ARRAY":
# Array
arr = objectdictionary.Array(name, index)
arr = objectdictionary.ODArray(name, index)
for par_tree in parameters:
var = build_variable(par_tree)
arr.add_member(var)
Expand All @@ -71,7 +71,7 @@ def import_epf(epf):
od.add_object(arr)
else:
# Complex record
record = objectdictionary.Record(name, index)
record = objectdictionary.ODRecord(name, index)
for par_tree in parameters:
var = build_variable(par_tree)
record.add_member(var)
Expand All @@ -89,7 +89,7 @@ def build_variable(par_tree):
name = par_tree.get("SymbolName")
data_type = par_tree.get("DataType")

par = objectdictionary.Variable(name, index, subindex)
par = objectdictionary.ODVariable(name, index, subindex)
factor = par_tree.get("Factor", "1")
par.factor = int(factor) if factor.isdigit() else float(factor)
unit = par_tree.get("Unit")
Expand Down
5 changes: 4 additions & 1 deletion canopen/pdo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import logging

from canopen import node
from canopen.pdo.base import PdoBase, Maps, Map, Variable
from canopen.pdo.base import PdoBase, Maps

# Compatibility
from .base import Variable

logger = logging.getLogger(__name__)

Expand Down
Loading

0 comments on commit 0285f58

Please sign in to comment.