Skip to content

Commit a234bc9

Browse files
committed
Reworking the Gzipped ASC Reader/Writer
1 parent 0783a7c commit a234bc9

File tree

6 files changed

+61
-14
lines changed

6 files changed

+61
-14
lines changed

can/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
)
2626

2727
from .io import Logger, SizedRotatingLogger, Printer, LogReader, MessageSync
28-
from .io import ASCWriter, ASCReader, CompressedASCWriter, CompressedASCReader
28+
from .io import ASCWriter, ASCReader, GzipASCWriter, GzipASCReader
2929
from .io import BLFReader, BLFWriter
3030
from .io import CanutilsLogReader, CanutilsLogWriter
3131
from .io import CSVWriter, CSVReader

can/io/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .player import LogReader, MessageSync
99

1010
# Format specific
11-
from .asc import ASCWriter, ASCReader, CompressedASCWriter, CompressedASCReader
11+
from .asc import ASCWriter, ASCReader, GzipASCWriter, GzipASCReader
1212
from .blf import BLFReader, BLFWriter
1313
from .canutils import CanutilsLogReader, CanutilsLogWriter
1414
from .csv import CSVWriter, CSVReader

can/io/asc.py

+24-5
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
- under `test/data/logfile.asc`
77
"""
88
import gzip
9-
from typing import cast, Any, Generator, IO, List, Optional, Dict
9+
from typing import cast, Any, Generator, IO, List, Optional, Dict, Union
1010

1111
from datetime import datetime
1212
import time
1313
import logging
1414

15+
from .. import typechecking
1516
from ..message import Message
1617
from ..listener import Listener
1718
from ..util import channel2int
@@ -398,7 +399,7 @@ def on_message_received(self, msg: Message) -> None:
398399
self.log_event(serialized, msg.timestamp)
399400

400401

401-
class CompressedASCReader(ASCReader):
402+
class GzipASCReader(ASCReader):
402403
"""Gzipped version of :class:`~can.ASCReader`"""
403404

404405
def __init__(
@@ -418,12 +419,21 @@ def __init__(
418419
`relative` (starting at 0.0) or `absolute` (starting at
419420
the system time). Default `True = relative`.
420421
"""
421-
super(CompressedASCReader, self).__init__(
422+
self._fileobj = None
423+
if file is not None and (hasattr(file, "read") and hasattr(file, "write")):
424+
# file is None or some file-like object
425+
self._fileobj = file
426+
super(GzipASCReader, self).__init__(
422427
gzip.open(file, mode="rt"), base, relative_timestamp
423428
)
424429

430+
def stop(self) -> None:
431+
super(GzipASCReader, self).stop()
432+
if self._fileobj is not None:
433+
self._fileobj.close()
434+
425435

426-
class CompressedASCWriter(ASCWriter):
436+
class GzipASCWriter(ASCWriter):
427437
"""Gzipped version of :class:`~can.ASCWriter`"""
428438

429439
def __init__(
@@ -441,6 +451,15 @@ def __init__(
441451
:param compresslevel: Gzip compresslevel, see
442452
:class:`~gzip.GzipFile` for details. The default is 6.
443453
"""
444-
super(CompressedASCWriter, self).__init__(
454+
self._fileobj = None
455+
if file is not None and (hasattr(file, "read") and hasattr(file, "write")):
456+
# file is None or some file-like object
457+
self._fileobj = file
458+
super(GzipASCWriter, self).__init__(
445459
gzip.open(file, mode="wt", compresslevel=compresslevel), channel
446460
)
461+
462+
def stop(self) -> None:
463+
super(GzipASCWriter, self).stop()
464+
if self._fileobj is not None:
465+
self._fileobj.close()

can/io/logger.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from ..message import Message
2222
from ..listener import Listener
2323
from .generic import BaseIOHandler, FileIOMessageWriter
24-
from .asc import ASCWriter, CompressedASCWriter
24+
from .asc import ASCWriter, GzipASCWriter
2525
from .blf import BLFWriter
2626
from .canutils import CanutilsLogWriter
2727
from .csv import CSVWriter
@@ -55,7 +55,7 @@ class Logger(BaseIOHandler, Listener): # pylint: disable=abstract-method
5555
fetched_plugins = False
5656
message_writers = {
5757
".asc": ASCWriter,
58-
".asc.gz": CompressedASCWriter,
58+
".asc.gz": GzipASCWriter,
5959
".blf": BLFWriter,
6060
".csv": CSVWriter,
6161
".db": SqliteWriter,
@@ -85,7 +85,7 @@ def __new__( # type: ignore
8585
)
8686
Logger.fetched_plugins = True
8787

88-
suffix = pathlib.PurePath(filename).suffix.lower()
88+
suffix = "".join(s.lower() for s in pathlib.PurePath(filename).suffixes)
8989
try:
9090
return cast(
9191
Listener, Logger.message_writers[suffix](filename, *args, **kwargs)

can/io/player.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import can
1515

1616
from .generic import BaseIOHandler, MessageReader
17-
from .asc import ASCReader, CompressedASCReader
17+
from .asc import ASCReader, GzipASCReader
1818
from .blf import BLFReader
1919
from .canutils import CanutilsLogReader
2020
from .csv import CSVReader
@@ -50,7 +50,7 @@ class LogReader(BaseIOHandler):
5050
fetched_plugins = False
5151
message_readers = {
5252
".asc": ASCReader,
53-
".asc.gz": CompressedASCReader,
53+
".asc.gz": GzipASCReader,
5454
".blf": BLFReader,
5555
".csv": CSVReader,
5656
".db": SqliteReader,
@@ -77,7 +77,7 @@ def __new__( # type: ignore
7777
)
7878
LogReader.fetched_plugins = True
7979

80-
suffix = pathlib.PurePath(filename).suffix.lower()
80+
suffix = "".join(s.lower() for s in pathlib.PurePath(filename).suffixes)
8181
try:
8282
return typing.cast(
8383
MessageReader,

test/logformats_test.py

+29-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
1212
TODO: correctly set preserves_channel and adds_default_channel
1313
"""
14-
14+
import gzip
1515
import logging
1616
import unittest
1717
import tempfile
@@ -555,6 +555,34 @@ def test_can_and_canfd_error_frames(self):
555555
self.assertMessagesEqual(actual, expected_messages)
556556

557557

558+
class TestGzipASCFileFormat(ReaderWriterTest):
559+
"""Tests can.GzipASCWriter and can.GzipASCReader"""
560+
561+
def _setup_instance(self):
562+
super()._setup_instance_helper(
563+
can.GzipASCWriter,
564+
can.GzipASCReader,
565+
binary_file=True,
566+
check_comments=True,
567+
preserves_channel=False,
568+
adds_default_channel=0,
569+
)
570+
571+
def assertIncludesComments(self, filename):
572+
"""
573+
Ensures that all comments are literally contained in the given file.
574+
575+
:param filename: the path-like object to use
576+
"""
577+
if self.original_comments:
578+
# read the entire outout file
579+
with gzip.open(filename, "rt" if self.binary_file else "r") as file:
580+
output_contents = file.read()
581+
# check each, if they can be found in there literally
582+
for comment in self.original_comments:
583+
self.assertIn(comment, output_contents)
584+
585+
558586
class TestBlfFileFormat(ReaderWriterTest):
559587
"""Tests can.BLFWriter and can.BLFReader.
560588

0 commit comments

Comments
 (0)