11"""
22Utilities and configuration file parsing.
33"""
4+
45import functools
56import warnings
6- from typing import Dict , Optional , Union
7+ from typing import Any , Callable , cast , Dict , Iterable , Tuple , Optional , Union
78from time import time , perf_counter , get_clock_info
8-
9- from can import typechecking
10-
119import json
1210import os
1311import os .path
1816
1917import can
2018from can .interfaces import VALID_INTERFACES
19+ from can import typechecking
2120
2221log = logging .getLogger ("can.util" )
2322
@@ -89,9 +88,8 @@ def load_environment_config(context: Optional[str] = None) -> Dict[str, str]:
8988 "bitrate" : "CAN_BITRATE" ,
9089 }
9190
92- context_suffix = "_{}" .format (context ) if context else ""
93-
94- can_config_key = "CAN_CONFIG" + context_suffix
91+ context_suffix = f"_{ context } " if context else ""
92+ can_config_key = f"CAN_CONFIG{ context_suffix } "
9593 config : Dict [str , str ] = json .loads (os .environ .get (can_config_key , "{}" ))
9694
9795 for key , val in mapper .items ():
@@ -104,7 +102,7 @@ def load_environment_config(context: Optional[str] = None) -> Dict[str, str]:
104102
105103def load_config (
106104 path : Optional [typechecking .AcceptedIOType ] = None ,
107- config = None ,
105+ config : Optional [ Dict [ str , Any ]] = None ,
108106 context : Optional [str ] = None ,
109107) -> typechecking .BusConfig :
110108 """
@@ -158,16 +156,19 @@ def load_config(
158156 config = {}
159157
160158 # use the given dict for default values
161- config_sources = [
162- given_config ,
163- can .rc ,
164- lambda _context : load_environment_config ( # pylint: disable=unnecessary-lambda
165- _context
166- ),
167- lambda _context : load_environment_config (),
168- lambda _context : load_file_config (path , _context ),
169- lambda _context : load_file_config (path ),
170- ]
159+ config_sources = cast (
160+ Iterable [Union [Dict [str , Any ], Callable [[Any ], Dict [str , Any ]]]],
161+ [
162+ given_config ,
163+ can .rc ,
164+ lambda _context : load_environment_config ( # pylint: disable=unnecessary-lambda
165+ _context
166+ ),
167+ lambda _context : load_environment_config (),
168+ lambda _context : load_file_config (path , _context ),
169+ lambda _context : load_file_config (path ),
170+ ],
171+ )
171172
172173 # Slightly complex here to only search for the file config if required
173174 for cfg in config_sources :
@@ -189,9 +190,7 @@ def load_config(
189190 config [key ] = None
190191
191192 if config ["interface" ] not in VALID_INTERFACES :
192- raise NotImplementedError (
193- "Invalid CAN Bus Type - {}" .format (config ["interface" ])
194- )
193+ raise NotImplementedError (f'Invalid CAN Bus Type "{ config ["interface" ]} "' )
195194
196195 if "bitrate" in config :
197196 config ["bitrate" ] = int (config ["bitrate" ])
@@ -216,30 +215,33 @@ def load_config(
216215 timing_conf [key ] = int (config [key ], base = 0 )
217216 del config [key ]
218217 if timing_conf :
219- timing_conf ["bitrate" ] = config . get ( "bitrate" )
218+ timing_conf ["bitrate" ] = config [ "bitrate" ]
220219 config ["timing" ] = can .BitTiming (** timing_conf )
221220
222- can .log .debug ("can config: {}" .format (config ))
223- return config
221+ can .log .debug ("can config: %s" , config )
222+
223+ return cast (typechecking .BusConfig , config )
224+
224225
226+ def set_logging_level (level_name : str ) -> None :
227+ """Set the logging level for the `"can"` logger.
225228
226- def set_logging_level (level_name : Optional [str ] = None ):
227- """Set the logging level for the "can" logger.
228- Expects one of: 'critical', 'error', 'warning', 'info', 'debug', 'subdebug'
229+ :param level_name: One of: `'critical'`, `'error'`, `'warning'`, `'info'`,
230+ `'debug'`, `'subdebug'`, or the value `None` (=default). Defaults to `'debug'`.
229231 """
230232 can_logger = logging .getLogger ("can" )
231233
232234 try :
233- can_logger .setLevel (getattr (logging , level_name .upper ())) # type: ignore
235+ can_logger .setLevel (getattr (logging , level_name .upper ()))
234236 except AttributeError :
235237 can_logger .setLevel (logging .DEBUG )
236- log .debug ("Logging set to {}" . format ( level_name ) )
238+ log .debug ("Logging set to %s" , level_name )
237239
238240
239241def len2dlc (length : int ) -> int :
240242 """Calculate the DLC from data length.
241243
242- :param int length: Length in number of bytes (0-64)
244+ :param length: Length in number of bytes (0-64)
243245
244246 :returns: DLC (0-15)
245247 """
@@ -261,20 +263,17 @@ def dlc2len(dlc: int) -> int:
261263 return CAN_FD_DLC [dlc ] if dlc <= 15 else 64
262264
263265
264- def channel2int (channel : Optional [Union [ typechecking .Channel ] ]) -> Optional [int ]:
266+ def channel2int (channel : Optional [typechecking .Channel ]) -> Optional [int ]:
265267 """Try to convert the channel to an integer.
266268
267269 :param channel:
268- Channel string (e.g. can0, CAN1) or integer
270+ Channel string (e.g. `" can0"`, `" CAN1"` ) or an integer
269271
270- :returns: Channel integer or `None` if unsuccessful
272+ :returns: Channel integer or `` None` ` if unsuccessful
271273 """
272- if channel is None :
273- return None
274274 if isinstance (channel , int ):
275275 return channel
276- # String and byte objects have a lower() method
277- if hasattr (channel , "lower" ):
276+ if isinstance (channel , str ):
278277 match = re .match (r".*(\d+)$" , channel )
279278 if match :
280279 return int (match .group (1 ))
@@ -299,35 +298,33 @@ def library_function(new_arg):
299298 def deco (f ):
300299 @functools .wraps (f )
301300 def wrapper (* args , ** kwargs ):
302- rename_kwargs (f .__name__ , kwargs , aliases )
301+ _rename_kwargs (f .__name__ , kwargs , aliases )
303302 return f (* args , ** kwargs )
304303
305304 return wrapper
306305
307306 return deco
308307
309308
310- def rename_kwargs (func_name , kwargs , aliases ):
309+ def _rename_kwargs (
310+ func_name : str , kwargs : Dict [str , str ], aliases : Dict [str , str ]
311+ ) -> None :
311312 """Helper function for `deprecated_args_alias`"""
312313 for alias , new in aliases .items ():
313314 if alias in kwargs :
314315 value = kwargs .pop (alias )
315316 if new is not None :
316- warnings .warn (
317- "{} is deprecated; use {}" .format (alias , new ), DeprecationWarning
318- )
317+ warnings .warn (f"{ alias } is deprecated; use { new } " , DeprecationWarning )
319318 if new in kwargs :
320319 raise TypeError (
321- "{} received both {} (deprecated) and {}" .format (
322- func_name , alias , new
323- )
320+ f"{ func_name } received both { alias } (deprecated) and { new } "
324321 )
325322 kwargs [new ] = value
326323 else :
327324 warnings .warn ("{} is deprecated" .format (alias ), DeprecationWarning )
328325
329326
330- def time_perfcounter_correlation ():
327+ def time_perfcounter_correlation () -> Tuple [ float , float ] :
331328 """Get the `perf_counter` value nearest to when time.time() is updated
332329
333330 Computed if the default timer used by `time.time` on this platform has a resolution
0 commit comments