rda-python-common 3.0.23__tar.gz → 3.0.25__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.23/src/rda_python_common.egg-info → rda_python_common-3.0.25}/PKG-INFO +2 -2
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/README.md +1 -1
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/pyproject.toml +1 -1
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/__init__.py +1 -1
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_file.py +94 -5
- {rda_python_common-3.0.23 → rda_python_common-3.0.25/src/rda_python_common.egg-info}/PKG-INFO +2 -2
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/LICENSE +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/setup.cfg +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/PgCMD.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/PgDBI.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/PgFile.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/PgLOG.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/PgLock.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/PgOPT.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/PgSIG.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/PgSplit.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/PgUtil.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_cmd.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_dbi.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_lock.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_log.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_opt.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_password.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_sig.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_split.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pg_util.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pgpassword.py +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common/pgpassword.usg +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common.egg-info/SOURCES.txt +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common.egg-info/dependency_links.txt +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common.egg-info/entry_points.txt +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common.egg-info/requires.txt +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common.egg-info/top_level.txt +0 -0
- {rda_python_common-3.0.23 → rda_python_common-3.0.25}/test/test_common.py +0 -0
{rda_python_common-3.0.23/src/rda_python_common.egg-info → rda_python_common-3.0.25}/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.25
|
|
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.25`). 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.25`). 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
|
|
|
@@ -875,8 +875,14 @@ class PgFile(PgUtil, PgSIG):
|
|
|
875
875
|
"""Download every object under a key prefix into a local directory.
|
|
876
876
|
|
|
877
877
|
The object store has no directories; a zarr store and the like is a set of
|
|
878
|
-
objects sharing a key prefix.
|
|
879
|
-
|
|
878
|
+
objects sharing a key prefix. The whole prefix comes down in one recursive
|
|
879
|
+
call, which is what makes this usable at all: such a store routinely holds
|
|
880
|
+
thousands of tiny members, and one process per member costs hours where
|
|
881
|
+
the recursive call costs seconds.
|
|
882
|
+
|
|
883
|
+
Nothing is fetched when every member is already staged under todir at the
|
|
884
|
+
object's size and no older than the object itself, so the second copy into
|
|
885
|
+
the same directory (dsarch makes one when it tars) is free.
|
|
880
886
|
|
|
881
887
|
Args:
|
|
882
888
|
todir (str): Destination local directory path.
|
|
@@ -890,17 +896,100 @@ class PgFile(PgUtil, PgSIG):
|
|
|
890
896
|
if not bucket: bucket = self.PGLOG['OBJCTBKT']
|
|
891
897
|
ms = re.match(r'^(.+)/$', fromdir)
|
|
892
898
|
if ms: fromdir = ms.group(1)
|
|
893
|
-
|
|
899
|
+
# opt 1 adds the LastModified the 'lo' listing already carries; it is only
|
|
900
|
+
# bits 2 and 8 that would cost a metadata call per key
|
|
901
|
+
flist = self.object_glob(fromdir, bucket, 1, logact)
|
|
894
902
|
if flist == self.FAILURE: return self.FAILURE
|
|
895
903
|
prefix = fromdir + '/'
|
|
896
904
|
keys = [key for key in flist if key.startswith(prefix)]
|
|
897
905
|
if not keys:
|
|
898
906
|
return self.lmsg(fromdir, "{}-{} to copy to {}".format(self.OHOST, self.PGLOG['MISSFILE'], todir), logact)
|
|
907
|
+
# a partly staged directory is downloaded again in full rather than member by
|
|
908
|
+
# member: one member costs about as much as the whole recursive call, so
|
|
909
|
+
# fetching even a handful individually is the slower way round
|
|
910
|
+
if not self.object_local_missing(todir, prefix, keys, flist, 1, logact):
|
|
911
|
+
# every member is current, but the key list is the authoritative one: a local
|
|
912
|
+
# file no longer under the prefix means the store was rewritten in place, and
|
|
913
|
+
# archiving it would keep members the store has dropped. start over instead
|
|
914
|
+
extra = self.local_extra_files(todir, prefix, keys)
|
|
915
|
+
if not extra: return self.SUCCESS
|
|
916
|
+
self.pglog("{}: restage over {} file(s) no longer in {}-{}".format(
|
|
917
|
+
todir, len(extra), self.OHOST, fromdir), logact|self.LOGWRN)
|
|
918
|
+
if not self.delete_local_file(todir, logact): return self.FAILURE
|
|
919
|
+
self.make_local_directory(todir, logact)
|
|
920
|
+
cmd = "{} go -k {} -b {} -ld {} -r".format(self.OBJCTCMD, fromdir, bucket, todir)
|
|
921
|
+
buf = self.pgsystem(cmd, logact, self.CMDBTH)
|
|
922
|
+
# verify on size alone; a member just downloaded is newer than the object by
|
|
923
|
+
# definition, and comparing timestamps here would only expose a clock skew
|
|
924
|
+
miss = self.object_local_missing(todir, prefix, keys, flist, 0, logact)
|
|
925
|
+
if miss:
|
|
926
|
+
return self.errlog("{}-{}: Error download {} of {} member(s) to {}\n{}".format(
|
|
927
|
+
self.OHOST, fromdir, len(miss), len(keys), todir, buf), 'O', 1, logact)
|
|
928
|
+
return self.SUCCESS
|
|
929
|
+
|
|
930
|
+
# List the members of an object key prefix that are not staged under todir yet
|
|
931
|
+
# todir - target local directory name
|
|
932
|
+
# prefix - source object key prefix, including the trailing '/'
|
|
933
|
+
# keys - the member keys to check
|
|
934
|
+
# flist - object_glob() info, keyed by member key
|
|
935
|
+
# chktime - also require the local copy to be no older than the object
|
|
936
|
+
def object_local_missing(self, todir, prefix, keys, flist, chktime = 0, logact = 0):
|
|
937
|
+
"""Return the member keys that still need downloading under a key prefix.
|
|
938
|
+
|
|
939
|
+
A local copy counts as present when it matches the object size, and with
|
|
940
|
+
chktime also when it is no older than the object's LastModified.
|
|
941
|
+
|
|
942
|
+
Args:
|
|
943
|
+
todir (str): Destination local directory path.
|
|
944
|
+
prefix (str): Object key prefix including the trailing '/'.
|
|
945
|
+
keys (list): Member keys to check.
|
|
946
|
+
flist (dict): Mapping of key → object info from object_glob().
|
|
947
|
+
chktime (int): Also compare modification times; default 0.
|
|
948
|
+
logact (int): Logging action flags; default 0.
|
|
949
|
+
|
|
950
|
+
Returns:
|
|
951
|
+
list: The member keys not staged under todir.
|
|
952
|
+
"""
|
|
953
|
+
miss = []
|
|
899
954
|
plen = len(prefix)
|
|
900
955
|
for key in keys:
|
|
956
|
+
oinfo = flist[key]
|
|
901
957
|
tofile = "{}/{}".format(todir, key[plen:])
|
|
902
|
-
|
|
903
|
-
|
|
958
|
+
linfo = self.check_local_file(tofile, 1, logact)
|
|
959
|
+
if linfo and linfo['data_size'] == oinfo['data_size']:
|
|
960
|
+
if not chktime: continue
|
|
961
|
+
# an unparsable LastModified leaves date_modified unset; fetch again then
|
|
962
|
+
if 'date_modified' in oinfo and \
|
|
963
|
+
self.cmptime(linfo['date_modified'], linfo['time_modified'],
|
|
964
|
+
oinfo['date_modified'], oinfo['time_modified']) >= 0: continue
|
|
965
|
+
miss.append(key)
|
|
966
|
+
return miss
|
|
967
|
+
|
|
968
|
+
# List the files staged under todir that the object key prefix no longer holds
|
|
969
|
+
# todir - target local directory name
|
|
970
|
+
# prefix - source object key prefix, including the trailing '/'
|
|
971
|
+
# keys - the member keys the object store currently holds
|
|
972
|
+
def local_extra_files(self, todir, prefix, keys):
|
|
973
|
+
"""Return the paths under todir that are not members of an object key prefix.
|
|
974
|
+
|
|
975
|
+
Paths are relative to todir, matching the layout a recursive download creates.
|
|
976
|
+
|
|
977
|
+
Args:
|
|
978
|
+
todir (str): Local directory holding the staged copy.
|
|
979
|
+
prefix (str): Object key prefix including the trailing '/'.
|
|
980
|
+
keys (list): The member keys currently under the prefix.
|
|
981
|
+
|
|
982
|
+
Returns:
|
|
983
|
+
list: Relative paths under todir with no matching member key.
|
|
984
|
+
"""
|
|
985
|
+
plen = len(prefix)
|
|
986
|
+
members = set(key[plen:] for key in keys)
|
|
987
|
+
extra = []
|
|
988
|
+
for path, dirs, files in os.walk(todir):
|
|
989
|
+
for fname in files:
|
|
990
|
+
name = op.relpath(op.join(path, fname), todir)
|
|
991
|
+
if name not in members: extra.append(name)
|
|
992
|
+
return extra
|
|
904
993
|
|
|
905
994
|
# Copy a remote file to object
|
|
906
995
|
# tofile - target object file name
|
{rda_python_common-3.0.23 → rda_python_common-3.0.25/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.25
|
|
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.25`). 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.23 → rda_python_common-3.0.25}/src/rda_python_common.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common.egg-info/requires.txt
RENAMED
|
File without changes
|
{rda_python_common-3.0.23 → rda_python_common-3.0.25}/src/rda_python_common.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|