• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Project-OSmOSE / OSEkit / 19831033427

01 Dec 2025 05:08PM UTC coverage: 96.981% (+0.03%) from 96.955%
19831033427

Pull #307

github

web-flow
Merge 92d3f5588 into 27d210a34
Pull Request #307: [DRAFT] Relative paths

41 of 42 new or added lines in 6 files covered. (97.62%)

13 existing lines in 5 files now uncovered.

3951 of 4074 relevant lines covered (96.98%)

0.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.36
/src/osekit/core_api/base_file.py
1
"""BaseFile: Base class for the File objects.
2

3
A File object associates file-written data to timestamps.
4
"""
5

6
from __future__ import annotations
1✔
7

8
import os
1✔
9
from typing import TYPE_CHECKING
1✔
10

11
from osekit.config import (
1✔
12
    TIMESTAMP_FORMAT_EXPORTED_FILES_LOCALIZED,
13
    TIMESTAMP_FORMATS_EXPORTED_FILES,
14
)
15
from osekit.utils.timestamp_utils import localize_timestamp
1✔
16

17
if TYPE_CHECKING:
18
    from os import PathLike
19

20
    import numpy as np
21
    import pytz
22
    from pandas import Timestamp
23

24
from pathlib import Path
1✔
25

26
from pandas import Timedelta
1✔
27

28
from osekit.core_api.event import Event
1✔
29
from osekit.utils.timestamp_utils import strptime_from_text
1✔
30

31

32
class BaseFile(Event):
1✔
33
    """Base class for the File objects.
34

35
    A File object associates file-written data to timestamps.
36
    """
37

38
    def __init__(
1✔
39
        self,
40
        path: PathLike | str,
41
        relative_root: PathLike | str | None = None,
42
        begin: Timestamp | None = None,
43
        end: Timestamp | None = None,
44
        strptime_format: str | list[str] | None = None,
45
        timezone: str | pytz.timezone | None = None,
46
    ) -> None:
47
        """Initialize a File object with a path and timestamps.
48

49
        The begin timestamp can either be provided as a parameter
50
        or parsed from the filename according to the provided strptime_format.
51

52
        Parameters
53
        ----------
54
        path: PathLike | str
55
            Full path to the file.
56
        relative_root: PathLike | str | None
57
            Root path according to which the path is specified.
58
            If None, the path is absolute.
59
        begin: pandas.Timestamp | None
60
            Timestamp corresponding to the first data point in the file.
61
            If it is not provided, strptime_format is mandatory.
62
            If both begin and strptime_format are provided,
63
            begin will overrule the timestamp embedded in the filename.
64
        end: pandas.Timestamp | None
65
            (Optional) Timestamp after the last data point in the file.
66
        strptime_format: str | None
67
            The strptime format used in the text.
68
            It should use valid strftime codes (https://strftime.org/).
69
            Example: '%y%m%d_%H:%M:%S'.
70
        timezone: str | pytz.timezone | None
71
            The timezone in which the file should be localized.
72
            If None, the file begin/end will be tz-naive.
73
            If different from a timezone parsed from the filename, the timestamps'
74
            timezone will be converted from the parsed timezone
75
            to the specified timezone.
76

77
        """
78
        self.relative_root = relative_root
1✔
79
        self.path = Path(path)
1✔
80

81
        if begin is None and strptime_format is None:
1✔
UNCOV
82
            raise ValueError("Either begin or strptime_format must be specified")
×
83

84
        self.begin = (
1✔
85
            begin
86
            if begin is not None
87
            else strptime_from_text(
88
                text=self.path.name,
89
                datetime_template=strptime_format,
90
            )
91
        )
92

93
        if timezone:
1✔
94
            self.begin = localize_timestamp(self.begin, timezone)
1✔
95

96
        self.end = end if end is not None else (self.begin + Timedelta(seconds=1))
1✔
97

98
    @property
1✔
99
    def relative_root(self) -> Path | None:
1✔
100
        """Root path according to which the path is specified.
101

102
        If None, the path is absolute.
103
        """
104
        return self._relative_root
1✔
105

106
    @relative_root.setter
1✔
107
    def relative_root(self, relative_root: Path | None) -> None:
1✔
108
        self._relative_root = relative_root
1✔
109

110
    @property
1✔
111
    def path(self) -> Path:
1✔
112
        """Absolute path of the file."""
113
        return (
1✔
114
            self.relative_root / self.relative_path
115
            if self.relative_root
116
            else self.relative_path
117
        )
118

119
    @path.setter
1✔
120
    def path(self, path: PathLike | str) -> None:
1✔
121
        path = Path(path)
1✔
122
        self._path = (
1✔
123
            os.path.relpath(path, self.relative_root) if self.relative_root else path
124
        )
125

126
    @property
1✔
127
    def relative_path(self) -> Path:
1✔
128
        """Path of the file relative to the relative_root path."""
129
        return self._path
1✔
130

131
    def read(self, start: Timestamp, stop: Timestamp) -> np.ndarray:
1✔
132
        """Return the data that is between start and stop from the file.
133

134
        This is an abstract method and should be overridden with actual implementations.
135

136
        Parameters
137
        ----------
138
        start: pandas.Timestamp
139
            Timestamp corresponding to the first data point to read.
140
        stop: pandas.Timestamp
141
            Timestamp after the last data point to read.
142

143
        Returns
144
        -------
145
        The data between start and stop.
146

147
        """
148

149
    def to_dict(self) -> dict:
1✔
150
        """Serialize a BaseFile to a dictionary.
151

152
        Returns
153
        -------
154
        dict:
155
            The serialized dictionary representing the BaseFile.
156

157
        """
158
        return {
1✔
159
            "path": str(self.path),
160
            "begin": self.begin.strftime(TIMESTAMP_FORMAT_EXPORTED_FILES_LOCALIZED),
161
            "end": self.end.strftime(TIMESTAMP_FORMAT_EXPORTED_FILES_LOCALIZED),
162
        }
163

164
    @classmethod
1✔
165
    def from_dict(cls, serialized: dict) -> BaseFile:
1✔
166
        """Return a BaseFile object from a dictionary.
167

168
        Parameters
169
        ----------
170
        serialized: dict
171
            The serialized dictionary representing the BaseFile.
172

173
        Returns
174
        -------
175
        BaseFile:
176
            The deserialized BaseFile object.
177

178
        """
179
        path = serialized["path"]
1✔
180
        return cls(
1✔
181
            path=path,
182
            strptime_format=TIMESTAMP_FORMATS_EXPORTED_FILES,
183
        )
184

185
    def __hash__(self) -> int:
1✔
186
        """Overwrite hash magic method."""
187
        return hash(self.path)
1✔
188

189
    def __str__(self) -> str:
1✔
190
        """Overwrite __str__."""
191
        return self.begin.strftime(TIMESTAMP_FORMAT_EXPORTED_FILES_LOCALIZED)
1✔
192

193
    def __eq__(self, other: BaseFile):
1✔
194
        """Override __eq__."""
195
        if not isinstance(other, BaseFile):
1✔
196
            return False
×
197
        return self.path == other.path and super().__eq__(other)
1✔
198

199
    def move(self, folder: Path) -> None:
1✔
200
        """Move the file to the target folder.
201

202
        Parameters
203
        ----------
204
        folder: Path
205
            destination folder where the file will be moved.
206

207
        """
208
        destination_path = folder / self.path.name
1✔
209
        folder.mkdir(exist_ok=True, parents=True)
1✔
210
        self.path.rename(destination_path)
1✔
211
        self.path = destination_path
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc