wwvb 3.0.8__py3-none-any.whl → 4.0.0a0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
wwvb/updateiers.py CHANGED
@@ -6,32 +6,34 @@
6
6
 
7
7
  """Update the DUT1 and LS data based on online sources"""
8
8
 
9
+ from __future__ import annotations
10
+
9
11
  import csv
10
12
  import datetime
11
13
  import io
12
14
  import itertools
13
- import os
14
15
  import pathlib
15
- from typing import Callable, List, Optional
16
+ from typing import Callable
16
17
 
17
18
  import bs4
18
19
  import click
19
20
  import platformdirs
20
21
  import requests
21
22
 
22
- DIST_PATH = str(pathlib.Path(__file__).parent / "iersdata_dist.py")
23
+ DIST_PATH = pathlib.Path(__file__).parent / "iersdata_dist.py"
23
24
 
24
- OLD_TABLE_START: Optional[datetime.date] = None
25
- OLD_TABLE_END: Optional[datetime.date] = None
26
- if os.path.exists(DIST_PATH):
25
+ OLD_TABLE_START: datetime.date | None = None
26
+ OLD_TABLE_END: datetime.date | None = None
27
+ if DIST_PATH.exists():
27
28
  import wwvb.iersdata_dist
28
29
 
29
30
  OLD_TABLE_START = wwvb.iersdata_dist.DUT1_DATA_START
30
31
  OLD_TABLE_END = OLD_TABLE_START + datetime.timedelta(days=len(wwvb.iersdata_dist.DUT1_OFFSETS) - 1)
31
32
 
32
33
  IERS_URL = "https://datacenter.iers.org/data/csv/finals2000A.all.csv"
33
- if os.path.exists("finals2000A.all.csv"):
34
- IERS_URL = "finals2000A.all.csv"
34
+ IERS_PATH = pathlib.Path("finals2000A.all.csv")
35
+ if IERS_PATH.exists():
36
+ IERS_URL = str(IERS_PATH)
35
37
  print("using local", IERS_URL)
36
38
  NIST_URL = "https://www.nist.gov/pml/time-and-frequency-division/atomic-standards/leap-second-and-ut1-utc-information"
37
39
 
@@ -42,15 +44,14 @@ def _get_text(url: str) -> str:
42
44
  with requests.get(url, timeout=30) as response:
43
45
  return response.text
44
46
  else:
45
- return open(url, encoding="utf-8").read()
47
+ return pathlib.Path(url).read_text(encoding="utf-8")
46
48
 
47
49
 
48
- def update_iersdata(
49
- target_file: str,
50
+ def update_iersdata( # noqa: PLR0915, PLR0912
51
+ target_path: pathlib.Path,
50
52
  ) -> None:
51
53
  """Update iersdata.py"""
52
-
53
- offsets: List[int] = []
54
+ offsets: list[int] = []
54
55
  iersdata_text = _get_text(IERS_URL)
55
56
  for r in csv.DictReader(io.StringIO(iersdata_text), delimiter=";"):
56
57
  jd = float(r["MJD"])
@@ -97,11 +98,11 @@ def update_iersdata(
97
98
  off_end = (patch_end - table_start).days
98
99
  offsets[off_start:off_end] = [val] * (off_end - off_start)
99
100
 
100
- wwvb_dut1: Optional[int] = None
101
- wwvb_start: Optional[datetime.date] = None
101
+ wwvb_dut1: int | None = None
102
+ wwvb_start: datetime.date | None = None
102
103
  for row in wwvb_dut1_table.findAll("tr")[1:][::-1]:
103
104
  cells = row.findAll("td")
104
- when = datetime.datetime.strptime(cells[0].text, "%Y-%m-%d").date()
105
+ when = datetime.datetime.strptime(cells[0].text + "+0000", "%Y-%m-%d%z").date()
105
106
  dut1 = cells[2].text.replace("s", "").replace(" ", "")
106
107
  dut1 = int(round(float(dut1) * 10))
107
108
  if wwvb_dut1 is not None:
@@ -123,7 +124,7 @@ def update_iersdata(
123
124
  assert wwvb_start is not None
124
125
  patch(wwvb_start, wwvb_data_stamp + datetime.timedelta(days=1), wwvb_dut1)
125
126
 
126
- with open(target_file, "wt", encoding="utf-8") as output:
127
+ with target_path.open("w", encoding="utf-8") as output:
127
128
 
128
129
  def code(*args: str) -> None:
129
130
  """Print to the output file"""
@@ -138,9 +139,9 @@ def update_iersdata(
138
139
  code("import datetime")
139
140
 
140
141
  code("__all__ = ['DUT1_DATA_START', 'DUT1_OFFSETS']")
141
- code(f"DUT1_DATA_START = {repr(table_start)}")
142
+ code(f"DUT1_DATA_START = {table_start!r}")
142
143
  c = sorted(chr(ord("a") + ch + 10) for ch in set(offsets))
143
- code(f"{','.join(c)} = tuple({repr(''.join(c))})")
144
+ code(f"{','.join(c)} = tuple({''.join(c)!r})")
144
145
  code(f"DUT1_OFFSETS = str( # {table_start.year:04d}{table_start.month:02d}{table_start.day:02d}")
145
146
  line = ""
146
147
  j = 0
@@ -151,10 +152,7 @@ def update_iersdata(
151
152
  sz = len(list(it))
152
153
  if j:
153
154
  part = part + "+"
154
- if sz < 2:
155
- part = part + ch
156
- else:
157
- part = part + f"{ch}*{sz}"
155
+ part = part + ch if sz < 2 else part + f"{ch}*{sz}"
158
156
  j += sz
159
157
  if len(line + part) > 60:
160
158
  d = table_start + datetime.timedelta(j - 1)
@@ -171,25 +169,30 @@ def update_iersdata(
171
169
  print(f"iersdata covers {table_start} .. {table_end}")
172
170
 
173
171
 
174
- def iersdata_path(callback: Callable[[str, str], str]) -> str:
172
+ def iersdata_path(callback: Callable[[str, str], pathlib.Path]) -> pathlib.Path:
175
173
  """Find out the path for this directory"""
176
- return os.path.join(callback("wwvbpy", "unpythonic.net"), "wwvb_iersdata.py")
174
+ print("iersdata_path", callback)
175
+ r = callback("wwvbpy", "unpythonic.net") / "wwvb_iersdata.py"
176
+ print(f"iersdata_path {r=!r}")
177
+ return r
177
178
 
178
179
 
179
180
  @click.command()
180
181
  @click.option(
181
182
  "--user",
182
183
  "location",
183
- flag_value=iersdata_path(platformdirs.user_data_dir),
184
- default=iersdata_path(platformdirs.user_data_dir),
184
+ flag_value=iersdata_path(platformdirs.user_data_path),
185
+ default=iersdata_path(platformdirs.user_data_path),
186
+ type=pathlib.Path,
185
187
  )
186
188
  @click.option("--dist", "location", flag_value=DIST_PATH)
187
- @click.option("--site", "location", flag_value=iersdata_path(platformdirs.site_data_dir))
189
+ @click.option("--site", "location", flag_value=iersdata_path(platformdirs.site_data_path))
188
190
  def main(location: str) -> None:
189
191
  """Update DUT1 data"""
190
- print("will write to", location)
191
- os.makedirs(os.path.dirname(location), exist_ok=True)
192
- update_iersdata(location)
192
+ path = pathlib.Path(location)
193
+ print(f"will write to {location!r}")
194
+ path.parent.mkdir(parents=True, exist_ok=True)
195
+ update_iersdata(path)
193
196
 
194
197
 
195
198
  if __name__ == "__main__":
wwvb/wwvbtk.py CHANGED
@@ -5,12 +5,13 @@
5
5
  # SPDX-FileCopyrightText: 2021 Jeff Epler
6
6
  #
7
7
  # SPDX-License-Identifier: GPL-3.0-only
8
+ from __future__ import annotations
8
9
 
9
10
  import functools
10
11
  import threading
11
12
  import time
12
13
  from tkinter import Canvas, TclError, Tk
13
- from typing import Any, Generator, Optional, Tuple
14
+ from typing import Any, Generator
14
15
 
15
16
  import click
16
17
 
@@ -23,7 +24,7 @@ def _app() -> Tk:
23
24
  return Tk()
24
25
 
25
26
 
26
- def validate_colors(ctx: Any, param: Any, value: str) -> list[str]:
27
+ def validate_colors(ctx: Any, param: Any, value: str) -> list[str]: # noqa: ARG001
27
28
  """Check that all colors in a string are valid, splitting it to a list"""
28
29
  app = _app()
29
30
  colors = value.split()
@@ -53,9 +54,8 @@ DEFAULT_COLORS = "#3c3c3c #3c3c3c #3c3c3c #cc3c3c #88883c #3ccc3c"
53
54
  @click.option("--colors", callback=validate_colors, default=DEFAULT_COLORS)
54
55
  @click.option("--size", default=48)
55
56
  @click.option("--min-size", default=None)
56
- def main(colors: list[str], size: int, min_size: Optional[int]) -> None:
57
+ def main(colors: list[str], size: int, min_size: int | None) -> None: # noqa: PLR0915
57
58
  """Visualize the WWVB signal in realtime"""
58
-
59
59
  if min_size is None:
60
60
  min_size = size
61
61
 
@@ -65,7 +65,7 @@ def main(colors: list[str], size: int, min_size: Optional[int]) -> None:
65
65
  if deadline > now:
66
66
  time.sleep(deadline - now)
67
67
 
68
- def wwvbtick() -> Generator[Tuple[float, wwvb.AmplitudeModulation], None, None]:
68
+ def wwvbtick() -> Generator[tuple[float, wwvb.AmplitudeModulation], None, None]:
69
69
  """Yield consecutive values of the WWVB amplitude signal, going from minute to minute"""
70
70
  timestamp = time.time() // 60 * 60
71
71
 
@@ -77,13 +77,15 @@ def main(colors: list[str], size: int, min_size: Optional[int]) -> None:
77
77
  yield timestamp + i, code
78
78
  timestamp = timestamp + 60
79
79
 
80
- def wwvbsmarttick() -> Generator[Tuple[float, wwvb.AmplitudeModulation], None, None]:
81
- """Yield consecutive values of the WWVB amplitude signal but deal with time
82
- progressing unexpectedly, such as when the computer is suspended or NTP steps
83
- the clock backwards
80
+ def wwvbsmarttick() -> Generator[tuple[float, wwvb.AmplitudeModulation], None, None]:
81
+ """Yield consecutive values of the WWVB amplitude signal
82
+
83
+ .. but deal with time progressing unexpectedly, such as when the
84
+ computer is suspended or NTP steps the clock backwards
84
85
 
85
86
  When time goes backwards or advances by more than a minute, get a fresh
86
- wwvbtick object; otherwise, discard time signals more than 1s in the past."""
87
+ wwvbtick object; otherwise, discard time signals more than 1s in the past.
88
+ """
87
89
  while True:
88
90
  for stamp, code in wwvbtick():
89
91
  now = time.time()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wwvb
3
- Version: 3.0.8
3
+ Version: 4.0.0a0
4
4
  Summary: Generate WWVB timecodes for any desired time
5
5
  Home-page: https://github.com/jepler/wwvbpy
6
6
  Author: Jeff Epler
@@ -0,0 +1,23 @@
1
+ uwwvb.py,sha256=Ocys0AK10NocugDxNjIjUkL3_uVqD2Q6c2WLfqXmx1s,5732
2
+ wwvb/__init__.py,sha256=gSeXqukkcHnYCJAkbXk4eWBMqBu7n3GJ7CJM32XMiaU,30770
3
+ wwvb/__version__.py,sha256=vsEaiHcm9DvHyRWD600KxOTf-j-TilwuyCMsi2Ba3dE,413
4
+ wwvb/decode.py,sha256=d7bAG2pVsFMX0uxY6pMaz-psdbLXauSHh55JDaUT6W4,2713
5
+ wwvb/dut1table.py,sha256=uqaCnCOWr7ytx-nt3mmyhFb9jJVNP5N-WJX-glunKAk,890
6
+ wwvb/gen.py,sha256=0hgicarLgCtOgBgIpb9sU08yzKgCGuwIYOqblR34H5I,3791
7
+ wwvb/iersdata.py,sha256=NOItawXnXwd3Gq3K_cx85NVQ_iogLw3MDgzOI8q_75Y,924
8
+ wwvb/iersdata_dist.py,sha256=zQVO2AjiBTrhpSs21HUG9fL4S11K3WzTk0kP_eyMXz4,2364
9
+ wwvb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ wwvb/testcli.py,sha256=wa1E9iRaE62OBHshR4K_hxhIzSNxwpWy8rgoEKuhrqs,10168
11
+ wwvb/testdaylight.py,sha256=JW8UJK-FeAg9Kjy5F_aBYbUVj44DKpJOXQ-u9ooyprA,2485
12
+ wwvb/testls.py,sha256=Kz4-MWLaUKABwyql8sWdzvtg8gipxhHv4r-6fn3fptg,1720
13
+ wwvb/testpm.py,sha256=JR3V_EIm0Su3c4m5CcKpMANL3aZnpzEzDL3KhgKX3rM,905
14
+ wwvb/testuwwvb.py,sha256=SMvq85tJgjGMYHKsreCtlM4Wrb3MYOOjf5rKf9wuHYc,9176
15
+ wwvb/testwwvb.py,sha256=t0TUJhHOh-mRFD-GUvePzHs7D3DkNb_paRAI1uYH8l8,16807
16
+ wwvb/tz.py,sha256=XVYh0btrnyP_nUiZUwBjufkYbb26_DTiZVl-R_1BA2A,299
17
+ wwvb/updateiers.py,sha256=3Bg0cpQnTDrGWcHbi0rwZ4rSURJcO64Bds9FDTYLSK8,7382
18
+ wwvb/wwvbtk.py,sha256=WumGtKsAxMw1HMTfm5x4dOKmHikCaDBRZfh_WbF4iu0,4585
19
+ wwvb-4.0.0a0.dist-info/METADATA,sha256=lLqzL4USvZY6Md_rAg-k7OhzY2ySNPHjSWgTKwF8qG4,10292
20
+ wwvb-4.0.0a0.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
21
+ wwvb-4.0.0a0.dist-info/entry_points.txt,sha256=KSevvHWLEKxOxUQ-L-OQidD4Sj2BPEfhZ2TQhOgyys4,179
22
+ wwvb-4.0.0a0.dist-info/top_level.txt,sha256=0IYdkhEAMgurpv_F-76rlyn4GdxepGFzG99tivVdQVU,11
23
+ wwvb-4.0.0a0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,23 +0,0 @@
1
- uwwvb.py,sha256=UX5oSMs4KZPt1hg1urZXhN0pMU3BvQWYOKExZT8FiIo,5674
2
- wwvb/__init__.py,sha256=oUUcweJnrFDVw5_-smJopfVAk5yNFlEnOkYMixNxZzc,29762
3
- wwvb/__version__.py,sha256=UsWpfolO3V5lhkRSzLYHaglRPoxe1Nfcc4kMi3j-8W8,411
4
- wwvb/decode.py,sha256=PBfBzYJJkIh8VD-d_SHvBl3gX4FpXhqG1lH2fP8lUaI,2758
5
- wwvb/dut1table.py,sha256=uqaCnCOWr7ytx-nt3mmyhFb9jJVNP5N-WJX-glunKAk,890
6
- wwvb/gen.py,sha256=pOSgkJTh_TDKN1FulzbAW8aN77bJXtJjo1KGoBEU3Dk,3697
7
- wwvb/iersdata.py,sha256=hJFj-ZL3RP13dcdFGWoT6WOgoV-6CAy-sWSYfi_EXwg,965
8
- wwvb/iersdata_dist.py,sha256=dmd6ShKPG5AHBm0dfRAKFpFpt8WDiW1NqNF8DLeMgrI,2363
9
- wwvb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- wwvb/testcli.py,sha256=06uIEdg-ZH0UOISr0X7oy4iAQ5eb4-MejQC7TeqIJz8,10086
11
- wwvb/testdaylight.py,sha256=JW8UJK-FeAg9Kjy5F_aBYbUVj44DKpJOXQ-u9ooyprA,2485
12
- wwvb/testls.py,sha256=Kz4-MWLaUKABwyql8sWdzvtg8gipxhHv4r-6fn3fptg,1720
13
- wwvb/testpm.py,sha256=I5ajzZjUypyKszSe4sTnMZbS43nPmee4H1G3uZlHC_w,935
14
- wwvb/testuwwvb.py,sha256=oj68-Vv1EFBG9MOWB8zW2sTN1Yg22nVYOL_Aor3IJTI,8398
15
- wwvb/testwwvb.py,sha256=bWMI0-Qbaye9Afil4qyPKsNYtY-B6d1wBJZUn-MS99w,16109
16
- wwvb/tz.py,sha256=XVYh0btrnyP_nUiZUwBjufkYbb26_DTiZVl-R_1BA2A,299
17
- wwvb/updateiers.py,sha256=zpMvIzuPvKdA-XvBcOwQiFx7e9yH-V-VypL95bG5rWk,7240
18
- wwvb/wwvbtk.py,sha256=fFXoyReyGZIEpddz74KY0vKfLm1ZP1jwDHTTAbVd8XY,4525
19
- wwvb-3.0.8.dist-info/METADATA,sha256=99ps6bN93tu3nAzKIVWepexqDDaPtfeg_SR4a0c2fRI,10290
20
- wwvb-3.0.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
21
- wwvb-3.0.8.dist-info/entry_points.txt,sha256=KSevvHWLEKxOxUQ-L-OQidD4Sj2BPEfhZ2TQhOgyys4,179
22
- wwvb-3.0.8.dist-info/top_level.txt,sha256=0IYdkhEAMgurpv_F-76rlyn4GdxepGFzG99tivVdQVU,11
23
- wwvb-3.0.8.dist-info/RECORD,,