rda-python-common 3.0.21__tar.gz → 3.0.23__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 (34) hide show
  1. {rda_python_common-3.0.21/src/rda_python_common.egg-info → rda_python_common-3.0.23}/PKG-INFO +2 -2
  2. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/README.md +1 -1
  3. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/pyproject.toml +1 -1
  4. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/__init__.py +1 -1
  5. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_file.py +4 -1
  6. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_sig.py +46 -0
  7. {rda_python_common-3.0.21 → rda_python_common-3.0.23/src/rda_python_common.egg-info}/PKG-INFO +2 -2
  8. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/LICENSE +0 -0
  9. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/setup.cfg +0 -0
  10. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/PgCMD.py +0 -0
  11. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/PgDBI.py +0 -0
  12. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/PgFile.py +0 -0
  13. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/PgLOG.py +0 -0
  14. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/PgLock.py +0 -0
  15. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/PgOPT.py +0 -0
  16. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/PgSIG.py +0 -0
  17. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/PgSplit.py +0 -0
  18. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/PgUtil.py +0 -0
  19. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_cmd.py +0 -0
  20. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_dbi.py +0 -0
  21. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_lock.py +0 -0
  22. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_log.py +0 -0
  23. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_opt.py +0 -0
  24. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_password.py +0 -0
  25. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_split.py +0 -0
  26. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pg_util.py +0 -0
  27. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pgpassword.py +0 -0
  28. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common/pgpassword.usg +0 -0
  29. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common.egg-info/SOURCES.txt +0 -0
  30. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common.egg-info/dependency_links.txt +0 -0
  31. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common.egg-info/entry_points.txt +0 -0
  32. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common.egg-info/requires.txt +0 -0
  33. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/src/rda_python_common.egg-info/top_level.txt +0 -0
  34. {rda_python_common-3.0.21 → rda_python_common-3.0.23}/test/test_common.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rda_python_common
3
- Version: 3.0.21
3
+ Version: 3.0.23
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.21`). If the import
192
+ You should see the installed version (currently `3.0.23`). 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.21`). If the import
168
+ You should see the installed version (currently `3.0.23`). 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
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rda_python_common"
7
- version = "3.0.21"
7
+ version = "3.0.23"
8
8
  authors = [
9
9
  { name="Zaihua Ji", email="zji@ucar.edu" },
10
10
  ]
@@ -22,7 +22,7 @@ object that existing callers expect.
22
22
 
23
23
  from . import PgLOG, PgUtil, PgDBI, PgFile, PgLock, PgCMD, PgSIG, PgOPT, PgSplit
24
24
 
25
- __version__ = "3.0.21"
25
+ __version__ = "3.0.23"
26
26
 
27
27
  __all__ = [
28
28
  "PgLOG",
@@ -3982,7 +3982,10 @@ class PgFile(PgUtil, PgSIG):
3982
3982
  if ms:
3983
3983
  fsize = int(ms.group(1))
3984
3984
  cksum = ms.group(2)
3985
- if cksum and cksum == frec['checksum'] or not cksum and fsize == frec['data_size']:
3985
+ # a size difference means the file changed since the backup, no matter what
3986
+ # the checksum says; a stale checksum left behind by an earlier re-archive
3987
+ # used to match and hide the change, leaving the backup stale forever
3988
+ if fsize == frec['data_size'] and cksum == frec['checksum']:
3986
3989
  ret = 1
3987
3990
  if logact:
3988
3991
  if ret == 1:
@@ -63,6 +63,7 @@ class PgSIG(PgDBI):
63
63
  'MTIME': 0, # maximum daemon running time in seconds, 0 for unlimited
64
64
  'STIME': 0, # time the daemon is started
65
65
  'STRTM': '', # string format of 'STIME'
66
+ 'TERMCB': None, # callback to report before a caught termination signal kills the run
66
67
  }
67
68
 
68
69
  # add users for starting this daemon
@@ -480,6 +481,45 @@ class PgSIG(PgDBI):
480
481
  if self.PGSIG['PPID'] <= 1 and len(self.CPIDS) > 0: # passing signal to child processes
481
482
  for pid in self.CPIDS: self.kill_process(pid, signum)
482
483
 
484
+ # catch the termination signal so a batch run gets a chance to report before it dies
485
+ # PBS kills a job that runs out of walltime with SIGTERM first and SIGKILL a few seconds
486
+ # later (the MoM's kill_delay, 10 seconds by default), and the same pair is what qdel
487
+ # sends. SIGTERM is the only warning there is, so trapping it turns the last seconds
488
+ # into a report instead of losing the run silently. only a batch run arms this: on the
489
+ # command line SIGTERM must keep killing the process the way the user expects.
490
+ # callback - function called as callback(signum, frame) to build and send the report
491
+ def catch_term_signal(self, callback):
492
+ """Trap SIGTERM in a batch run so a report can be sent before the job is killed.
493
+
494
+ Does nothing outside a batch run (``PGLOG['CURBID']`` < 1).
495
+
496
+ Args:
497
+ callback: Function called as ``callback(signum, frame)`` from the
498
+ signal handler to build and send the report.
499
+ """
500
+ if self.PGLOG['CURBID'] < 1: return # only a batch run gets killed off a walltime
501
+ self.PGSIG['TERMCB'] = callback
502
+ signal.signal(signal.SIGTERM, self.term_signal_catch)
503
+
504
+ # run the registered callback and then die of the signal that was sent
505
+ def term_signal_catch(self, signum, frame):
506
+ """Report through the registered callback, then re-raise the signal.
507
+
508
+ The default handler is restored before the callback runs so that a
509
+ second signal, or the SIGKILL that follows, ends the run outright
510
+ instead of re-entering here should the callback hang. Re-raising the
511
+ signal keeps the exit status the one the sender asked for.
512
+
513
+ Args:
514
+ signum (int): The signal number received.
515
+ frame: The current stack frame, passed on to the callback.
516
+ """
517
+ signal.signal(signum, signal.SIG_DFL)
518
+ callback = self.PGSIG['TERMCB']
519
+ self.PGSIG['TERMCB'] = None # report only once
520
+ if callback: callback(signum, frame)
521
+ os.kill(os.getpid(), signum)
522
+
483
523
  # wrapper function to call os.kill() logging caught error based on logact
484
524
  # return self.SUCCESS is success; PgLog.FAILURE if not
485
525
  def kill_process(self, pid, signum, logact=0):
@@ -602,6 +642,9 @@ class PgSIG(PgDBI):
602
642
  pid = self.process_fork(msg)
603
643
  if pid == 0: # in child
604
644
  signal.signal(signal.SIGQUIT, self.signal_catch) # catch quit signal only
645
+ if self.PGSIG['TERMCB']: # a child shares the parent's check; it must not report
646
+ signal.signal(signal.SIGTERM, signal.SIG_DFL)
647
+ self.PGSIG['TERMCB'] = None
605
648
  self.PGSIG['PPID'] = self.PGSIG['PID']
606
649
  self.PGSIG['PID'] = pid = os.getpid()
607
650
  self.cmdlog("Timeout child to " + msg, time.time(), 0)
@@ -693,6 +736,9 @@ class PgSIG(PgDBI):
693
736
  self.pglog("{}: starts CPID {} for {}".format(self.PGSIG['DSTR'], pid, pname))
694
737
  else:
695
738
  signal.signal(signal.SIGQUIT, signal.SIG_DFL) # turn off catch QUIT signal in child
739
+ if self.PGSIG['TERMCB']: # a child shares the parent's check; it must not report
740
+ signal.signal(signal.SIGTERM, signal.SIG_DFL)
741
+ self.PGSIG['TERMCB'] = None
696
742
  self.PGLOG['LOGMASK'] &= ~self.WARNLG # turn off warn in child
697
743
  self.PGSIG['PPID'] = self.PGSIG['PID']
698
744
  self.PGSIG['PID'] = pid = os.getpid()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rda_python_common
3
- Version: 3.0.21
3
+ Version: 3.0.23
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.21`). If the import
192
+ You should see the installed version (currently `3.0.23`). 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