Merge pull request #151 from jepler/dunder_new_typing
This commit is contained in:
commit
92e7ff0e3a
5 changed files with 35 additions and 9 deletions
9
Makefile
9
Makefile
|
|
@ -46,6 +46,15 @@ test_venv:
|
||||||
mypy:
|
mypy:
|
||||||
$(Q)mypy --strict --no-warn-unused-ignores src test
|
$(Q)mypy --strict --no-warn-unused-ignores src test
|
||||||
|
|
||||||
|
.PHONY: pyright
|
||||||
|
pyright:
|
||||||
|
$(Q)pyright src test
|
||||||
|
|
||||||
|
.PHONY: pyrefly
|
||||||
|
pyrefly:
|
||||||
|
$(Q)pyrefly check src test
|
||||||
|
|
||||||
|
|
||||||
.PHONY: update
|
.PHONY: update
|
||||||
update:
|
update:
|
||||||
$(Q)env PYTHONPATH=src $(PYTHON) -mwwvb.updateiers --dist
|
$(Q)env PYTHONPATH=src $(PYTHON) -mwwvb.updateiers --dist
|
||||||
|
|
|
||||||
|
|
@ -411,7 +411,14 @@ class WWVBMinute(_WWVBMinute):
|
||||||
year = cls.full_year(year)
|
year = cls.full_year(year)
|
||||||
if ly is None:
|
if ly is None:
|
||||||
ly = isly(year)
|
ly = isly(year)
|
||||||
return _WWVBMinute.__new__(cls, year, days, hour, minute, dst, ut1, ls, ly)
|
return super().__new__(cls, year, days, hour, minute, dst, ut1, ls, ly)
|
||||||
|
|
||||||
|
def __init__(self, *args: Any, **kw: Any) -> None:
|
||||||
|
"""Do-nothing function.
|
||||||
|
|
||||||
|
Instance initialization is performed in __new__. This implementation of __init__
|
||||||
|
works around a pyrefly bug.
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def full_year(cls, year: int) -> int:
|
def full_year(cls, year: int) -> int:
|
||||||
|
|
@ -662,12 +669,12 @@ class WWVBMinute(_WWVBMinute):
|
||||||
else:
|
else:
|
||||||
self._fill_pm_timecode_regular(t)
|
self._fill_pm_timecode_regular(t)
|
||||||
|
|
||||||
def next_minute(self, *, newut1: int | None = None, newls: bool | None = None) -> WWVBMinute:
|
def next_minute(self, *, newut1: int | None = None, newls: bool | None = None) -> Self:
|
||||||
"""Return an object representing the next minute"""
|
"""Return an object representing the next minute"""
|
||||||
d = self.as_datetime() + datetime.timedelta(minutes=1)
|
d = self.as_datetime() + datetime.timedelta(minutes=1)
|
||||||
return self.from_datetime(d, newut1=newut1, newls=newls, old_time=self)
|
return self.from_datetime(d, newut1=newut1, newls=newls, old_time=self)
|
||||||
|
|
||||||
def previous_minute(self, *, newut1: int | None = None, newls: bool | None = None) -> WWVBMinute:
|
def previous_minute(self, *, newut1: int | None = None, newls: bool | None = None) -> Self:
|
||||||
"""Return an object representing the previous minute"""
|
"""Return an object representing the previous minute"""
|
||||||
d = self.as_datetime() - datetime.timedelta(minutes=1)
|
d = self.as_datetime() - datetime.timedelta(minutes=1)
|
||||||
return self.from_datetime(d, newut1=newut1, newls=newls, old_time=self)
|
return self.from_datetime(d, newut1=newut1, newls=newls, old_time=self)
|
||||||
|
|
@ -686,7 +693,7 @@ class WWVBMinute(_WWVBMinute):
|
||||||
return 0, False
|
return 0, False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fromstring(cls, s: str) -> WWVBMinute:
|
def fromstring(cls, s: str) -> Self:
|
||||||
"""Construct a WWVBMinute from a string representation created by print_timecodes"""
|
"""Construct a WWVBMinute from a string representation created by print_timecodes"""
|
||||||
s = _removeprefix(s, "WWVB timecode: ")
|
s = _removeprefix(s, "WWVB timecode: ")
|
||||||
d: dict[str, int] = {}
|
d: dict[str, int] = {}
|
||||||
|
|
@ -702,7 +709,7 @@ class WWVBMinute(_WWVBMinute):
|
||||||
dst = d.pop("dst", None)
|
dst = d.pop("dst", None)
|
||||||
ut1 = d.pop("ut1", None)
|
ut1 = d.pop("ut1", None)
|
||||||
ls = d.pop("ls", None)
|
ls = d.pop("ls", None)
|
||||||
d.pop("ly", None)
|
d.pop("ly", None) # Always use calculated ly flag
|
||||||
if d:
|
if d:
|
||||||
raise ValueError(f"Invalid options: {d}")
|
raise ValueError(f"Invalid options: {d}")
|
||||||
return cls(year, days, hour, minute, dst, ut1=ut1, ls=None if ls is None else bool(ls))
|
return cls(year, days, hour, minute, dst, ut1=ut1, ls=None if ls is None else bool(ls))
|
||||||
|
|
@ -715,7 +722,7 @@ class WWVBMinute(_WWVBMinute):
|
||||||
newut1: int | None = None,
|
newut1: int | None = None,
|
||||||
newls: bool | None = None,
|
newls: bool | None = None,
|
||||||
old_time: WWVBMinute | None = None,
|
old_time: WWVBMinute | None = None,
|
||||||
) -> WWVBMinute:
|
) -> Self:
|
||||||
"""Construct a WWVBMinute from a datetime, possibly specifying ut1/ls data or propagating it from an old time"""
|
"""Construct a WWVBMinute from a datetime, possibly specifying ut1/ls data or propagating it from an old time"""
|
||||||
u = d.utctimetuple()
|
u = d.utctimetuple()
|
||||||
if newls is None and newut1 is None:
|
if newls is None and newut1 is None:
|
||||||
|
|
@ -723,7 +730,7 @@ class WWVBMinute(_WWVBMinute):
|
||||||
return cls(u.tm_year, u.tm_yday, u.tm_hour, u.tm_min, ut1=newut1, ls=newls)
|
return cls(u.tm_year, u.tm_yday, u.tm_hour, u.tm_min, ut1=newut1, ls=newls)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_timecode_am(cls, t: WWVBTimecode) -> WWVBMinute | None: # noqa: PLR0912
|
def from_timecode_am(cls, t: WWVBTimecode) -> Self | None: # noqa: PLR0912
|
||||||
"""Construct a WWVBMinute from a WWVBTimecode"""
|
"""Construct a WWVBMinute from a WWVBTimecode"""
|
||||||
for i in (0, 9, 19, 29, 39, 49, 59):
|
for i in (0, 9, 19, 29, 39, 49, 59):
|
||||||
if t.am[i] != AmplitudeModulation.MARK:
|
if t.am[i] != AmplitudeModulation.MARK:
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ def update_iersdata( # noqa: PLR0915
|
||||||
"""Update iersdata.py"""
|
"""Update iersdata.py"""
|
||||||
offsets: list[int] = []
|
offsets: list[int] = []
|
||||||
iersdata_text = _get_text(IERS_URL)
|
iersdata_text = _get_text(IERS_URL)
|
||||||
|
table_start: datetime.date | None = None
|
||||||
for r in csv.DictReader(io.StringIO(iersdata_text), delimiter=";"):
|
for r in csv.DictReader(io.StringIO(iersdata_text), delimiter=";"):
|
||||||
jd = float(r["MJD"])
|
jd = float(r["MJD"])
|
||||||
offs_str = r["UT1-UTC"]
|
offs_str = r["UT1-UTC"]
|
||||||
|
|
@ -79,6 +80,8 @@ def update_iersdata( # noqa: PLR0915
|
||||||
|
|
||||||
offsets.append(offs)
|
offsets.append(offs)
|
||||||
|
|
||||||
|
assert table_start is not None
|
||||||
|
|
||||||
wwvb_text = _get_text(NIST_URL)
|
wwvb_text = _get_text(NIST_URL)
|
||||||
wwvb_data = bs4.BeautifulSoup(wwvb_text, features="html.parser")
|
wwvb_data = bs4.BeautifulSoup(wwvb_text, features="html.parser")
|
||||||
wwvb_dut1_table = wwvb_data.findAll("table")[2]
|
wwvb_dut1_table = wwvb_data.findAll("table")[2]
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ def main(colors: list[str], size: int, min_size: int | None) -> None: # noqa: P
|
||||||
def deadline_ms(deadline: datetime.datetime) -> int:
|
def deadline_ms(deadline: datetime.datetime) -> int:
|
||||||
"""Compute the number of ms until a deadline"""
|
"""Compute the number of ms until a deadline"""
|
||||||
now = datetime.datetime.now(datetime.timezone.utc)
|
now = datetime.datetime.now(datetime.timezone.utc)
|
||||||
return int(max(0, (deadline - now).total_seconds()) * 1000)
|
return int(max(0.0, (deadline - now).total_seconds()) * 1000)
|
||||||
|
|
||||||
def wwvbtick() -> Generator[tuple[datetime.datetime, wwvb.AmplitudeModulation]]:
|
def wwvbtick() -> Generator[tuple[datetime.datetime, wwvb.AmplitudeModulation]]:
|
||||||
"""Yield consecutive values of the WWVB amplitude signal, going from minute to minute"""
|
"""Yield consecutive values of the WWVB amplitude signal, going from minute to minute"""
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,14 @@
|
||||||
# SPDX-FileCopyrightText: 2021 Jeff Epler
|
# SPDX-FileCopyrightText: 2021 Jeff Epler
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
#
|
||||||
|
# "For six minutes each half hour, from 10–16 and 40–46 minutes past each hour,
|
||||||
|
# one-minute frames are replaced by a special extended time frame. Rather than
|
||||||
|
# transmitting 35 bits of information in one minute, this transmits 7 bits
|
||||||
|
# (time of day and DST status only) over 6 minutes, giving 30 times as much
|
||||||
|
# energy per transmitted bit, a 14.8 dB improvement in the link budget compared
|
||||||
|
# to the standard one-minute time code." (wikipedia)
|
||||||
|
#
|
||||||
WWVB timecode: year=2021 days=311 hour=08 min=10 dst=1 ut1=-100 ly=0 ls=0 --channel=phase
|
WWVB timecode: year=2021 days=311 hour=08 min=10 dst=1 ut1=-100 ly=0 ls=0 --channel=phase
|
||||||
2021-311 08:10 010000110100000111110110000001010110111111100110110101010001
|
2021-311 08:10 010000110100000111110110000001010110111111100110110101010001
|
||||||
2021-311 08:11 001001100111100011101110101111010010110010100111001000110001
|
2021-311 08:11 001001100111100011101110101111010010110010100111001000110001
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue