Skip to content

Commit

Permalink
Add back PdoBase.export() dependency (canmatrix) (#493)
Browse files Browse the repository at this point in the history
The canmatrix optional dependency was removed on Oct 10, 2021 with commit
c46228f. It is now added back as an optional dependency, using the same
name as previously: db_export.

To install the dependency:

$ python3 -m pip install 'canopen[db_export]'

Resolves #488
  • Loading branch information
erlend-aasland authored Jul 9, 2024
1 parent 08eba81 commit 6bd39ba
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 31 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
fail-fast: false
matrix:
python-version: ['3.x']
features: ['', '[db_export]']

steps:
- uses: actions/checkout@v3
Expand All @@ -28,7 +29,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install pytest pytest-cov
pip install -e .
pip install -e '.${{ matrix.features }}'
- name: Test with pytest
run: |
pytest -v --cov=canopen --cov-report=xml --cov-branch
Expand Down
14 changes: 12 additions & 2 deletions canopen/pdo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,24 @@ def subscribe(self):
def export(self, filename):
"""Export current configuration to a database file.
.. note::
This API requires the ``db_export`` feature to be installed::
python3 -m pip install 'canopen[db_export]'
:param str filename:
Filename to save to (e.g. DBC, DBF, ARXML, KCD etc)
:raises NotImplementedError:
When the ``canopen[db_export]`` feature is not installed.
:return: The CanMatrix object created
:rtype: canmatrix.canmatrix.CanMatrix
"""
from canmatrix import canmatrix
from canmatrix import formats
try:
from canmatrix import canmatrix
from canmatrix import formats
except ImportError:
raise NotImplementedError("This feature requires the 'canopen[db_export]' feature")

db = canmatrix.CanMatrix()
for pdo_map in self.map.values():
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ dependencies = [
]
dynamic = ["version"]

[project.optional-dependencies]
db_export = [
"canmatrix ~= 1.0",
]

[project.urls]
documentation = "https://canopen.readthedocs.io/en/stable/"
repository = "https://github.com/christiansandberg/canopen"
Expand Down
77 changes: 49 additions & 28 deletions test/test_pdo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,41 @@


class TestPDO(unittest.TestCase):

def test_bit_mapping(self):
def setUp(self):
node = canopen.Node(1, SAMPLE_EDS)
map = node.pdo.tx[1]
map.add_variable('INTEGER16 value') # 0x2001
map.add_variable('UNSIGNED8 value', length=4) # 0x2002
map.add_variable('INTEGER8 value', length=4) # 0x2003
map.add_variable('INTEGER32 value') # 0x2004
map.add_variable('BOOLEAN value', length=1) # 0x2005
map.add_variable('BOOLEAN value 2', length=1) # 0x2006
pdo = node.pdo.tx[1]
pdo.add_variable('INTEGER16 value') # 0x2001
pdo.add_variable('UNSIGNED8 value', length=4) # 0x2002
pdo.add_variable('INTEGER8 value', length=4) # 0x2003
pdo.add_variable('INTEGER32 value') # 0x2004
pdo.add_variable('BOOLEAN value', length=1) # 0x2005
pdo.add_variable('BOOLEAN value 2', length=1) # 0x2006

# Write some values
map['INTEGER16 value'].raw = -3
map['UNSIGNED8 value'].raw = 0xf
map['INTEGER8 value'].raw = -2
map['INTEGER32 value'].raw = 0x01020304
map['BOOLEAN value'].raw = False
map['BOOLEAN value 2'].raw = True
pdo['INTEGER16 value'].raw = -3
pdo['UNSIGNED8 value'].raw = 0xf
pdo['INTEGER8 value'].raw = -2
pdo['INTEGER32 value'].raw = 0x01020304
pdo['BOOLEAN value'].raw = False
pdo['BOOLEAN value 2'].raw = True

self.pdo = pdo
self.node = node

# Check expected data
self.assertEqual(map.data, b'\xfd\xff\xef\x04\x03\x02\x01\x02')
def test_pdo_map_bit_mapping(self):
self.assertEqual(self.pdo.data, b'\xfd\xff\xef\x04\x03\x02\x01\x02')

# Read values from data
self.assertEqual(map['INTEGER16 value'].raw, -3)
self.assertEqual(map['UNSIGNED8 value'].raw, 0xf)
self.assertEqual(map['INTEGER8 value'].raw, -2)
self.assertEqual(map['INTEGER32 value'].raw, 0x01020304)
self.assertEqual(map['BOOLEAN value'].raw, False)
self.assertEqual(map['BOOLEAN value 2'].raw, True)
def test_pdo_map_getitem(self):
pdo = self.pdo
self.assertEqual(pdo['INTEGER16 value'].raw, -3)
self.assertEqual(pdo['UNSIGNED8 value'].raw, 0xf)
self.assertEqual(pdo['INTEGER8 value'].raw, -2)
self.assertEqual(pdo['INTEGER32 value'].raw, 0x01020304)
self.assertEqual(pdo['BOOLEAN value'].raw, False)
self.assertEqual(pdo['BOOLEAN value 2'].raw, True)

def test_pdo_getitem(self):
node = self.node
self.assertEqual(node.tpdo[1]['INTEGER16 value'].raw, -3)
self.assertEqual(node.tpdo[1]['UNSIGNED8 value'].raw, 0xf)
self.assertEqual(node.tpdo[1]['INTEGER8 value'].raw, -2)
Expand All @@ -54,10 +59,26 @@ def test_bit_mapping(self):
self.assertEqual(node.tpdo[0x2002].raw, 0xf)
self.assertEqual(node.pdo[0x1600][0x2002].raw, 0xf)

def test_save_pdo(self):
node = canopen.Node(1, SAMPLE_EDS)
node.tpdo.save()
node.rpdo.save()
def test_pdo_save(self):
self.node.tpdo.save()
self.node.rpdo.save()

def test_pdo_export(self):
import tempfile
try:
import canmatrix
except ImportError:
raise unittest.SkipTest("The PDO export API requires canmatrix")

for pdo in "tpdo", "rpdo":
with tempfile.NamedTemporaryFile(suffix=".csv") as tmp:
fn = tmp.name
with self.subTest(filename=fn, pdo=pdo):
getattr(self.node, pdo).export(fn)
with open(fn) as csv:
header = csv.readline()
self.assertIn("ID", header)
self.assertIn("Frame Name", header)


if __name__ == "__main__":
Expand Down

0 comments on commit 6bd39ba

Please sign in to comment.