rda-python-common 3.0.29__tar.gz → 3.0.30__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.
- {rda_python_common-3.0.29/src/rda_python_common.egg-info → rda_python_common-3.0.30}/PKG-INFO +2 -2
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/README.md +1 -1
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/pyproject.toml +1 -1
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/__init__.py +1 -1
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_sig.py +74 -6
- {rda_python_common-3.0.29 → rda_python_common-3.0.30/src/rda_python_common.egg-info}/PKG-INFO +2 -2
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/LICENSE +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/setup.cfg +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/PgCMD.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/PgDBI.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/PgFile.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/PgLOG.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/PgLock.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/PgOPT.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/PgSIG.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/PgSplit.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/PgUtil.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_cmd.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_dbi.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_file.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_lock.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_log.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_opt.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_password.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_split.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pg_util.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pgpassword.py +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common/pgpassword.usg +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common.egg-info/SOURCES.txt +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common.egg-info/dependency_links.txt +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common.egg-info/entry_points.txt +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common.egg-info/requires.txt +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common.egg-info/top_level.txt +0 -0
- {rda_python_common-3.0.29 → rda_python_common-3.0.30}/test/test_common.py +0 -0
{rda_python_common-3.0.29/src/rda_python_common.egg-info → rda_python_common-3.0.30}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rda_python_common
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.30
|
|
4
4
|
Summary: RDA Python common library codes shared by other RDA python packages
|
|
5
5
|
Author-email: Zaihua Ji <zji@ucar.edu>
|
|
6
6
|
Project-URL: Homepage, https://github.com/NCAR/rda-python-common
|
|
@@ -189,7 +189,7 @@ PgLOG.pglog("hello", PgLOG.LOGWRN)
|
|
|
189
189
|
python -c "import rda_python_common; print(rda_python_common.__version__)"
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
-
You should see the installed version (currently `3.0.
|
|
192
|
+
You should see the installed version (currently `3.0.30`). If the import
|
|
193
193
|
fails, double-check that the active Python environment is the one where you
|
|
194
194
|
ran `pip install`.
|
|
195
195
|
|
|
@@ -165,7 +165,7 @@ PgLOG.pglog("hello", PgLOG.LOGWRN)
|
|
|
165
165
|
python -c "import rda_python_common; print(rda_python_common.__version__)"
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
-
You should see the installed version (currently `3.0.
|
|
168
|
+
You should see the installed version (currently `3.0.30`). If the import
|
|
169
169
|
fails, double-check that the active Python environment is the one where you
|
|
170
170
|
ran `pip install`.
|
|
171
171
|
|
|
@@ -13,6 +13,7 @@ import re
|
|
|
13
13
|
import sys
|
|
14
14
|
import errno
|
|
15
15
|
import signal
|
|
16
|
+
import select
|
|
16
17
|
import time
|
|
17
18
|
import subprocess
|
|
18
19
|
import psutil
|
|
@@ -57,6 +58,7 @@ class PgSIG(PgDBI):
|
|
|
57
58
|
'WTINC': 5, # seconds added to the adaptive wait after each loop still waiting
|
|
58
59
|
'CWTIME': 0, # current adaptive wait (in seconds), 0 before the first wait
|
|
59
60
|
'WLOOP': -1, # loop count of the last adaptive wait sleep
|
|
61
|
+
'WPIPE': None, # (read fd, write fd) of the pipe SIGCHLD writes to wake up a wait
|
|
60
62
|
'DTIME': 600, # the daemon record refresh time (in seconds)
|
|
61
63
|
'RTIME': 2400, # the web rda config unlocking and unconfigured system down waiting time (in seconds)
|
|
62
64
|
'CTIME': 4800, # the lock cleaning & configued system down waiting time (in seconds)
|
|
@@ -158,6 +160,7 @@ class PgSIG(PgDBI):
|
|
|
158
160
|
os.umask(0)
|
|
159
161
|
# setup to catch signals in daemon only
|
|
160
162
|
signal.signal(signal.SIGCHLD, self.clean_dead_child)
|
|
163
|
+
self.open_wake_pipe()
|
|
161
164
|
signal.signal(signal.SIGQUIT, self.signal_catch)
|
|
162
165
|
signal.signal(signal.SIGUSR1, self.signal_catch)
|
|
163
166
|
signal.signal(signal.SIGUSR2, self.signal_catch)
|
|
@@ -560,7 +563,7 @@ class PgSIG(PgDBI):
|
|
|
560
563
|
signum (int): The signal number received (expected to be SIGCHLD).
|
|
561
564
|
frame: The current stack frame (unused).
|
|
562
565
|
"""
|
|
563
|
-
live = 0
|
|
566
|
+
live = wake = 0
|
|
564
567
|
while True:
|
|
565
568
|
try:
|
|
566
569
|
dpid, status = os.waitpid(-1, os.WNOHANG)
|
|
@@ -574,7 +577,57 @@ class PgSIG(PgDBI):
|
|
|
574
577
|
if live > 0: break # wait twice if a process is still a live
|
|
575
578
|
live += 1
|
|
576
579
|
elif self.PGSIG['PPID'] < 2:
|
|
577
|
-
if dpid in self.CPIDS:
|
|
580
|
+
if dpid in self.CPIDS:
|
|
581
|
+
del self.CPIDS[dpid]
|
|
582
|
+
wake = 1
|
|
583
|
+
if wake: self.wake_waiter() # a managed child is done; end any wait for it now
|
|
584
|
+
|
|
585
|
+
# open the pipe a SIGCHLD handler writes to, so a wait for processes wakes up at once
|
|
586
|
+
def open_wake_pipe(self):
|
|
587
|
+
"""Open the non-blocking self-pipe that wakes ``show_wait_message()`` on SIGCHLD.
|
|
588
|
+
|
|
589
|
+
``clean_dead_child()`` writes one byte to it when a child process in ``CPIDS``
|
|
590
|
+
is done, and ``show_wait_message()`` waits on it with the adaptive wait time as
|
|
591
|
+
the timeout, so a free process slot is used at once instead of after a sleep.
|
|
592
|
+
"""
|
|
593
|
+
if self.PGSIG['WPIPE']: return
|
|
594
|
+
try:
|
|
595
|
+
rfd, wfd = os.pipe()
|
|
596
|
+
os.set_blocking(rfd, False)
|
|
597
|
+
os.set_blocking(wfd, False)
|
|
598
|
+
except OSError as e:
|
|
599
|
+
self.pglog("Cannot open wake pipe, wait by sleeping: {}".format(str(e)), self.LOGWRN)
|
|
600
|
+
return
|
|
601
|
+
self.PGSIG['WPIPE'] = (rfd, wfd)
|
|
602
|
+
|
|
603
|
+
# close the wake pipe, such as in a child process that inherited it
|
|
604
|
+
def close_wake_pipe(self):
|
|
605
|
+
"""Close the SIGCHLD wake pipe and forget it."""
|
|
606
|
+
if not self.PGSIG['WPIPE']: return
|
|
607
|
+
for fd in self.PGSIG['WPIPE']:
|
|
608
|
+
try:
|
|
609
|
+
os.close(fd)
|
|
610
|
+
except OSError:
|
|
611
|
+
pass
|
|
612
|
+
self.PGSIG['WPIPE'] = None
|
|
613
|
+
|
|
614
|
+
# write one byte to the wake pipe to end a wait in show_wait_message()
|
|
615
|
+
def wake_waiter(self):
|
|
616
|
+
"""Wake a wait in ``show_wait_message()``; a full pipe already wakes it."""
|
|
617
|
+
if not self.PGSIG['WPIPE']: return
|
|
618
|
+
try:
|
|
619
|
+
os.write(self.PGSIG['WPIPE'][1], b'x')
|
|
620
|
+
except OSError:
|
|
621
|
+
pass # pipe full (a wake is pending already) or closed
|
|
622
|
+
|
|
623
|
+
# read out all pending wake bytes, so a past wake does not end the next wait
|
|
624
|
+
def drain_wake_pipe(self):
|
|
625
|
+
"""Read out any pending bytes of the SIGCHLD wake pipe."""
|
|
626
|
+
if not self.PGSIG['WPIPE']: return
|
|
627
|
+
try:
|
|
628
|
+
while os.read(self.PGSIG['WPIPE'][0], 512): pass
|
|
629
|
+
except OSError:
|
|
630
|
+
pass # BlockingIOError when empty
|
|
578
631
|
|
|
579
632
|
# send signal to daemon and exit
|
|
580
633
|
def signal_daemon(self, sname, aname, uname):
|
|
@@ -748,6 +801,7 @@ class PgSIG(PgDBI):
|
|
|
748
801
|
self.PGSIG['PID'] = pid = os.getpid()
|
|
749
802
|
self.PGSIG['MPROC'] = 1 # 1 in child process
|
|
750
803
|
self.CBIDS = {} # empty backgroud proces info in case not
|
|
804
|
+
self.close_wake_pipe() # the wake pipe is the parent's
|
|
751
805
|
self.PGSIG['DSTR'] += ": CPID {} for {}".format(pid, pname)
|
|
752
806
|
self.cmdlog("CPID {} for {}".format(pid, pname))
|
|
753
807
|
self.pgdisconnect(0) # disconnect database in child
|
|
@@ -793,6 +847,7 @@ class PgSIG(PgDBI):
|
|
|
793
847
|
if logact&self.EXITLG: logact &= ~self.EXITLG
|
|
794
848
|
ccnt = i = 0
|
|
795
849
|
if dowait < 0: ccnt = 1 if (pid or pname) else self.PGSIG['MPROC']
|
|
850
|
+
self.drain_wake_pipe() # the check below covers any child done before now
|
|
796
851
|
while True:
|
|
797
852
|
pcnt = 0
|
|
798
853
|
if not pid and pname: pid = self.pname2cpid(pname)
|
|
@@ -845,6 +900,7 @@ class PgSIG(PgDBI):
|
|
|
845
900
|
self.check_vuser(uname, aname)
|
|
846
901
|
signal.signal(signal.SIGQUIT, self.signal_catch) # catch quit signal only
|
|
847
902
|
signal.signal(signal.SIGCHLD, self.clean_dead_child)
|
|
903
|
+
self.open_wake_pipe()
|
|
848
904
|
self.PGSIG['DSTR'] = dstr
|
|
849
905
|
self.PGSIG['DNAME'] = aname
|
|
850
906
|
self.PGSIG['PPID'] = 0
|
|
@@ -1293,14 +1349,26 @@ class PgSIG(PgDBI):
|
|
|
1293
1349
|
loop (int): Current loop iteration count, 0 for the first sleep of a wait.
|
|
1294
1350
|
msg (str): Message to log.
|
|
1295
1351
|
logact (int, optional): Log action flags. Defaults to ``LOGWRN``.
|
|
1296
|
-
dowait (int, optional): If non-zero,
|
|
1297
|
-
from ``adaptive_wait_time()``, at most ``PGSIG['WTIME']`` seconds
|
|
1298
|
-
|
|
1352
|
+
dowait (int, optional): If non-zero, wait for the adaptive wait time
|
|
1353
|
+
from ``adaptive_wait_time()``, at most ``PGSIG['WTIME']`` seconds,
|
|
1354
|
+
or until a child process in ``CPIDS`` is done, whichever is first
|
|
1355
|
+
(see ``open_wake_pipe()``). Defaults to 0.
|
|
1299
1356
|
"""
|
|
1300
1357
|
if logact is None: logact = self.LOGWRN
|
|
1301
1358
|
if loop > 0 and (loop%30) == 0:
|
|
1302
1359
|
self.pglog("{} at {}".format(msg, self.current_datetime()), logact)
|
|
1303
|
-
if dowait:
|
|
1360
|
+
if not dowait: return
|
|
1361
|
+
wtime = self.adaptive_wait_time(loop)
|
|
1362
|
+
if self.PGSIG['WPIPE'] and self.PGSIG['PPID'] < 2:
|
|
1363
|
+
# wake as soon as a child is done; the adaptive time is only the longest wait
|
|
1364
|
+
rfd = self.PGSIG['WPIPE'][0]
|
|
1365
|
+
try:
|
|
1366
|
+
select.select([rfd], [], [], wtime)
|
|
1367
|
+
except (OSError, ValueError):
|
|
1368
|
+
time.sleep(wtime)
|
|
1369
|
+
self.drain_wake_pipe()
|
|
1370
|
+
else:
|
|
1371
|
+
time.sleep(wtime)
|
|
1304
1372
|
|
|
1305
1373
|
# get the adaptive time to sleep for one loop of a wait for processes
|
|
1306
1374
|
def adaptive_wait_time(self, loop):
|
{rda_python_common-3.0.29 → rda_python_common-3.0.30/src/rda_python_common.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rda_python_common
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.30
|
|
4
4
|
Summary: RDA Python common library codes shared by other RDA python packages
|
|
5
5
|
Author-email: Zaihua Ji <zji@ucar.edu>
|
|
6
6
|
Project-URL: Homepage, https://github.com/NCAR/rda-python-common
|
|
@@ -189,7 +189,7 @@ PgLOG.pglog("hello", PgLOG.LOGWRN)
|
|
|
189
189
|
python -c "import rda_python_common; print(rda_python_common.__version__)"
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
-
You should see the installed version (currently `3.0.
|
|
192
|
+
You should see the installed version (currently `3.0.30`). If the import
|
|
193
193
|
fails, double-check that the active Python environment is the one where you
|
|
194
194
|
ran `pip install`.
|
|
195
195
|
|
|
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
|
{rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common.egg-info/requires.txt
RENAMED
|
File without changes
|
{rda_python_common-3.0.29 → rda_python_common-3.0.30}/src/rda_python_common.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|