p3lib 1.1.74__tar.gz → 1.1.76__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.
- {p3lib-1.1.74 → p3lib-1.1.76}/PKG-INFO +1 -1
- {p3lib-1.1.74 → p3lib-1.1.76}/setup.cfg +1 -1
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/ngt.py +148 -54
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib.egg-info/PKG-INFO +1 -1
- {p3lib-1.1.74 → p3lib-1.1.76}/LICENSE +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/README.md +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/pyproject.toml +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/__init__.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/ate.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/bokeh_auth.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/bokeh_gui.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/boot_manager.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/conduit.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/database_if.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/helper.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/json_networking.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/mqtt_rpc.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/netif.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/netplotly.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/pconfig.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/ssh.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/table_plot.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib/uio.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib.egg-info/SOURCES.txt +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib.egg-info/dependency_links.txt +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib.egg-info/requires.txt +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/src/p3lib.egg-info/top_level.txt +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/tests/test_conduit.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/tests/test_json_networking.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/tests/test_netif.py +0 -0
- {p3lib-1.1.74 → p3lib-1.1.76}/tests/test_ssh.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: p3lib
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.76
|
4
4
|
Summary: A group of python modules for networking, plotting data, config storage, automating boot scripts, ssh access and user input output.
|
5
5
|
Home-page: https://github.com/pjaos/p3lib
|
6
6
|
Author: Paul Austen
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[metadata]
|
2
2
|
name = p3lib
|
3
|
-
version = 1.1.
|
3
|
+
version = 1.1.76
|
4
4
|
author = Paul Austen
|
5
5
|
author_email = pausten.os@gmail.com
|
6
6
|
description = A group of python modules for networking, plotting data, config storage, automating boot scripts, ssh access and user input output.
|
@@ -8,22 +8,12 @@
|
|
8
8
|
import traceback
|
9
9
|
import os
|
10
10
|
import platform
|
11
|
-
import argparse
|
12
11
|
|
13
12
|
from time import sleep
|
14
|
-
from p3lib.uio import UIO
|
15
|
-
from p3lib.helper import logTraceBack
|
16
|
-
|
17
13
|
from queue import Queue
|
18
14
|
from time import time, strftime, localtime
|
19
15
|
|
20
|
-
|
21
|
-
from nicegui import ui, app
|
22
|
-
|
23
|
-
from pathlib import Path
|
24
|
-
from typing import Optional
|
25
|
-
|
26
|
-
from nicegui import events
|
16
|
+
from nicegui import ui
|
27
17
|
|
28
18
|
class TabbedNiceGui(object):
|
29
19
|
"""@brief Responsible for starting the providing a tabbed GUI.
|
@@ -38,6 +28,7 @@ class TabbedNiceGui(object):
|
|
38
28
|
# than normal.
|
39
29
|
DESCRIP_STYLE = '<span style="font-size:1.2em;">'
|
40
30
|
ENABLE_BUTTONS = "ENABLE_BUTTONS"
|
31
|
+
NOTIFY_DIALOG = "NOTIFY_DIALOG"
|
41
32
|
UPDATE_SECONDS = "UPDATE_SECONDS"
|
42
33
|
INFO_MESSAGE = "INFO: "
|
43
34
|
WARN_MESSAGE = "WARN: "
|
@@ -46,6 +37,7 @@ class TabbedNiceGui(object):
|
|
46
37
|
MAX_PROGRESS_VALUE = 100
|
47
38
|
DEFAULT_SERVER_PORT = 9812
|
48
39
|
GUI_TIMER_SECONDS = 0.1
|
40
|
+
PROGRESS_TIMER_SECONDS = 1.0
|
49
41
|
UPDATE_SECONDS = "UPDATE_SECONDS"
|
50
42
|
DEFAULT_GUI_RESPONSE_TIMEOUT= 30.0
|
51
43
|
POETRY_CONFIG_FILE = "pyproject.toml"
|
@@ -72,6 +64,15 @@ class TabbedNiceGui(object):
|
|
72
64
|
logFileName = f"{logFilePrefix}_{dateTimeStamp}.log"
|
73
65
|
return logFileName
|
74
66
|
|
67
|
+
@staticmethod
|
68
|
+
def CheckPort(port):
|
69
|
+
"""@brief Check the server port.
|
70
|
+
@param port The server port."""
|
71
|
+
if port < 1024:
|
72
|
+
raise Exception("The minimum TCP port that you can bind the GUI server to is 1024.")
|
73
|
+
if port > 65535:
|
74
|
+
raise Exception("The maximum TCP port that you can bind the GUI server to is 65535.")
|
75
|
+
|
75
76
|
@staticmethod
|
76
77
|
def GetProgramVersion():
|
77
78
|
"""@brief Get the program version from the poetry pyproject.toml file.
|
@@ -99,17 +100,22 @@ class TabbedNiceGui(object):
|
|
99
100
|
if programVersion is None:
|
100
101
|
raise Exception(f"Failed to extract program version from '{line}' line of {poetryConfigFile} file.")
|
101
102
|
return programVersion
|
102
|
-
|
103
|
+
|
103
104
|
def __init__(self, debugEnabled, logPath=None):
|
104
105
|
"""@brief Constructor
|
105
106
|
@param debugEnabled True if debugging is enabled.
|
106
107
|
@param logPath The path to store log files. If left as None then no log files are created."""
|
107
|
-
self._debugEnabled
|
108
|
-
self._logFile
|
109
|
-
self._buttonList
|
110
|
-
self._logMessageCount
|
111
|
-
self.
|
112
|
-
self.
|
108
|
+
self._debugEnabled = debugEnabled
|
109
|
+
self._logFile = None # This must be defined in subclass if logging to a file is required.
|
110
|
+
self._buttonList = []
|
111
|
+
self._logMessageCount = 0
|
112
|
+
self._updateProgressOnTimer = False
|
113
|
+
self._progressStepValue = 0
|
114
|
+
self._progressBarStartMessage = ""
|
115
|
+
self._progressBarExpectedMessageList = []
|
116
|
+
self._expectedProgressBarMessageIndex = 0
|
117
|
+
self._expectedProgressBarMsgCount = 0
|
118
|
+
self._programVersion = TabbedNiceGui.GetProgramVersion()
|
113
119
|
|
114
120
|
self._logPath = None
|
115
121
|
if logPath:
|
@@ -145,29 +151,35 @@ class TabbedNiceGui(object):
|
|
145
151
|
"""@brief Send a info message to be displayed in the GUI.
|
146
152
|
This can be called from outside the GUI thread.
|
147
153
|
@param msg The message to be displayed."""
|
148
|
-
msgDict = {TabbedNiceGui.INFO_MESSAGE: msg}
|
154
|
+
msgDict = {TabbedNiceGui.INFO_MESSAGE: str(msg)}
|
149
155
|
self.updateGUI(msgDict)
|
150
156
|
|
151
157
|
def warn(self, msg):
|
152
158
|
"""@brief Send a warning message to be displayed in the GUI.
|
153
159
|
This can be called from outside the GUI thread.
|
154
160
|
@param msg The message to be displayed."""
|
155
|
-
msgDict = {TabbedNiceGui.WARN_MESSAGE: msg}
|
161
|
+
msgDict = {TabbedNiceGui.WARN_MESSAGE: str(msg)}
|
156
162
|
self.updateGUI(msgDict)
|
157
163
|
|
158
164
|
def error(self, msg):
|
159
165
|
"""@brief Send a error message to be displayed in the GUI.
|
160
166
|
This can be called from outside the GUI thread.
|
161
167
|
@param msg The message to be displayed."""
|
162
|
-
msgDict = {TabbedNiceGui.ERROR_MESSAGE:
|
168
|
+
msgDict = {TabbedNiceGui.ERROR_MESSAGE: str(msg)}
|
163
169
|
self.updateGUI(msgDict)
|
164
170
|
|
171
|
+
def infoDialog(self, msg):
|
172
|
+
"""@brief Display an info level dialog.
|
173
|
+
@param msg The message dialog."""
|
174
|
+
msgDict = {TabbedNiceGui.NOTIFY_DIALOG: str(msg)}
|
175
|
+
self.updateGUI(msgDict)
|
176
|
+
|
165
177
|
def debug(self, msg):
|
166
178
|
"""@brief Send a debug message to be displayed in the GUI.
|
167
179
|
This can be called from outside the GUI thread.
|
168
180
|
@param msg The message to be displayed."""
|
169
181
|
if self._debugEnabled:
|
170
|
-
msgDict = {TabbedNiceGui.DEBUG_MESSAGE: msg}
|
182
|
+
msgDict = {TabbedNiceGui.DEBUG_MESSAGE: str(msg)}
|
171
183
|
self.updateGUI(msgDict)
|
172
184
|
|
173
185
|
async def getInput(self, prompt):
|
@@ -193,11 +205,11 @@ class TabbedNiceGui(object):
|
|
193
205
|
If not then the exception message is displayed.
|
194
206
|
@param exception The exception instance."""
|
195
207
|
if self._debugEnabled:
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
208
|
+
lines = traceback.format_exc().split("\n")
|
209
|
+
for line in lines:
|
210
|
+
self.error(line)
|
211
|
+
if len(exception.args) > 0:
|
212
|
+
self.error(exception.args[0])
|
201
213
|
|
202
214
|
def _sendEnableAllButtons(self, state):
|
203
215
|
"""@brief Send a message to the GUI to enable/disable all the GUI buttons.
|
@@ -303,7 +315,8 @@ class TabbedNiceGui(object):
|
|
303
315
|
self._log.push(msg)
|
304
316
|
self._saveLogMsg(msg)
|
305
317
|
self._logMessageCount += 1
|
306
|
-
|
318
|
+
# We've received a log message so update progress bar if required.
|
319
|
+
self._updateProgressBar(msg)
|
307
320
|
|
308
321
|
def _infoGT(self, msg):
|
309
322
|
"""@brief Update an info level message. This must be called from the GUI thread.
|
@@ -344,7 +357,9 @@ class TabbedNiceGui(object):
|
|
344
357
|
if enabled:
|
345
358
|
for button in self._buttonList:
|
346
359
|
button.enable()
|
347
|
-
|
360
|
+
# No buttons are enabled, any executed task must be complete therefor hide the progress bar.
|
361
|
+
self._stopProgress()
|
362
|
+
|
348
363
|
else:
|
349
364
|
for button in self._buttonList:
|
350
365
|
button.disable()
|
@@ -352,8 +367,8 @@ class TabbedNiceGui(object):
|
|
352
367
|
if self._progressStepValue > 0:
|
353
368
|
self._progress.set_visibility(True)
|
354
369
|
|
355
|
-
def
|
356
|
-
"""@called periodically to allow updates of the GUI."""
|
370
|
+
def guiTimerCallback(self):
|
371
|
+
"""@called periodically (quickly) to allow updates of the GUI."""
|
357
372
|
while not self._toGUIQueue.empty():
|
358
373
|
rxMessage = self._toGUIQueue.get()
|
359
374
|
if isinstance(rxMessage, dict):
|
@@ -391,39 +406,115 @@ class TabbedNiceGui(object):
|
|
391
406
|
ui.label("Message Log")
|
392
407
|
self._progress = ui.slider(min=0,max=TabbedNiceGui.MAX_PROGRESS_VALUE,step=1)
|
393
408
|
self._progress.set_visibility(False)
|
409
|
+
self._progress.min = 0
|
410
|
+
# Don't allow user to adjust progress bar thumb
|
411
|
+
self._progress.disable()
|
394
412
|
self._log = ui.log(max_lines=2000)
|
395
413
|
self._log.set_visibility(True)
|
396
414
|
|
397
415
|
with ui.row():
|
398
|
-
ui.button('Quit', on_click=self.close)
|
399
|
-
ui.button('Log Message Count', on_click=self._showLogMsgCount)
|
400
416
|
ui.button('Clear Log', on_click=self._clearLog)
|
417
|
+
ui.button('Log Message Count', on_click=self._showLogMsgCount)
|
418
|
+
ui.button('Quit', on_click=self.close)
|
401
419
|
|
402
420
|
with ui.row():
|
403
421
|
ui.label(f"Software Version: {self._programVersion}")
|
404
422
|
|
405
|
-
ui.timer(interval=TabbedNiceGui.GUI_TIMER_SECONDS, callback=self.
|
423
|
+
ui.timer(interval=TabbedNiceGui.GUI_TIMER_SECONDS, callback=self.guiTimerCallback)
|
424
|
+
ui.timer(interval=TabbedNiceGui.PROGRESS_TIMER_SECONDS, callback=self.progressTimerCallback)
|
406
425
|
ui.run(host=address, port=port, title=pageTitle, dark=True, uvicorn_logging_level=guiLogLevel, reload=reload)
|
407
426
|
|
408
|
-
def
|
409
|
-
"""@brief
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
427
|
+
def progressTimerCallback(self):
|
428
|
+
"""@brief Time to update the progress bar. We run the timer all the time because there appears to be a
|
429
|
+
bug in the ui.timer instance. Calling cancel() does not appear to cancel the timer."""
|
430
|
+
if self._updateProgressOnTimer and self._progress.visible:
|
431
|
+
# Increment the progress bar
|
432
|
+
self._progress.set_value( self._progress.value + self._progressStepValue )
|
433
|
+
|
434
|
+
def _startProgress(self, durationSeconds=0, startMessage=None, expectedMsgList=[], expectedMsgCount=0):
|
435
|
+
"""@brief Start a timer that will update the progress bar.
|
436
|
+
The progress bar can simply update on a timer every second with durationSeconds set to the expected length
|
437
|
+
of the task.
|
438
|
+
|
439
|
+
If startMessage is set to a text string the progress time will not start until the log message area contains
|
440
|
+
the start message.
|
441
|
+
|
442
|
+
Alternatively if expectedMsgList contains a list of strings we expect to receive then the progress bar is
|
443
|
+
updated as each message is received. The messages may be the entire line of a log message or parts of a
|
444
|
+
log message line.
|
445
|
+
|
446
|
+
Alternatively if expectedMsgCount is set to a value > 0 then the progress bar is updated as each message is
|
447
|
+
added to the log and reaches 100% when the number of messages added to the log file reaches the expectedMsgCount.
|
448
|
+
|
449
|
+
@param startMessage The text of the log message we expect to receive to trigger the progress bar timer start.
|
450
|
+
@param expectedMsgList A list of the expected log file messages.
|
451
|
+
@param expectedMsgCount A int value that defines the number of log messages we expect to receive for normal progress
|
452
|
+
completion."""
|
453
|
+
self._progressValue = 0
|
454
|
+
self._progressBarStartMessage = ""
|
455
|
+
self._progressBarExpectedMessageList = []
|
456
|
+
self._expectedProgressBarMessageIndex = 0
|
457
|
+
self._expectedProgressBarMsgCount = 0
|
458
|
+
self._updateProgressOnTimer = False
|
459
|
+
self._progress.set_value( self._progressValue )
|
460
|
+
# If the caller wants to the progress bar to update as the log file message count increases.
|
461
|
+
if expectedMsgCount > 0:
|
462
|
+
self._expectedProgressBarMsgCount = expectedMsgCount
|
463
|
+
self._progressStepValue = TabbedNiceGui.MAX_PROGRESS_VALUE/float(self._expectedProgressBarMsgCount)
|
464
|
+
|
465
|
+
# If the caller wants to update the progress bar on expected messages.
|
466
|
+
elif len(expectedMsgList):
|
467
|
+
#Use the text of log messages to increment the progress bar.
|
468
|
+
self._expectedProgressBarMessageIndex = 0
|
469
|
+
self._progressBarExpectedMessageList = expectedMsgList
|
470
|
+
self._progressStepValue = TabbedNiceGui.MAX_PROGRESS_VALUE/float(len(expectedMsgList))
|
471
|
+
|
472
|
+
elif durationSeconds > 0:
|
473
|
+
# Calc the step size required to give the required duration
|
474
|
+
self._progressStepValue = TabbedNiceGui.MAX_PROGRESS_VALUE/float(durationSeconds)
|
475
|
+
if startMessage:
|
476
|
+
self._progressBarStartMessage = startMessage
|
477
|
+
else:
|
478
|
+
# Start updating the progress bar now.
|
479
|
+
self._updateProgressOnTimer = True
|
480
|
+
|
417
481
|
else:
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
def
|
423
|
-
"""@brief
|
424
|
-
|
425
|
-
|
426
|
-
|
482
|
+
raise Exception("BUG: _startProgressTimer() called. len(expectedMsgList)=0 and durationSeconds<=0.")
|
483
|
+
|
484
|
+
self._progress.set_visibility(True)
|
485
|
+
|
486
|
+
def _stopProgress(self):
|
487
|
+
"""@brief Stop the progress bar being updated and hide it."""
|
488
|
+
self._updateProgressOnTimer = False
|
489
|
+
self._progress.set_visibility(False)
|
490
|
+
|
491
|
+
def _updateProgressBar(self, msg):
|
492
|
+
"""@brief Update the progress bar if required when a log message is received. This is called as each message is added to the log.
|
493
|
+
@param msg The log message received."""
|
494
|
+
# If we update the progress bar as each message is received until we have a log with self._expectedProgressBarMsgCount many messages.
|
495
|
+
if self._expectedProgressBarMsgCount > 0:
|
496
|
+
self._progressValue = self._progressValue + self._progressStepValue
|
497
|
+
self._progress.set_value( self._progressValue )
|
498
|
+
|
499
|
+
# If we have a list of log messages to update the progress bar.
|
500
|
+
elif len(self._progressBarExpectedMessageList) > 0:
|
501
|
+
if self._expectedProgressBarMessageIndex < len(self._progressBarExpectedMessageList):
|
502
|
+
# Get the message we expect to receive next
|
503
|
+
expectedMsg = self._progressBarExpectedMessageList[self._expectedProgressBarMessageIndex]
|
504
|
+
if msg.find(expectedMsg) != -1:
|
505
|
+
self._progressValue = self._progressValue + self._progressStepValue
|
506
|
+
self._progress.set_value( self._progressValue )
|
507
|
+
self._expectedProgressBarMessageIndex += 1
|
508
|
+
|
509
|
+
# If we have a message that we expect to receive to start the progress bar timer.
|
510
|
+
elif self._progressBarStartMessage and len(self._progressBarStartMessage):
|
511
|
+
# If we found the start message in the message received.
|
512
|
+
if msg.find(self._progressBarStartMessage) != -1:
|
513
|
+
# Start updating the progress bar now on the timer.
|
514
|
+
self._updateProgressOnTimer = True
|
515
|
+
|
516
|
+
def _initTask(self):
|
517
|
+
"""@brief Should be called before a task is started."""
|
427
518
|
self._enableAllButtons(False)
|
428
519
|
self._clearMessages()
|
429
520
|
|
@@ -438,7 +529,7 @@ class TabbedNiceGui(object):
|
|
438
529
|
|
439
530
|
def close(self):
|
440
531
|
"""@brief Close down the app server."""
|
441
|
-
ui.notify("Press 'CTRL C' at command line to quit.")
|
532
|
+
ui.notify("Press 'CTRL C' at command line or close the terminal window to quit.")
|
442
533
|
# A subclass close() method can call
|
443
534
|
# app.shutdown()
|
444
535
|
# if reload=False on ui.run()
|
@@ -471,6 +562,10 @@ class TabbedNiceGui(object):
|
|
471
562
|
state = rxDict[TabbedNiceGui.ENABLE_BUTTONS]
|
472
563
|
self._enableAllButtons(state)
|
473
564
|
|
565
|
+
elif TabbedNiceGui.NOTIFY_DIALOG in rxDict:
|
566
|
+
message = rxDict[TabbedNiceGui.NOTIFY_DIALOG]
|
567
|
+
ui.notify(message, close_button='OK', type="positive", position="center")
|
568
|
+
|
474
569
|
else:
|
475
570
|
|
476
571
|
self._handleGUIUpdate(rxDict)
|
@@ -714,4 +809,3 @@ class YesNoDialog(object):
|
|
714
809
|
def close(self):
|
715
810
|
"""@brief Close the boolean dialog."""
|
716
811
|
self._dialog.close()
|
717
|
-
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: p3lib
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.76
|
4
4
|
Summary: A group of python modules for networking, plotting data, config storage, automating boot scripts, ssh access and user input output.
|
5
5
|
Home-page: https://github.com/pjaos/p3lib
|
6
6
|
Author: Paul Austen
|
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
|