Skip to content

Commit cabafb4

Browse files
committed
Merge branch 'develop' into issue1364_TimedRotatingLogger
2 parents 8aff574 + c4c396b commit cabafb4

34 files changed

+485
-297
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,12 @@ jobs:
9191
run: |
9292
pylint --rcfile=.pylintrc \
9393
can/**.py \
94+
can/io \
9495
setup.py \
95-
doc.conf \
96+
doc/conf.py \
9697
scripts/**.py \
97-
examples/**.py
98+
examples/**.py \
99+
can/interfaces/socketcan
98100
99101
format:
100102
runs-on: ubuntu-latest
@@ -127,7 +129,10 @@ jobs:
127129
pip install -r doc/doc-requirements.txt
128130
- name: Build documentation
129131
run: |
130-
python -m sphinx -Wan doc build
132+
python -m sphinx -Wan --keep-going doc build
133+
- name: Run doctest
134+
run: |
135+
python -m sphinx -b doctest -W --keep-going doc build
131136
- uses: actions/upload-artifact@v3
132137
with:
133138
name: sphinx-out

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ htmlcov/
5252
.cache
5353
nosetests.xml
5454
coverage.xml
55+
coverage.lcov
5556
*,cover
5657
.hypothesis/
5758
test.*

.pylintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ disable=invalid-name,
8181
# either give multiple identifier separated by comma (,) or put this option
8282
# multiple time (only on the command line, not in the configuration file where
8383
# it should appear only once). See also the "--disable" option for examples.
84-
enable=c-extension-no-member
84+
enable=c-extension-no-member,
85+
useless-suppression,
8586

8687

8788
[REPORTS]

can/bus.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,10 @@ def stop_all_periodic_tasks(self, remove_tasks: bool = True) -> None:
314314
def __iter__(self) -> Iterator[Message]:
315315
"""Allow iteration on messages as they are received.
316316
317-
>>> for msg in bus:
318-
... print(msg)
317+
.. code-block:: python
318+
319+
for msg in bus:
320+
print(msg)
319321
320322
321323
:yields:
@@ -352,9 +354,9 @@ def set_filters(
352354
353355
:param filters:
354356
A iterable of dictionaries each containing a "can_id",
355-
a "can_mask", and an optional "extended" key.
357+
a "can_mask", and an optional "extended" key::
356358
357-
>>> [{"can_id": 0x11, "can_mask": 0x21, "extended": False}]
359+
[{"can_id": 0x11, "can_mask": 0x21, "extended": False}]
358360
359361
A filter matches, when
360362
``<received_can_id> & can_mask == can_id & can_mask``.
@@ -464,7 +466,5 @@ class _SelfRemovingCyclicTask(CyclicSendTaskABC, ABC):
464466
Only needed for typing :meth:`Bus._periodic_tasks`. Do not instantiate.
465467
"""
466468

467-
def stop( # pylint: disable=arguments-differ
468-
self, remove_task: bool = True
469-
) -> None:
469+
def stop(self, remove_task: bool = True) -> None:
470470
raise NotImplementedError()

can/exceptions.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,21 @@ class CanError(Exception):
3232
3333
If specified, the error code is automatically appended to the message:
3434
35-
>>> # With an error code (it also works with a specific error):
36-
>>> error = CanOperationError(message="Failed to do the thing", error_code=42)
37-
>>> str(error)
38-
'Failed to do the thing [Error Code 42]'
39-
>>>
40-
>>> # Missing the error code:
41-
>>> plain_error = CanError(message="Something went wrong ...")
42-
>>> str(plain_error)
43-
'Something went wrong ...'
35+
.. testsetup:: canerror
36+
37+
from can import CanError, CanOperationError
38+
39+
.. doctest:: canerror
40+
41+
>>> # With an error code (it also works with a specific error):
42+
>>> error = CanOperationError(message="Failed to do the thing", error_code=42)
43+
>>> str(error)
44+
'Failed to do the thing [Error Code 42]'
45+
>>>
46+
>>> # Missing the error code:
47+
>>> plain_error = CanError(message="Something went wrong ...")
48+
>>> str(plain_error)
49+
'Something went wrong ...'
4450
4551
:param error_code:
4652
An optional error code to narrow down the cause of the fault

can/interface.py

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
import logging
99
from typing import Any, cast, Iterable, Type, Optional, Union, List
1010

11+
from . import util
1112
from .bus import BusABC
12-
from .util import load_config, deprecated_args_alias
1313
from .interfaces import BACKENDS
1414
from .exceptions import CanInterfaceNotImplementedError
1515
from .typechecking import AutoDetectedConfig, Channel
@@ -61,6 +61,13 @@ class Bus(BusABC): # pylint: disable=abstract-method
6161
Instantiates a CAN Bus of the given ``interface``, falls back to reading a
6262
configuration file from default locations.
6363
64+
.. note::
65+
Please note that while the arguments provided to this class take precedence
66+
over any existing values from configuration, it is possible that other parameters
67+
from the configuration may be added to the bus instantiation.
68+
This could potentially have unintended consequences. To prevent this,
69+
you may use the *ignore_config* parameter to ignore any existing configurations.
70+
6471
:param channel:
6572
Channel identification. Expected type is backend dependent.
6673
Set to ``None`` to let it be resolved automatically from the default
@@ -71,8 +78,13 @@ class Bus(BusABC): # pylint: disable=abstract-method
7178
Set to ``None`` to let it be resolved automatically from the default
7279
:ref:`configuration`.
7380
74-
:param args:
75-
``interface`` specific positional arguments.
81+
:param config_context:
82+
Extra 'context', that is passed to config sources.
83+
This can be used to select a section other than 'default' in the configuration file.
84+
85+
:param ignore_config:
86+
If ``True``, only the given arguments will be used for the bus instantiation. Existing
87+
configuration sources will be ignored.
7688
7789
:param kwargs:
7890
``interface`` specific keyword arguments.
@@ -88,25 +100,28 @@ class Bus(BusABC): # pylint: disable=abstract-method
88100
"""
89101

90102
@staticmethod
91-
@deprecated_args_alias(bustype="interface") # Deprecated since python-can 4.2
92-
def __new__( # type: ignore # pylint: disable=keyword-arg-before-vararg
103+
@util.deprecated_args_alias(
104+
deprecation_start="4.2.0",
105+
deprecation_end="5.0.0",
106+
bustype="interface",
107+
context="config_context",
108+
)
109+
def __new__( # type: ignore
93110
cls: Any,
94111
channel: Optional[Channel] = None,
95112
interface: Optional[str] = None,
96-
*args: Any,
113+
config_context: Optional[str] = None,
114+
ignore_config: bool = False,
97115
**kwargs: Any,
98116
) -> BusABC:
99117
# figure out the rest of the configuration; this might raise an error
100118
if interface is not None:
101119
kwargs["interface"] = interface
102120
if channel is not None:
103121
kwargs["channel"] = channel
104-
if "context" in kwargs:
105-
context = kwargs["context"]
106-
del kwargs["context"]
107-
else:
108-
context = None
109-
kwargs = load_config(config=kwargs, context=context)
122+
123+
if not ignore_config:
124+
kwargs = util.load_config(config=kwargs, context=config_context)
110125

111126
# resolve the bus class to use for that interface
112127
cls = _get_class_for_interface(kwargs["interface"])
@@ -115,17 +130,12 @@ def __new__( # type: ignore # pylint: disable=keyword-arg-before-vararg
115130
del kwargs["interface"]
116131

117132
# make sure the bus can handle this config format
118-
if "channel" not in kwargs:
119-
raise ValueError("'channel' argument missing")
120-
else:
121-
channel = kwargs["channel"]
122-
del kwargs["channel"]
123-
133+
channel = kwargs.pop("channel", channel)
124134
if channel is None:
125135
# Use the default channel for the backend
126-
bus = cls(*args, **kwargs)
136+
bus = cls(**kwargs)
127137
else:
128-
bus = cls(channel, *args, **kwargs)
138+
bus = cls(channel, **kwargs)
129139

130140
return cast(BusABC, bus)
131141

can/interfaces/ixxat/canlib_vcinpl.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ class IXXATBus(BusABC):
417417
}
418418

419419
@deprecated_args_alias(
420+
deprecation_start="4.0.0",
421+
deprecation_end="5.0.0",
420422
UniqueHardwareId="unique_hardware_id",
421423
rxFifoSize="rx_fifo_size",
422424
txFifoSize="tx_fifo_size",

can/interfaces/ixxat/canlib_vcinpl2.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ class IXXATBus(BusABC):
417417
"""
418418

419419
@deprecated_args_alias(
420+
deprecation_start="4.0.0",
421+
deprecation_end="5.0.0",
420422
UniqueHardwareId="unique_hardware_id",
421423
rxFifoSize="rx_fifo_size",
422424
txFifoSize="tx_fifo_size",

can/interfaces/kvaser/canlib.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -662,9 +662,18 @@ def get_stats(self) -> structures.BusStatistics:
662662
663663
Use like so:
664664
665-
>>> stats = bus.get_stats()
666-
>>> print(stats)
667-
std_data: 0, std_remote: 0, ext_data: 0, ext_remote: 0, err_frame: 0, bus_load: 0.0%, overruns: 0
665+
.. testsetup:: kvaser
666+
667+
from unittest.mock import Mock
668+
from can.interfaces.kvaser.structures import BusStatistics
669+
bus = Mock()
670+
bus.get_stats = Mock(side_effect=lambda: BusStatistics())
671+
672+
.. doctest:: kvaser
673+
674+
>>> stats = bus.get_stats()
675+
>>> print(stats)
676+
std_data: 0, std_remote: 0, ext_data: 0, ext_remote: 0, err_frame: 0, bus_load: 0.0%, overruns: 0
668677
669678
:returns: bus statistics.
670679
"""

0 commit comments

Comments
 (0)