Coverage for typed_stream/_impl/file_streams.py: 94%
51 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-12 21:24 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-12 21:24 +0000
1# Licensed under the EUPL-1.2 or later.
2# You may obtain a copy of the licence in all the official languages of the
3# European Union at https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
5"""Stream classes for streaming file data."""
7from __future__ import annotations
9from types import EllipsisType
10from typing import AnyStr, Literal
12from ._lazy_file_iterators import (
13 LazyFileIterator,
14 LazyFileIteratorRemovingEndsBytes,
15 LazyFileIteratorRemovingEndsStr,
16)
17from ._types import PathLikeType
18from ._typing import override
19from .stream import Stream
21__all__: tuple[Literal["BinaryFileStream"], Literal["FileStream"]] = (
22 "BinaryFileStream",
23 "FileStream",
24)
27class FileStreamBase(Stream[AnyStr]):
28 """ABC for file streams."""
30 _file_iterator: None | LazyFileIterator[AnyStr]
31 __slots__ = ("_file_iterator",)
33 def _close_source(self) -> None:
34 """Close the source of the Stream. Used in FileStream."""
35 if not self._file_iterator:
36 return
37 self._file_iterator.close()
38 self._file_iterator = None
40 @override
41 def _get_args(self) -> tuple[object, ...]:
42 """Return the args used to initializing self."""
43 if not self._file_iterator:
44 return (...,)
46 return (
47 self._file_iterator.path,
48 self._file_iterator.encoding,
49 # pylint: disable=unidiomatic-typecheck
50 type(self._file_iterator) is LazyFileIterator,
51 )
54class FileStream(FileStreamBase[str]):
55 """Lazily iterate over a file."""
57 __slots__ = ()
59 def __init__(
60 self,
61 data: PathLikeType | EllipsisType,
62 encoding: str = "UTF-8",
63 keep_line_ends: bool = False,
64 ) -> None:
65 """Create a new FileStream.
67 To create a finished FileStream do FileStream(...).
68 """
69 if isinstance(data, EllipsisType):
70 self._file_iterator = None
71 super().__init__(...)
72 return
74 self._file_iterator = (
75 LazyFileIterator(data, encoding=encoding)
76 if keep_line_ends
77 else LazyFileIteratorRemovingEndsStr(data, encoding=encoding)
78 )
79 super().__init__(self._file_iterator, self._close_source)
81 @classmethod
82 @override
83 def _module(cls) -> str:
84 if cls == FileStream:
85 return "typed_stream"
86 return cls.__module__
89class BinaryFileStream(FileStreamBase[bytes]):
90 """Lazily iterate over the lines of a file."""
92 __slots__ = ()
94 def __init__(
95 self,
96 data: PathLikeType | EllipsisType,
97 keep_line_ends: bool = False,
98 ) -> None:
99 """Create a new BinaryFileStream.
101 To create a finished BinaryFileStream do BinaryFileStream(...).
102 """
103 if isinstance(data, EllipsisType):
104 self._file_iterator = None
105 super().__init__(...)
106 return
108 self._file_iterator = (
109 LazyFileIterator(data)
110 if keep_line_ends
111 else LazyFileIteratorRemovingEndsBytes(data)
112 )
113 super().__init__(self._file_iterator, self._close_source)
115 @classmethod
116 @override
117 def _module(cls) -> str:
118 if cls == BinaryFileStream:
119 return "typed_stream"
120 return cls.__module__