File: internal-api.rst

package info (click to toggle)
python-can 3.3.2.final~github-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,172 kB
  • sloc: python: 10,208; makefile: 30; sh: 12
file content (120 lines) | stat: -rw-r--r-- 4,472 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
.. _internalapi:

Internal API
============

Here we document the odds and ends that are more helpful for creating your own interfaces
or listeners but generally shouldn't be required to interact with python-can.


.. _businternals:


Extending the ``BusABC`` class
------------------------------

Concrete implementations **must** implement the following:
    * :meth:`~can.BusABC.send` to send individual messages
    * :meth:`~can.BusABC._recv_internal` to receive individual messages
      (see note below!)
    * set the :attr:`~can.BusABC.channel_info` attribute to a string describing
      the underlying bus and/or channel

They **might** implement the following:
    * :meth:`~can.BusABC.flush_tx_buffer` to allow discarding any
      messages yet to be sent
    * :meth:`~can.BusABC.shutdown` to override how the bus should
      shut down
    * :meth:`~can.BusABC._send_periodic_internal` to override the software based
      periodic sending and push it down to the kernel or hardware.
    * :meth:`~can.BusABC._apply_filters` to apply efficient filters
      to lower level systems like the OS kernel or hardware.
    * :meth:`~can.BusABC._detect_available_configs` to allow the interface
      to report which configurations are currently available for new
      connections.
    * :meth:`~can.BusABC.state` property to allow reading and/or changing
      the bus state.

.. note::

    *TL;DR*: Only override :meth:`~can.BusABC._recv_internal`,
    never :meth:`~can.BusABC.recv` directly.

    Previously, concrete bus classes had to override :meth:`~can.BusABC.recv`
    directly instead of :meth:`~can.BusABC._recv_internal`, but that has
    changed to allow the abstract base class to handle in-software message
    filtering as a fallback. All internal interfaces now implement that new
    behaviour. Older (custom) interfaces might still be implemented like that
    and thus might not provide message filtering:


Concrete instances are usually created by :class:`can.Bus` which takes the users
configuration into account.


Bus Internals
~~~~~~~~~~~~~

Several methods are not documented in the main :class:`can.BusABC`
as they are primarily useful for library developers as opposed to
library users. This is the entire ABC bus class with all internal
methods:

.. autoclass:: can.BusABC
    :private-members:
    :special-members:
    :noindex:



About the IO module
-------------------

Handling of the different file formats is implemented in :mod:`can.io`.
Each file/IO type is within a separate module and ideally implements both a *Reader* and a *Writer*.
The reader usually extends :class:`can.io.generic.BaseIOHandler`, while
the writer often additionally extends :class:`can.Listener`,
to be able to be passed directly to a :class:`can.Notifier`.



Adding support for new file formats
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This assumes that you want to add a new file format, called *canstore*.
Ideally add both reading and writing support for the new file format, although this is not strictly required.

1. Create a new module: *can/io/canstore.py*
   (*or* simply copy some existing one like *can/io/csv.py*)
2. Implement a reader ``CanstoreReader`` (which often extends :class:`can.io.generic.BaseIOHandler`, but does not have to).
   Besides from a constructor, only ``__iter__(self)`` needs to be implemented.
3. Implement a writer ``CanstoreWriter`` (which often extends :class:`can.io.generic.BaseIOHandler` and :class:`can.Listener`, but does not have to).
   Besides from a constructor, only ``on_message_received(self, msg)`` needs to be implemented.
4. Add a case to ``can.io.player.LogReader``'s ``__new__()``.
5. Document the two new classes (and possibly additional helpers) with docstrings and comments.
   Please mention features and limitations of the implementation.
6. Add a short section to the bottom of *doc/listeners.rst*.
7. Add tests where appropriate, for example by simply adding a test case called
   `class TestCanstoreFileFormat(ReaderWriterTest)` to *test/logformats_test.py*.
   That should already handle all of the general testing.
   Just follow the way the other tests in there do it.
8. Add imports to *can/__init__py* and *can/io/__init__py* so that the
   new classes can be simply imported as *from can import CanstoreReader, CanstoreWriter*.



IO Utilities
~~~~~~~~~~~~


.. automodule:: can.io.generic
    :members:



Other Utilities
---------------


.. automodule:: can.util
    :members: