Source code for tslist.tslist

# -*- coding: utf-8 -*-

# tslist
# ------
# timestamp with a list (created by auxilium)
#
# Author:   sonntagsgesicht
# Version:  0.1.2, copyright Friday, 11 October 2024
# Website:  https://github.com/sonntagsgesicht/tslist
# License:  Apache License 2.0 (see LICENSE file)


from datetime import datetime, date
from pprint import pformat
from typing import Callable, Any as DateType

from .parser import parse_datetime


class ts:

    def __init__(self, cls: Callable | None = None,
                 default: DateType | None = None):
        """returns timestamp in given date type"""
        self.cls = cls
        self.default = default

    def __call__(self, value: DateType | None = None):
        if self.cls is None or self.cls == datetime:
            return parse_datetime(value, self.default)
        if self.cls == date:
            return parse_datetime(value, self.default).date()
        return self.cls(value)


[docs] class TSList(list): def __init__(self, iterable=(), /): """TS filtered list :param iterable: iterable of items :return: list The TS filtered list enhances the standard `list <https://docs.python.org/3/library/stdtypes.html#list>`_ by filtering the list by `slices <https://docs.python.org/3/library/stdtypes.html#slices>`_ of types **T** differing from **int** in which (before comparision) any item **x** is converted to type **T** by calling **T(x)** >>> from tslist import TSList >>> l = 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9 >>> tsl = TSList(l) >>> tsl TSList([1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9]) >>> tsl[1.0:1.3] # filter all items between 1.0 (included) and 1.3 (excluded) TSList([1.0, 1.1, 1.2]) >>> tsl[1.0:1.31] TSList([1.0, 1.1, 1.2, 1.3]) >>> tsl[1.1] # filter all items at 1.1 TSList([1.1]) >>> tsl.append(1.1) >>> tsl[1.1] TSList([1.1, 1.1]) This becomes even more handy if list items admit conversions. >>> from datetime import timedelta, datetime >>> from tslist import TS >>> class Timedelta(timedelta): ... def __float__(self): ... return self.total_seconds() ... ... def __ts__(self): ... # used for conversion using tslist.TS ... return datetime(2000, 1, 1) + self >>> l = [Timedelta(d) for d in range(10, 15)] >>> tsl = TSList(l) >>> tsl TSList( [ Timedelta(days=10), Timedelta(days=11), Timedelta(days=12), Timedelta(days=13), Timedelta(days=14)] ) >>> list(map(float, tsl)) [864000.0, 950400.0, 1036800.0, 1123200.0, 1209600.0] >>> tsl[950400.:1209600.:2] TSList([Timedelta(days=11), Timedelta(days=13)]) >>> list(map(TS, tsl)) [TS(20000111), TS(20000112), TS(20000113), TS(20000114), TS(20000115)] >>> tsl[TS(20000112):TS(20000114)] TSList([Timedelta(days=11), Timedelta(days=12)]) See |TS()| for more detail on timestamp and datetime conversion. """ # noqa E501 # todo: what if iterable is dict {ts: obj}? super().__init__(iterable) def __getitem__(self, key): if isinstance(key, int): return super().__getitem__(key) if isinstance(key, tuple): return tuple(super().__getitem__(k) for k in key) cls = self.__class__ if not isinstance(key, slice): t = ts(key.__class__) return cls(v for v in self if t(v) == key) if isinstance(key.start, int) or isinstance(key.stop, int): # use default slice behavior return cls(super().__getitem__(key)) if key.start and key.stop: t_s, t_e = ts(key.start.__class__), ts(key.stop.__class__) r = (v for v in self if key.start <= t_s(v) and t_e(v) < key.stop) elif key.start: t = ts(key.start.__class__) r = (v for v in self if key.start <= t(v)) elif key.stop: t = ts(key.stop.__class__) r = (v for v in self if t(v) < key.stop) else: r = self if isinstance(key.step, int): # gives TSList[start:stop:step] := TSList[start:stop][::step] if key.step < 0: return cls(r)[-1::key.step] return cls(r)[0::key.step] elif key.step: cls = key.step.__class__.__name__ raise ValueError(f"slice steps of type {cls!r} do not work") return cls(r) def __str__(self): return super().__str__() def __repr__(self): c = self.__class__.__name__ s = super().__repr__() s = f"{c}({s})" if len(s) < 80: return s s = pformat(list(self), indent=2, sort_dicts=False) return f"{c}(\n{s}\n)"
[docs] def astype(self, dtype): return self.__class__(map(dtype, self))