-
-
Notifications
You must be signed in to change notification settings - Fork 0
add pyright #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
add pyright #14
Changes from 8 commits
ebf7d4a
af0584d
c2c220a
73d386d
ebb3c89
140aea7
c9c94ac
a0736d7
dc8bea3
343d681
13d45c4
88598e5
b979524
9b5684c
345c157
e525a25
9e14c97
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,8 +1,9 @@ | ||||||||||||||||
| import math | ||||||||||||||||
| from datetime import date, datetime, timedelta | ||||||||||||||||
| from typing import Dict, Union | ||||||||||||||||
|
Comment on lines
1
to
2
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Python 3.8 compatibility: annotations will break without future import. You’re using PEP 585 generics (list[...] / tuple[...]) while supporting 3.8. Add the future import (or switch to typing.List/Tuple). This is a real runtime error on 3.8. +from __future__ import annotations
import math
from datetime import date, datetime, timedelta
-from typing import Dict, Union
+from typing import Dict, Union, ClassVar, Mapping, Type📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| def date_from_int(val, div=1): | ||||||||||||||||
| def date_from_int(val: int, div=1) -> date: | ||||||||||||||||
| val //= div | ||||||||||||||||
| d = val % 100 | ||||||||||||||||
| val //= 100 | ||||||||||||||||
|
|
@@ -11,26 +12,26 @@ def date_from_int(val, div=1): | |||||||||||||||
| return date(val, m, d) | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| def date_to_int(val, mul=1): | ||||||||||||||||
| def date_to_int(val: date, mul: int = 1) -> int: | ||||||||||||||||
| return mul * (val.year * 10000 + val.month * 100 + val.day) | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| class TimeunitKindMeta(type): | ||||||||||||||||
| kind_int = None | ||||||||||||||||
| formatter = None | ||||||||||||||||
| _pre_registered = [] | ||||||||||||||||
| _registered = None | ||||||||||||||||
| _multiplier = None | ||||||||||||||||
| kind_int: int = -1 | ||||||||||||||||
| formatter: str = "" | ||||||||||||||||
| _pre_registered: list["TimeunitKindMeta"] = [] | ||||||||||||||||
| _registered: Union[None, Dict[int, "TimeunitKindMeta"]] = None | ||||||||||||||||
| _multiplier: int = -1 | ||||||||||||||||
|
|
||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
| def __init__(cls, name, bases, attrs): | ||||||||||||||||
| def __init__(cls, name, bases, attrs) -> None: | ||||||||||||||||
| super().__init__(name, bases, attrs) | ||||||||||||||||
| if cls.kind_int is not None: | ||||||||||||||||
| TimeunitKindMeta._pre_registered.append(cls) | ||||||||||||||||
| TimeunitKindMeta._registered = None | ||||||||||||||||
| TimeunitKindMeta._multiplier = None | ||||||||||||||||
| TimeunitKindMeta._multiplier = -1 | ||||||||||||||||
|
|
||||||||||||||||
| @property | ||||||||||||||||
| def unit_register(self): | ||||||||||||||||
| def unit_register(self) -> Dict[int, "TimeunitKindMeta"]: | ||||||||||||||||
| result = TimeunitKindMeta._registered | ||||||||||||||||
| if result is None: | ||||||||||||||||
| result = { | ||||||||||||||||
|
|
@@ -42,27 +43,29 @@ def unit_register(self): | |||||||||||||||
| return result | ||||||||||||||||
|
|
||||||||||||||||
| @property | ||||||||||||||||
| def multiplier(cls): | ||||||||||||||||
| def multiplier(cls) -> int: | ||||||||||||||||
| result = TimeunitKindMeta._multiplier | ||||||||||||||||
| if result is None: | ||||||||||||||||
| result = max(1, *[k.kind_int for k in TimeunitKindMeta._pre_registered]) | ||||||||||||||||
| result = 10 ** math.ceil(math.log10(result)) | ||||||||||||||||
| if result == -1: | ||||||||||||||||
| result = 1 | ||||||||||||||||
| for k in TimeunitKindMeta._pre_registered: | ||||||||||||||||
| while k.kind_int >= result: | ||||||||||||||||
| result *= 10 | ||||||||||||||||
| TimeunitKindMeta._multiplier = result | ||||||||||||||||
| return result | ||||||||||||||||
|
|
||||||||||||||||
| def __int__(self): | ||||||||||||||||
| def __int__(self) -> int: | ||||||||||||||||
| return self.kind_int | ||||||||||||||||
|
|
||||||||||||||||
| def __index__(self): | ||||||||||||||||
| def __index__(self) -> int: | ||||||||||||||||
| return int(self) | ||||||||||||||||
|
|
||||||||||||||||
| def __hash__(self): | ||||||||||||||||
| def __hash__(self) -> int: | ||||||||||||||||
| """ | ||||||||||||||||
| Return the hash value of the time unit, based on its integer encoding. | ||||||||||||||||
| """ | ||||||||||||||||
| return hash(int(self)) | ||||||||||||||||
|
|
||||||||||||||||
| def __eq__(self, other): | ||||||||||||||||
| def __eq__(self, other: object) -> bool: | ||||||||||||||||
| """ | ||||||||||||||||
| Return True if this time unit kind is the same as another kind or matches the kind registered for the given integer. | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -73,10 +76,11 @@ def __eq__(self, other): | |||||||||||||||
| bool: True if both refer to the same time unit kind, otherwise False. | ||||||||||||||||
| """ | ||||||||||||||||
| if isinstance(other, int): | ||||||||||||||||
| other = TimeunitKind.unit_register[other] | ||||||||||||||||
| # if out of range, None will fail | ||||||||||||||||
| other = TimeunitKind.unit_register.get(other) | ||||||||||||||||
| return self is other | ||||||||||||||||
|
|
||||||||||||||||
| def __call__(cls, dt): | ||||||||||||||||
| def __call__(cls, dt: Union["Timeunit", date]) -> "Timeunit": | ||||||||||||||||
| """ | ||||||||||||||||
| Creates a `Timeunit` instance of this kind from a given date or `Timeunit`. | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -89,17 +93,17 @@ def __call__(cls, dt): | |||||||||||||||
| def __lt__(self, other): | ||||||||||||||||
| return self.kind_int < other.kind_int | ||||||||||||||||
|
|
||||||||||||||||
| def from_int(cls, val): | ||||||||||||||||
| def from_int(cls, val: int) -> "Timeunit": | ||||||||||||||||
| mul = cls.multiplier | ||||||||||||||||
| return TimeunitKind.unit_register[val % mul](date_from_int(val, mul)) | ||||||||||||||||
|
|
||||||||||||||||
| def get_previous(cls, dt): | ||||||||||||||||
| def get_previous(cls, dt: Union[date, "Timeunit"]) -> "Timeunit": | ||||||||||||||||
| if isinstance(dt, Timeunit): | ||||||||||||||||
| dt = dt.dt | ||||||||||||||||
| dt -= timedelta(days=1) | ||||||||||||||||
| return cls(dt) | ||||||||||||||||
|
|
||||||||||||||||
| def last_day(cls, dt): | ||||||||||||||||
| def last_day(cls, dt: date) -> date: | ||||||||||||||||
| """ | ||||||||||||||||
| Return the last date of the time unit containing the given date. | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -111,7 +115,7 @@ def last_day(cls, dt): | |||||||||||||||
| """ | ||||||||||||||||
| return cls._next(dt) - timedelta(days=1) | ||||||||||||||||
|
|
||||||||||||||||
| def _next(cls, dt): | ||||||||||||||||
| def _next(cls, dt: date) -> date: | ||||||||||||||||
| """ | ||||||||||||||||
| Return the first day of the next time unit following the given date. | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -123,7 +127,7 @@ def _next(cls, dt): | |||||||||||||||
| """ | ||||||||||||||||
| return cls.last_day(dt) + timedelta(days=1) | ||||||||||||||||
|
|
||||||||||||||||
| def get_next(cls, dt): | ||||||||||||||||
| def get_next(cls, dt: Union["Timeunit", date]) -> "Timeunit": | ||||||||||||||||
| """ | ||||||||||||||||
| Return the next time unit instance of this kind after the given date. | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -133,16 +137,16 @@ def get_next(cls, dt): | |||||||||||||||
| dt = dt.dt | ||||||||||||||||
| return cls(cls._next(cls.truncate(dt))) | ||||||||||||||||
|
|
||||||||||||||||
| def to_str(cls, dt): | ||||||||||||||||
| def to_str(cls, dt) -> str: | ||||||||||||||||
| return dt.strftime(cls.formatter) | ||||||||||||||||
|
|
||||||||||||||||
| def truncate(cls, dt): | ||||||||||||||||
| def truncate(cls, dt: date) -> date: | ||||||||||||||||
| return datetime.strptime(cls.to_str(dt), cls.formatter).date() | ||||||||||||||||
|
|
||||||||||||||||
| def _inner_shift(cls, cur, dt, amount): | ||||||||||||||||
| def _inner_shift(cls, cur, dt, amount) -> Union[date, None]: | ||||||||||||||||
| return None | ||||||||||||||||
|
|
||||||||||||||||
| def _shift(cls, cur, dt, amount): | ||||||||||||||||
| def _shift(cls, cur: "Timeunit", dt: date, amount: int) -> "Timeunit": | ||||||||||||||||
| new_dt = cls._inner_shift(cur, dt, amount) | ||||||||||||||||
| if new_dt is not None: | ||||||||||||||||
| return cls(new_dt) | ||||||||||||||||
|
|
@@ -159,20 +163,20 @@ def _shift(cls, cur, dt, amount): | |||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| class TimeunitKind(metaclass=TimeunitKindMeta): | ||||||||||||||||
| kind_int = None | ||||||||||||||||
| formatter = None | ||||||||||||||||
| kind_int = -1 | ||||||||||||||||
| formatter = "" | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| class Year(TimeunitKind): | ||||||||||||||||
| kind_int = 1 | ||||||||||||||||
| formatter = "%Y" | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def _next(cls, dt): | ||||||||||||||||
| def _next(cls, dt: date) -> date: | ||||||||||||||||
| return date(dt.year + 1, 1, 1) | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def _inner_shift(cls, cur, dt, amount): | ||||||||||||||||
| def _inner_shift(cls, cur: "Timeunit", dt: date, amount: int): | ||||||||||||||||
| return date(dt.year + amount, 1, 1) | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -184,11 +188,11 @@ def to_str(cls, dt): | |||||||||||||||
| return f"{dt.year}Q{dt.month//3}" | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def truncate(cls, dt): | ||||||||||||||||
| def truncate(cls, dt: date) -> date: | ||||||||||||||||
| return date(dt.year, 3 * ((dt.month - 1) // 3) + 1, 1) | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def _inner_shift(cls, cur, dt, amount): | ||||||||||||||||
| def _inner_shift(cls, cur: "Timeunit", dt: date, amount: int) -> date: | ||||||||||||||||
| q_new = dt.year * 4 + amount + (dt.month - 1) // 3 | ||||||||||||||||
| y = q_new // 4 | ||||||||||||||||
| q = q_new % 4 | ||||||||||||||||
|
|
@@ -207,7 +211,7 @@ class Month(TimeunitKind): | |||||||||||||||
| formatter = "%YM%m" | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def _inner_shift(cls, cur, dt, amount): | ||||||||||||||||
| def _inner_shift(cls, cur: "Timeunit", dt: date, amount: int) -> date: | ||||||||||||||||
| m_new = dt.year * 12 + amount + dt.month - 1 | ||||||||||||||||
| return date(m_new // 12, m_new % 12 + 1, 1) | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -225,11 +229,11 @@ class Week(TimeunitKind): | |||||||||||||||
| formatter = "%YW%W" | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def _inner_shift(cls, cur, dt, amount): | ||||||||||||||||
| def _inner_shift(cls, cur: "Timeunit", dt: date, amount: int) -> date: | ||||||||||||||||
| return dt + timedelta(days=7 * amount) | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def truncate(cls, dt): | ||||||||||||||||
| def truncate(cls, dt: date) -> date: | ||||||||||||||||
| if isinstance(dt, datetime): | ||||||||||||||||
| dt = dt.date() | ||||||||||||||||
| return dt - timedelta(days=dt.weekday()) | ||||||||||||||||
|
|
@@ -244,11 +248,11 @@ class Day(TimeunitKind): | |||||||||||||||
| formatter = "%Y-%m-%d" | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def _inner_shift(cls, cur, dt, amount): | ||||||||||||||||
| def _inner_shift(cls, cur: "Timeunit", dt: date, amount: int) -> date: | ||||||||||||||||
| return dt + timedelta(days=amount) | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def _next(self, dt): | ||||||||||||||||
| def _next(cls, dt: date) -> date: | ||||||||||||||||
| return dt + timedelta(days=1) | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -370,7 +374,7 @@ def __repr__(self): | |||||||||||||||
| return f"{self.__class__.__name__}({self.kind.__qualname__}, {self.dt!r})" | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def _get_range(cls, item): | ||||||||||||||||
| def _get_range(cls, item) -> tuple[date, date]: | ||||||||||||||||
| """ | ||||||||||||||||
| Extracts a date range tuple from the given item. | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -396,7 +400,8 @@ def _get_range(cls, item): | |||||||||||||||
| try: | ||||||||||||||||
| dt0, dt1 = item | ||||||||||||||||
| if isinstance(dt0, date) and isinstance(dt1, date): | ||||||||||||||||
| return item | ||||||||||||||||
| return dt0, dt1 | ||||||||||||||||
| raise TypeError(f"Item {item!r} is not a date range.") from None | ||||||||||||||||
| except TypeError: | ||||||||||||||||
| raise TypeError(f"Item {item!r} has no date range.") from None | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Make Pyright check against Python 3.8 and cache deps.
Apply:
pyright: name: pyright runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.x' - cache: 'pip' + cache: 'pip' + cache-dependency-path: | + requirements*.txt + setup.cfg + setup.py + pyproject.toml - name: Run pyright run: | - pip install "pyright>=1.1,<2" - pyright + python -m pip install -U pip + pip install "pyright>=1.1,<2" typing-extensions + pyright --pythonversion 3.8📝 Committable suggestion
🤖 Prompt for AI Agents