From b672ddf418039ec68fc22fe58798be840e61a20c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 8 Jul 2024 21:04:13 -0500 Subject: [PATCH 1/3] build docs during CI --- .github/workflows/test.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 51bcfa5..17903d8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,6 +13,22 @@ on: types: [rerequested] jobs: + docs: + runs-on: ubuntu-latest + steps: + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - uses: actions/checkout@v4 + + - name: Install deps + run: python -mpip install -r requirements-dev.txt + + - name: Build HTML docs + run: make html + test: strategy: fail-fast: false From 0a716adb38daca89289987e969df8444521060a5 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 8 Jul 2024 21:22:34 -0500 Subject: [PATCH 2/3] doc improvements & make more methods private --- index.rst | 31 +++++++++++++++++++++++ src/wwvb/__init__.py | 58 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 index.rst diff --git a/index.rst b/index.rst new file mode 100644 index 0000000..83f39d0 --- /dev/null +++ b/index.rst @@ -0,0 +1,31 @@ +.. SPDX-FileCopyrightText: 2021 Jeff Epler +.. +.. SPDX-License-Identifier: GPL-3.0-only + +wwvbpy +====== + +.. image:: https://github.com/jepler/wwvbpy/actions/workflows/test.yml/badge.svg + :target: https://github.com/jepler/wwvbpy/actions/workflows/test.yml + :alt: Test wwvbpy + +.. image:: https://img.shields.io/pypi/v/wwvb + :target: https://pypi.org/project/wwvb + :alt: PyPI + + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + +wwvb module +=========== + +.. automodule:: wwvb + :members: + +uwwvb module +============ + +.. automodule:: uwwvb + :members: diff --git a/src/wwvb/__init__.py b/src/wwvb/__init__.py index 7dcd317..69058bb 100644 --- a/src/wwvb/__init__.py +++ b/src/wwvb/__init__.py @@ -329,13 +329,28 @@ class _WWVBMinute(NamedTuple): """ year: int + """2-digit year within the WWVB epoch""" + days: int + """1-based day of year""" + hour: int + """UTC hour of day""" + min: int + """Minute of hour""" + dst: int + """2-bit DST code """ + ut1: int + """UT1 offset in units of 100ms, range -900 to +900ms""" + ls: bool + """Leap second warning flag""" + ly: bool + """Leap year flag""" class WWVBMinute(_WWVBMinute): @@ -463,14 +478,14 @@ def as_timecode(self) -> WWVBTimecode: """Fill a WWVBTimecode structure representing this minute. Fills both the amplitude and phase codes.""" t = WWVBTimecode(self.minute_length()) - self.fill_am_timecode(t) - self.fill_pm_timecode(t) + self._fill_am_timecode(t) + self._fill_pm_timecode(t) return t @property - def leap_sec(self) -> int: - """Return the 2-bit leap_sec value used by the PM code""" + def _leap_sec(self) -> int: + """Return the 2-bit _leap_sec value used by the PM code""" if not self.ls: return 0 if self.ut1 < 0: @@ -487,7 +502,7 @@ def minute_of_century(self) -> int: // 60 ) - def fill_am_timecode(self, t: WWVBTimecode) -> None: + def _fill_am_timecode(self, t: WWVBTimecode) -> None: """Fill the amplitude (AM) portion of a timecode object""" for i in [0, 9, 19, 29, 39, 49]: t.am[i] = AmplitudeModulation.MARK @@ -509,7 +524,7 @@ def fill_am_timecode(self, t: WWVBTimecode) -> None: t.am[56] = AmplitudeModulation(self.ls) t._put_am_bcd(self.dst, 57, 58) - def fill_pm_timecode_extended(self, t: WWVBTimecode) -> None: + def _fill_pm_timecode_extended(self, t: WWVBTimecode) -> None: """During minutes 10..15 and 40..45, the amplitude signal holds 'extended information'""" assert 10 <= self.min < 16 or 40 <= self.min < 46 minno = self.min % 10 @@ -543,14 +558,14 @@ def fill_pm_timecode_extended(self, t: WWVBTimecode) -> None: for i in range(60): t._put_pm_bit(i, full_seq[i + offset]) - def fill_pm_timecode_regular(self, t: WWVBTimecode) -> None: # noqa: PLR0915 + def _fill_pm_timecode_regular(self, t: WWVBTimecode) -> None: # noqa: PLR0915 """Except during minutes 10..15 and 40..45, the amplitude signal holds 'regular information'""" t._put_pm_bin(0, 13, SYNC_T) moc = self.minute_of_century - leap_sec = self.leap_sec + _leap_sec = self._leap_sec dst_on = self.dst - dst_ls = _dst_ls_lut[dst_on | (leap_sec << 2)] + dst_ls = _dst_ls_lut[dst_on | (_leap_sec << 2)] dst_next = _get_dst_next(self.as_datetime()) t._put_pm_bin(13, 5, _hamming_parity(moc)) t._put_pm_bit(18, _extract_bit(moc, 25)) @@ -599,12 +614,12 @@ def fill_pm_timecode_regular(self, t: WWVBTimecode) -> None: # noqa: PLR0915 if len(t.phase) > 60: t._put_pm_bit(60, PhaseModulation.ZERO) - def fill_pm_timecode(self, t: WWVBTimecode) -> None: + def _fill_pm_timecode(self, t: WWVBTimecode) -> None: """Fill the phase portion of a timecode object""" if 10 <= self.min < 16 or 40 <= self.min < 46: - self.fill_pm_timecode_extended(t) + self._fill_pm_timecode_extended(t) 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: """Return an object representing the next minute""" @@ -745,7 +760,10 @@ class WWVBTimecode: """Represent the amplitude and/or phase signal, usually over 1 minute""" am: list[AmplitudeModulation] + """The amplitude modulation data""" + phase: list[PhaseModulation] + """The phase modulation data""" def __init__(self, sz: int) -> None: """Construct a WWVB timecode ``sz`` seconds long""" @@ -881,7 +899,21 @@ def print_timecodes_json( channel: str, file: TextIO, ) -> None: - """Print a range of timecodes with a header. This header is in a format understood by WWVBMinute.fromstring""" + """Print a range of timecodes in JSON format. + + The result is a json array of minute data. Each minute data is an object with the following members: + + * year (int) + * days (int) + * hour (int) + * minute (int) + * amplitude (string; only if channel is amplitude or both) + * phase: (string; only if channel is phase or both) + + The amplitude and phase strings are of length 60 during most minutes, length 61 + during a minute that includes a (positive) leap second, and theoretically + length 59 in the case of a negative leap second. + """ result = [] for _ in range(minutes): data: dict[str, Any] = { From 4eb910f460001a009fd8baa23640d49a8f0d67eb Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 8 Jul 2024 21:24:29 -0500 Subject: [PATCH 3/3] require sphinx --- requirements-dev.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index 4cd77ef..cc62568 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -14,6 +14,9 @@ pre-commit python-dateutil requests; implementation_name=="cpython" setuptools>=68; implementation_name=="cpython" +sphinx +sphinx-autodoc-typehints +sphinx-rtd-theme twine; implementation_name=="cpython" types-beautifulsoup4 types-python-dateutil