Skip to content

Commit 2fed532

Browse files
committed
Load user-installed interface modules only on demand if importlib is not installed
1 parent 054eceb commit 2fed532

File tree

3 files changed

+30
-11
lines changed

3 files changed

+30
-11
lines changed

can/interface.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
log_autodetect = log.getChild("detect_available_configs")
1919

2020

21-
def _get_class_for_interface(interface: str) -> Type[BusABC]:
21+
def _get_class_for_interface(interface: str, installed_interfaces: dict = None) -> Type[BusABC]:
2222
"""
2323
Returns the main bus class for the given interface.
2424
@@ -28,8 +28,10 @@ def _get_class_for_interface(interface: str) -> Type[BusABC]:
2828
if there was a problem while importing the interface or the bus class within that
2929
"""
3030
# Find the correct backend
31+
if not isinstance(installed_interfaces, dict):
32+
installed_interfaces = BACKENDS
3133
try:
32-
module_name, class_name = BACKENDS[interface]
34+
module_name, class_name = installed_interfaces[interface]
3335
except KeyError:
3436
raise NotImplementedError(
3537
"CAN interface '{}' not supported".format(interface)
@@ -149,6 +151,13 @@ def detect_available_configs(
149151

150152
# Figure out where to search
151153
if interfaces is None:
154+
try:
155+
from importlib.metadata import entry_points # If this works, the interfaces have probably been loaded
156+
except ImportError:
157+
from pkg_resources import iter_entry_points as entry_points
158+
entry = entry_points("can.interface")
159+
BACKENDS.update({interface.name: (interface.module_name, interface.attrs[0])
160+
for interface in entry})
152161
interfaces = BACKENDS
153162
elif isinstance(interfaces, str):
154163
interfaces = (interfaces,)
@@ -158,7 +167,7 @@ def detect_available_configs(
158167
for interface in interfaces:
159168

160169
try:
161-
bus_class = _get_class_for_interface(interface)
170+
bus_class = _get_class_for_interface(interface, installed_interfaces=BACKENDS)
162171
except CanInterfaceNotImplementedError:
163172
log_autodetect.debug(
164173
'interface "%s" cannot be loaded for detection of available configurations',

can/interfaces/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@
3333
if 'can.interface' in entry:
3434
BACKENDS.update({interface.name: tuple(interface.value.split(':')) for interface in entry['can.interface']})
3535
except ImportError:
36-
from pkg_resources import iter_entry_points as entry_points
37-
entry = entry_points("can.interface")
38-
BACKENDS.update({interface.name: (interface.module_name, interface.attrs[0]) for interface in entry})
36+
# from pkg_resources import iter_entry_points as entry_points
37+
# entry = entry_points("can.interface")
38+
# BACKENDS.update({interface.name: (interface.module_name, interface.attrs[0]) for interface in entry})
39+
pass
3940

4041
VALID_INTERFACES = frozenset(list(BACKENDS.keys()))

can/util.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from configparser import ConfigParser
1616

1717
import can
18-
from .interfaces import VALID_INTERFACES
18+
from .interfaces import VALID_INTERFACES, BACKENDS
1919
from . import typechecking
2020
from .exceptions import CanInterfaceNotImplementedError
2121

@@ -207,10 +207,19 @@ def _create_bus_config(config: Dict[str, Any]) -> typechecking.BusConfig:
207207
if key not in config:
208208
config[key] = None
209209

210-
if config["interface"] not in VALID_INTERFACES:
211-
raise CanInterfaceNotImplementedError(
212-
f'Unknown interface type "{config["interface"]}"'
213-
)
210+
# if config["interface"] not in VALID_INTERFACES:
211+
if config["interface"] not in BACKENDS.keys():
212+
try:
213+
from importlib.metadata import entry_points # If this works, the interfaces have probably been loaded
214+
except ImportError:
215+
from pkg_resources import iter_entry_points as entry_points
216+
entry = entry_points("can.interface")
217+
BACKENDS.update({interface.name: (interface.module_name, interface.attrs[0])
218+
for interface in entry})
219+
if config["interface"] not in BACKENDS.keys():
220+
raise CanInterfaceNotImplementedError(
221+
f'Unknown interface type "{config["interface"]}"'
222+
)
214223

215224
if "bitrate" in config:
216225
config["bitrate"] = int(config["bitrate"])

0 commit comments

Comments
 (0)