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.
- {egauge_python-0.9.4/egauge_python.egg-info → egauge-python-0.9.6}/PKG-INFO +2 -9
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/ctid.py +1 -1
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/encoder.py +1 -1
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/pyside/terminal.py +1 -1
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/auth.py +43 -11
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/register_type.py +23 -28
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/virtual_register.py +1 -1
- {egauge_python-0.9.4 → egauge-python-0.9.6/egauge_python.egg-info}/PKG-INFO +2 -9
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/top_level.txt +0 -1
- {egauge_python-0.9.4 → egauge-python-0.9.6}/setup.py +1 -1
- {egauge_python-0.9.4 → egauge-python-0.9.6}/LICENSE +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/README.md +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/__init__.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/bit_stuffer.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/intel_hex_encoder.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/ctid/waveform.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/data/test-ctid-decoder.raw +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_capture.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_common.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_ctid.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_ctid_decoder.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_local.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/examples/test_register.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/pyside/__init__.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/pyside/ansi2html.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/__init__.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/__init__.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/credentials.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/credentials_dialog.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/gui/credentials_dialog.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/cloud/serial_number.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/__init__.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/capture.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/ctid_info.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/device.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/local.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/physical_quantity.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/physical_units.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/register.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/register_row.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/device/slop.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/error.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge/webapi/json_api.py +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/SOURCES.txt +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/dependency_links.txt +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/entry_points.txt +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/egauge_python.egg-info/requires.txt +0 -0
- {egauge_python-0.9.4 → egauge-python-0.9.6}/pyproject.toml +0 -0
- {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.
|
|
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
|
-
|
|
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
|
|
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} "
|
|
@@ -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;\
|
|
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
|
-
#
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
|
297
|
+
if not isinstance(auth_reply, dict):
|
|
276
298
|
return r
|
|
277
299
|
|
|
278
|
-
|
|
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
|
-
|
|
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("
|
|
679
|
-
pus.add(au)
|
|
680
|
-
pus.add_scaled(au, "
|
|
681
|
-
pus.add_scaled(au, "
|
|
682
|
-
pus.add_scaled(au, "
|
|
683
|
-
pus.add_scaled(au, "
|
|
684
|
-
pus.add_scaled(au, "
|
|
685
|
-
pus.add_scaled(au, "
|
|
686
|
-
pus.add_scaled(au, "μ
|
|
687
|
-
pus.add_scaled(au, "
|
|
688
|
-
pus.add_scaled(au, "
|
|
689
|
-
pus.add_scaled(au, "
|
|
690
|
-
pus.add_scaled(au, "
|
|
691
|
-
pus.add_scaled(au, "
|
|
692
|
-
pus.add_scaled(au, "
|
|
693
|
-
pus.add_scaled(au, "
|
|
694
|
-
pus.add_scaled(au, "
|
|
695
|
-
pus.add_scaled(au, "
|
|
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', '
|
|
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', '
|
|
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='
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|