egauge-python 0.9.4__tar.gz → 0.9.6__tar.gz

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.
Files changed (49) hide show
  1. {egauge_python-0.9.4/egauge_python.egg-info → egauge-python-0.9.6}/PKG-INFO +2 -9
  2. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/ctid.py +1 -1
  3. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/encoder.py +1 -1
  4. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/pyside/terminal.py +1 -1
  5. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/auth.py +43 -11
  6. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/register_type.py +23 -28
  7. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/virtual_register.py +1 -1
  8. {egauge_python-0.9.4 → egauge-python-0.9.6/egauge_python.egg-info}/PKG-INFO +2 -9
  9. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/top_level.txt +0 -1
  10. {egauge_python-0.9.4 → egauge-python-0.9.6}/setup.py +1 -1
  11. {egauge_python-0.9.4 → egauge-python-0.9.6}/LICENSE +0 -0
  12. {egauge_python-0.9.4 → egauge-python-0.9.6}/README.md +0 -0
  13. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/__init__.py +0 -0
  14. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/bit_stuffer.py +0 -0
  15. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/intel_hex_encoder.py +0 -0
  16. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/waveform.py +0 -0
  17. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/data/test-ctid-decoder.raw +0 -0
  18. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_capture.py +0 -0
  19. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_common.py +0 -0
  20. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_ctid.py +0 -0
  21. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_ctid_decoder.py +0 -0
  22. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_local.py +0 -0
  23. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_register.py +0 -0
  24. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/pyside/__init__.py +0 -0
  25. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/pyside/ansi2html.py +0 -0
  26. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/__init__.py +0 -0
  27. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/__init__.py +0 -0
  28. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/credentials.py +0 -0
  29. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/credentials_dialog.py +0 -0
  30. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/gui/credentials_dialog.py +0 -0
  31. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/serial_number.py +0 -0
  32. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/__init__.py +0 -0
  33. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/capture.py +0 -0
  34. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/ctid_info.py +0 -0
  35. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/device.py +0 -0
  36. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/local.py +0 -0
  37. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/physical_quantity.py +0 -0
  38. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/physical_units.py +0 -0
  39. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/register.py +0 -0
  40. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/register_row.py +0 -0
  41. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/slop.py +0 -0
  42. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/error.py +0 -0
  43. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/json_api.py +0 -0
  44. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/SOURCES.txt +0 -0
  45. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/dependency_links.txt +0 -0
  46. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/entry_points.txt +0 -0
  47. {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/requires.txt +0 -0
  48. {egauge_python-0.9.4 → egauge-python-0.9.6}/pyproject.toml +0 -0
  49. {egauge_python-0.9.4 → egauge-python-0.9.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: egauge-python
3
- Version: 0.9.4
3
+ Version: 0.9.6
4
4
  Summary: .
5
5
  Home-page: https://bitbucket.org/egauge/python/
6
6
  Author: David Mosberger-Tang
@@ -15,16 +15,9 @@ Classifier: Programming Language :: Python :: 3
15
15
  Classifier: Programming Language :: Python :: 3.6
16
16
  Requires-Python: >=3.11
17
17
  Description-Content-Type: text/markdown
18
- License-File: LICENSE
19
- Requires-Dist: crcmod
20
- Requires-Dist: deprecated
21
- Requires-Dist: intelhex
22
- Requires-Dist: requests>=2.4.2
23
18
  Provides-Extra: examples
24
- Requires-Dist: matplotlib; extra == "examples"
25
- Requires-Dist: readchar; extra == "examples"
26
19
  Provides-Extra: pyside
27
- Requires-Dist: PySide6; extra == "pyside"
20
+ License-File: LICENSE
28
21
 
29
22
  # eGauge open source Python code
30
23
 
@@ -490,7 +490,7 @@ class Table:
490
490
  f"delay={self.delay:g}μs"
491
491
  )
492
492
  elif self.sensor_type == SENSOR_TYPE_TEMP_LINEAR:
493
- ret += f"scale={self.scale:g}°C/V " f"offset={self.offset:g}°C"
493
+ ret += f"scale={self.scale:g}°C/V offset={self.offset:g}°C"
494
494
  elif self.sensor_type == SENSOR_TYPE_TEMP_NTC:
495
495
  ret += (
496
496
  f"A={self.ntc_a:g} "
@@ -238,7 +238,7 @@ def main():
238
238
  "--bias-voltage",
239
239
  type=float,
240
240
  default=0,
241
- help="Output voltage when no current " "is flowing through the CD.",
241
+ help="Output voltage when no current is flowing through the CD.",
242
242
  )
243
243
  #
244
244
  # Linear Parameters:
@@ -215,7 +215,7 @@ def test():
215
215
  self.plainTextEdit.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
216
216
  self.plainTextEdit.setAcceptDrops(False)
217
217
  self.plainTextEdit.setStyleSheet(
218
- "background-color: black;\n" "color: white;\n"
218
+ "background-color: black;\ncolor: white;\n"
219
219
  )
220
220
  self.plainTextEdit.setLineWidth(1)
221
221
  self.plainTextEdit.setUndoRedoEnabled(False)
@@ -1,6 +1,6 @@
1
1
  #
2
- # Copyright (c) 2020-2022, 2024 eGauge Systems LLC
3
- # 1644 Conestoga St, Suite 2
2
+ # Copyright (c) 2020-2022, 2024-2025 eGauge Systems LLC
3
+ # 4805 Sterling Dr, Suite 1
4
4
  # Boulder, CO 80301
5
5
  # voice: 720-545-9767
6
6
  # email: davidm@egauge.net
@@ -34,6 +34,7 @@ token-based authentication (TokenAuth).
34
34
  """
35
35
 
36
36
  import hashlib
37
+ import logging
37
38
  import os
38
39
  import secrets
39
40
  import types
@@ -49,6 +50,10 @@ from . import json_api
49
50
  # The name of the optional environment variable storing a token:
50
51
  ENV_EGAUGE_API_TOKEN = "EGAUGE_API_TOKEN"
51
52
 
53
+ MAX_RETRIES = 10
54
+
55
+ log = logging.getLogger(__name__)
56
+
52
57
 
53
58
  def _decorate_public_metaclass(decorator):
54
59
  """Return a metaclass which will decorate all public methods of a
@@ -109,7 +114,7 @@ class JWTAuth(AuthBase):
109
114
  def __call__(self, r):
110
115
  if self.bearer_token:
111
116
  self.add_auth_header(r)
112
- r.register_hook("response", self.handle_401)
117
+ r.register_hook("response", self.handle_response)
113
118
  return r
114
119
 
115
120
  def __eq__(self, other):
@@ -133,12 +138,12 @@ class JWTAuth(AuthBase):
133
138
 
134
139
  def handle_401(self, r, **kwargs):
135
140
  """Called when server responds with 401 Unauthorized."""
136
- if r.status_code != 401:
137
- return r
141
+ log.debug("handle_401: auth request received for %s", r.request.url)
138
142
 
139
143
  try:
140
144
  auth_request = r.json()
141
145
  except ValueError:
146
+ log.debug("handle_401: auth request is not valid JSON")
142
147
  return r
143
148
 
144
149
  realm = auth_request["rlm"]
@@ -166,10 +171,19 @@ class JWTAuth(AuthBase):
166
171
  auth_reply = json_api.post(login_uri, data, timeout=60, verify=verify)
167
172
 
168
173
  if not isinstance(auth_reply, dict):
174
+ log.debug("handle_401: auth reply is not a dict")
169
175
  return r
170
176
 
171
177
  token = auth_reply.get("jwt")
178
+ if auth_reply.get("error"):
179
+ log.debug(
180
+ "handle_401: auth reply error: %s", auth_reply.get("error")
181
+ )
182
+ return r
172
183
  if not isinstance(token, str):
184
+ log.debug(
185
+ "handle_401: token in auth reply is not a string: %s", token
186
+ )
173
187
  return r
174
188
 
175
189
  self.bearer_token = token
@@ -181,6 +195,17 @@ class JWTAuth(AuthBase):
181
195
  _r.request = prep
182
196
  return _r
183
197
 
198
+ def handle_response(self, r, **kwargs):
199
+ """Called when a server response is received."""
200
+ if r.status_code == 401:
201
+ for i in range(MAX_RETRIES):
202
+ r = self.handle_401(r, **kwargs)
203
+ if r.status_code != 401:
204
+ break
205
+ log.debug("handle_response: auth attempt %d failed", i + 1)
206
+ log.debug("handle_response: returning status %d", r.status_code)
207
+ return r
208
+
184
209
 
185
210
  class TokenAuth(AuthBase):
186
211
  """Implements the eGauge web services' token-based authentication
@@ -227,7 +252,7 @@ class TokenAuth(AuthBase):
227
252
 
228
253
  def __call__(self, r):
229
254
  self.add_auth_header(r)
230
- r.register_hook("response", self.handle_401)
255
+ r.register_hook("response", self.handle_response)
231
256
  return r
232
257
 
233
258
  def __eq__(self, other):
@@ -251,9 +276,6 @@ class TokenAuth(AuthBase):
251
276
 
252
277
  def handle_401(self, r, **kwargs):
253
278
  """Called when server responds with 401 Unauthorized."""
254
- if r.status_code != 401:
255
- return r
256
-
257
279
  usr = self.username
258
280
  pwd = self.password
259
281
 
@@ -272,10 +294,11 @@ class TokenAuth(AuthBase):
272
294
  self.token_service_url, json=creds, timeout=60, verify=verify
273
295
  ).json()
274
296
 
275
- if auth_reply is None:
297
+ if not isinstance(auth_reply, dict):
276
298
  return r
277
299
 
278
- if "token" not in auth_reply:
300
+ token = auth_reply.get("token")
301
+ if not isinstance(token, str) or not token:
279
302
  return r
280
303
 
281
304
  self.token = auth_reply["token"]
@@ -293,6 +316,15 @@ class TokenAuth(AuthBase):
293
316
  _r.request = prep
294
317
  return _r
295
318
 
319
+ def handle_response(self, r, **kwargs):
320
+ """Called when a server response is received."""
321
+ if r.status_code == 401:
322
+ for _ in range(MAX_RETRIES):
323
+ r = self.handle_401(r, **kwargs)
324
+ if r.status_code != 401:
325
+ break
326
+ return r
327
+
296
328
  def _save_token(self):
297
329
  if self.token_file is None or self.token is None:
298
330
  return
@@ -8,13 +8,8 @@
8
8
 
9
9
  from enum import Enum
10
10
 
11
- from .physical_units import (
12
- AlternateUnit,
13
- PhysicalUnitConversion,
14
- PhysicalUnits,
15
- PrimaryUnit,
16
- )
17
-
11
+ from .physical_units import AlternateUnit, PhysicalUnits, \
12
+ PhysicalUnitConversion, PrimaryUnit
18
13
 
19
14
  class UnitSystem(Enum):
20
15
  METRIC = 0
@@ -675,24 +670,24 @@ def _create_units():
675
670
 
676
671
  p38 = PrimaryUnit("var·s")
677
672
  pus.add(p38)
678
- au = AlternateUnit("vahr", p38, c3)
679
- pus.add(au)
680
- pus.add_scaled(au, "yvahr", 1e+24, "yocto")
681
- pus.add_scaled(au, "zvahr", 1e+21, "zepto")
682
- pus.add_scaled(au, "avahr", 1e+18, "atto")
683
- pus.add_scaled(au, "fvahr", 1000000000000000, "femto")
684
- pus.add_scaled(au, "pvahr", 1000000000000, "pico")
685
- pus.add_scaled(au, "nvahr", 1000000000, "nano")
686
- pus.add_scaled(au, "μvahr", 1000000, "micro")
687
- pus.add_scaled(au, "mvahr", 1000, "milli")
688
- pus.add_scaled(au, "kvahr", 1 / 1000, "kilo")
689
- pus.add_scaled(au, "Mvahr", 1 / 1000000, "mega")
690
- pus.add_scaled(au, "Gvahr", 1 / 1000000000, "giga")
691
- pus.add_scaled(au, "Tvahr", 1 / 1000000000000, "tera")
692
- pus.add_scaled(au, "Pvahr", 1 / 1000000000000000, "peta")
693
- pus.add_scaled(au, "Evahr", 1 / 1e+18, "exa")
694
- pus.add_scaled(au, "Zvahr", 1 / 1e+21, "zetta")
695
- pus.add_scaled(au, "Yvahr", 1 / 1e+24, "yotta")
673
+ au = AlternateUnit("varh", p38, c3)
674
+ pus.add(au)
675
+ pus.add_scaled(au, "yvarh", 1e+24, "yocto")
676
+ pus.add_scaled(au, "zvarh", 1e+21, "zepto")
677
+ pus.add_scaled(au, "avarh", 1e+18, "atto")
678
+ pus.add_scaled(au, "fvarh", 1000000000000000, "femto")
679
+ pus.add_scaled(au, "pvarh", 1000000000000, "pico")
680
+ pus.add_scaled(au, "nvarh", 1000000000, "nano")
681
+ pus.add_scaled(au, "μvarh", 1000000, "micro")
682
+ pus.add_scaled(au, "mvarh", 1000, "milli")
683
+ pus.add_scaled(au, "kvarh", 1 / 1000, "kilo")
684
+ pus.add_scaled(au, "Mvarh", 1 / 1000000, "mega")
685
+ pus.add_scaled(au, "Gvarh", 1 / 1000000000, "giga")
686
+ pus.add_scaled(au, "Tvarh", 1 / 1000000000000, "tera")
687
+ pus.add_scaled(au, "Pvarh", 1 / 1000000000000000, "peta")
688
+ pus.add_scaled(au, "Evarh", 1 / 1e+18, "exa")
689
+ pus.add_scaled(au, "Zvarh", 1 / 1e+21, "zetta")
690
+ pus.add_scaled(au, "Yvarh", 1 / 1e+24, "yotta")
696
691
 
697
692
  c7 = PhysicalUnitConversion(False,
698
693
  lambda x, t=None: (9/5)*x + 32,
@@ -758,10 +753,10 @@ class Units:
758
753
 
759
754
  # Preferred units for METRIC and IMPERIAL systems:
760
755
  preferred = [
761
- ['kW', 'kWh', 'kVA', 'kVAh', 'kvar', 'kvahr', 'kg', 'kg/s',
756
+ ['kW', 'kWh', 'kVA', 'kVAh', 'kvar', 'kvarh', 'kg', 'kg/s',
762
757
  'kWh/m²', 'km/h', 'hPa', 'Ah', 'Vh', 'L/m', 'L', '°C',
763
758
  '°C·d'],
764
- ['kW', 'kWh', 'kVA', 'kVAh', 'kvar', 'kvahr', 'lbs', 'lbs/s',
759
+ ['kW', 'kWh', 'kVA', 'kVAh', 'kvar', 'kvarh', 'lbs', 'lbs/s',
765
760
  'kWh/m²', 'mph', 'inHg', 'Ah', 'Vh', 'ft', '°F', '°F·d',
766
761
  'lbs·s', 'inHg·s', 'ft·s', 'gpm', 'gal']
767
762
  ]
@@ -804,7 +799,7 @@ class Units:
804
799
  cumul_scale=1 / 3600000, cumul_unit='kWh/m²',
805
800
  name='Irradiance'),
806
801
  'PQ': UnitTableEntry(fix_scale=1, rate_unit='var',
807
- cumul_scale=1 / 3600000, cumul_unit='kvahr',
802
+ cumul_scale=1 / 3600000, cumul_unit='kvarh',
808
803
  name='Reactive Power'),
809
804
  '$': UnitTableEntry(fix_scale=536870912, rate_unit='${currency}/s',
810
805
  cumul_scale=1 / 536870912, cumul_unit='${currency}',
@@ -193,7 +193,7 @@ class VirtualRegister(Generic[RegId]):
193
193
  """
194
194
 
195
195
  def error(reason: str) -> NoReturn:
196
- raise VirtRegError(f"{reason} (rest: '{formula[state.idx:]}')")
196
+ raise VirtRegError(f"{reason} (rest: '{formula[state.idx :]}')")
197
197
 
198
198
  def whitespace():
199
199
  while state.idx < len(formula) and formula[state.idx] in [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: egauge-python
3
- Version: 0.9.4
3
+ Version: 0.9.6
4
4
  Summary: .
5
5
  Home-page: https://bitbucket.org/egauge/python/
6
6
  Author: David Mosberger-Tang
@@ -15,16 +15,9 @@ Classifier: Programming Language :: Python :: 3
15
15
  Classifier: Programming Language :: Python :: 3.6
16
16
  Requires-Python: >=3.11
17
17
  Description-Content-Type: text/markdown
18
- License-File: LICENSE
19
- Requires-Dist: crcmod
20
- Requires-Dist: deprecated
21
- Requires-Dist: intelhex
22
- Requires-Dist: requests>=2.4.2
23
18
  Provides-Extra: examples
24
- Requires-Dist: matplotlib; extra == "examples"
25
- Requires-Dist: readchar; extra == "examples"
26
19
  Provides-Extra: pyside
27
- Requires-Dist: PySide6; extra == "pyside"
20
+ License-File: LICENSE
28
21
 
29
22
  # eGauge open source Python code
30
23
 
@@ -10,7 +10,7 @@ os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
10
10
 
11
11
  setuptools.setup(
12
12
  name="egauge-python",
13
- version="0.9.4",
13
+ version="0.9.6",
14
14
  packages=setuptools.find_namespace_packages(include="egauge.*"),
15
15
  install_requires=[
16
16
  "crcmod",
File without changes
File without changes
File without changes