1717import struct
1818import time
1919import zlib
20- from collections .abc import Generator
20+ from collections .abc import Generator , Iterator
2121from decimal import Decimal
2222from typing import Any , BinaryIO , Optional , Union , cast
2323
2424from ..message import Message
2525from ..typechecking import StringPathLike
2626from ..util import channel2int , dlc2len , len2dlc
27- from .generic import BinaryIOMessageReader , FileIOMessageWriter
27+ from .generic import BinaryIOMessageReader , BinaryIOMessageWriter
2828
2929TSystemTime = tuple [int , int , int , int , int , int , int , int ]
3030
@@ -104,7 +104,7 @@ class BLFParseError(Exception):
104104TIME_ONE_NANS_FACTOR = Decimal ("1e-9" )
105105
106106
107- def timestamp_to_systemtime (timestamp : float ) -> TSystemTime :
107+ def timestamp_to_systemtime (timestamp : Optional [ float ] ) -> TSystemTime :
108108 if timestamp is None or timestamp < 631152000 :
109109 # Probably not a Unix timestamp
110110 return 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
@@ -146,8 +146,6 @@ class BLFReader(BinaryIOMessageReader):
146146 silently ignored.
147147 """
148148
149- file : BinaryIO
150-
151149 def __init__ (
152150 self ,
153151 file : Union [StringPathLike , BinaryIO ],
@@ -206,7 +204,7 @@ def __iter__(self) -> Generator[Message, None, None]:
206204 yield from self ._parse_container (data )
207205 self .stop ()
208206
209- def _parse_container (self , data ) :
207+ def _parse_container (self , data : bytes ) -> Iterator [ Message ] :
210208 if self ._tail :
211209 data = b"" .join ((self ._tail , data ))
212210 try :
@@ -217,7 +215,7 @@ def _parse_container(self, data):
217215 # Save the remaining data that could not be processed
218216 self ._tail = data [self ._pos :]
219217
220- def _parse_data (self , data ) :
218+ def _parse_data (self , data : bytes ) -> Iterator [ Message ] :
221219 """Optimized inner loop by making local copies of global variables
222220 and class members and hardcoding some values."""
223221 unpack_obj_header_base = OBJ_HEADER_BASE_STRUCT .unpack_from
@@ -375,13 +373,11 @@ def _parse_data(self, data):
375373 pos = next_pos
376374
377375
378- class BLFWriter (FileIOMessageWriter ):
376+ class BLFWriter (BinaryIOMessageWriter ):
379377 """
380378 Logs CAN data to a Binary Logging File compatible with Vector's tools.
381379 """
382380
383- file : BinaryIO
384-
385381 #: Max log container size of uncompressed data
386382 max_container_size = 128 * 1024
387383
@@ -412,14 +408,12 @@ def __init__(
412408 Z_DEFAULT_COMPRESSION represents a default compromise between
413409 speed and compression (currently equivalent to level 6).
414410 """
415- mode = "rb+" if append else "wb"
416411 try :
417- super ().__init__ (file , mode = mode )
412+ super ().__init__ (file , mode = "rb+" if append else "wb" )
418413 except FileNotFoundError :
419414 # Trying to append to a non-existing file, create a new one
420415 append = False
421- mode = "wb"
422- super ().__init__ (file , mode = mode )
416+ super ().__init__ (file , mode = "wb" )
423417 assert self .file is not None
424418 self .channel = channel
425419 self .compression_level = compression_level
@@ -452,7 +446,7 @@ def __init__(
452446 # Write a default header which will be updated when stopped
453447 self ._write_header (FILE_HEADER_SIZE )
454448
455- def _write_header (self , filesize ) :
449+ def _write_header (self , filesize : int ) -> None :
456450 header = [b"LOGG" , FILE_HEADER_SIZE , self .application_id , 0 , 0 , 0 , 2 , 6 , 8 , 1 ]
457451 # The meaning of "count of objects read" is unknown
458452 header .extend ([filesize , self .uncompressed_size , self .object_count , 0 ])
@@ -462,7 +456,7 @@ def _write_header(self, filesize):
462456 # Pad to header size
463457 self .file .write (b"\x00 " * (FILE_HEADER_SIZE - FILE_HEADER_STRUCT .size ))
464458
465- def on_message_received (self , msg ) :
459+ def on_message_received (self , msg : Message ) -> None :
466460 channel = channel2int (msg .channel )
467461 if channel is None :
468462 channel = self .channel
@@ -514,7 +508,7 @@ def on_message_received(self, msg):
514508 data = CAN_MSG_STRUCT .pack (channel , flags , msg .dlc , arb_id , can_data )
515509 self ._add_object (CAN_MESSAGE , data , msg .timestamp )
516510
517- def log_event (self , text , timestamp = None ):
511+ def log_event (self , text : str , timestamp : Optional [ float ] = None ) -> None :
518512 """Add an arbitrary message to the log file as a global marker.
519513
520514 :param str text:
@@ -525,17 +519,19 @@ def log_event(self, text, timestamp=None):
525519 """
526520 try :
527521 # Only works on Windows
528- text = text .encode ("mbcs" )
522+ encoded = text .encode ("mbcs" )
529523 except LookupError :
530- text = text .encode ("ascii" )
524+ encoded = text .encode ("ascii" )
531525 comment = b"Added by python-can"
532526 marker = b"python-can"
533527 data = GLOBAL_MARKER_STRUCT .pack (
534- 0 , 0xFFFFFF , 0xFF3300 , 0 , len (text ), len (marker ), len (comment )
528+ 0 , 0xFFFFFF , 0xFF3300 , 0 , len (encoded ), len (marker ), len (comment )
535529 )
536- self ._add_object (GLOBAL_MARKER , data + text + marker + comment , timestamp )
530+ self ._add_object (GLOBAL_MARKER , data + encoded + marker + comment , timestamp )
537531
538- def _add_object (self , obj_type , data , timestamp = None ):
532+ def _add_object (
533+ self , obj_type : int , data : bytes , timestamp : Optional [float ] = None
534+ ) -> None :
539535 if timestamp is None :
540536 timestamp = self .stop_timestamp or time .time ()
541537 if self .start_timestamp is None :
@@ -564,7 +560,7 @@ def _add_object(self, obj_type, data, timestamp=None):
564560 if self ._buffer_size >= self .max_container_size :
565561 self ._flush ()
566562
567- def _flush (self ):
563+ def _flush (self ) -> None :
568564 """Compresses and writes data in the buffer to file."""
569565 if self .file .closed :
570566 return
@@ -578,7 +574,7 @@ def _flush(self):
578574 self ._buffer = [tail ]
579575 self ._buffer_size = len (tail )
580576 if not self .compression_level :
581- data = uncompressed_data
577+ data : "Union[bytes, memoryview[int]]" = uncompressed_data # noqa: UP037
582578 method = NO_COMPRESSION
583579 else :
584580 data = zlib .compress (uncompressed_data , self .compression_level )
@@ -601,7 +597,7 @@ def file_size(self) -> int:
601597 """Return an estimate of the current file size in bytes."""
602598 return self .file .tell () + self ._buffer_size
603599
604- def stop (self ):
600+ def stop (self ) -> None :
605601 """Stops logging and closes the file."""
606602 self ._flush ()
607603 if self .file .seekable ():
0 commit comments