rda-python-miscs 1.0.1__tar.gz → 1.0.2__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 (38) hide show
  1. rda_python_miscs-1.0.2/MANIFEST.in +1 -0
  2. {rda_python_miscs-1.0.1/src/rda_python_miscs.egg-info → rda_python_miscs-1.0.2}/PKG-INFO +3 -2
  3. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/pyproject.toml +2 -1
  4. rda_python_miscs-1.0.2/src/rda_python_miscs/gdexls.py +279 -0
  5. rda_python_miscs-1.0.2/src/rda_python_miscs/gdexls.usg +60 -0
  6. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2/src/rda_python_miscs.egg-info}/PKG-INFO +3 -2
  7. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs.egg-info/SOURCES.txt +2 -0
  8. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs.egg-info/entry_points.txt +1 -0
  9. rda_python_miscs-1.0.1/MANIFEST.in +0 -10
  10. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/LICENSE +0 -0
  11. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/README.md +0 -0
  12. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/setup.cfg +0 -0
  13. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/__init__.py +0 -0
  14. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/bashqsub.py +0 -0
  15. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/bashqsub.usg +0 -0
  16. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/pgwget.py +0 -0
  17. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdacp.py +0 -0
  18. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdacp.usg +0 -0
  19. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdakill.py +0 -0
  20. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdakill.usg +0 -0
  21. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdals.py +0 -0
  22. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdals.usg +0 -0
  23. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdamod.py +0 -0
  24. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdamod.usg +0 -0
  25. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdaown.py +0 -0
  26. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdaown.usg +0 -0
  27. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdaps.py +0 -0
  28. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdaps.usg +0 -0
  29. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdasub.py +0 -0
  30. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdasub.usg +0 -0
  31. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdazip.py +0 -0
  32. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/rdazip.usg +0 -0
  33. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/tcshqsub.py +0 -0
  34. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs/tcshqsub.usg +0 -0
  35. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs.egg-info/dependency_links.txt +0 -0
  36. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs.egg-info/requires.txt +0 -0
  37. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/src/rda_python_miscs.egg-info/top_level.txt +0 -0
  38. {rda_python_miscs-1.0.1 → rda_python_miscs-1.0.2}/tests/test_miscs.py +0 -0
@@ -0,0 +1 @@
1
+ include src/rda_python_miscs/*.usg
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: rda_python_miscs
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: RDA Python package to hold RDA miscellaneous utility programs
5
5
  Author-email: Zaihua Ji <zji@ucar.edu>
6
6
  Project-URL: Homepage, https://github.com/NCAR/rda-python-miscs
@@ -13,5 +13,6 @@ Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: rda_python_common
15
15
  Requires-Dist: rda_python_setuid
16
+ Dynamic: license-file
16
17
 
17
18
  RDA python package to hold miscellaneous utility programs.
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "rda_python_miscs"
9
- version = "1.0.1"
9
+ version = "1.0.2"
10
10
  authors = [
11
11
  { name="Zaihua Ji", email="zji@ucar.edu" },
12
12
  ]
@@ -44,6 +44,7 @@ where = ["src"]
44
44
  "rdasub" = "rda_python_miscs.rdasub:main"
45
45
  "pgwget" = "rda_python_miscs.pgwget:main"
46
46
  "rdals" = "rda_python_miscs.rdals:main"
47
+ "gdexls" = "rda_python_miscs.gdexls:main"
47
48
  "rdaps" = "rda_python_miscs.rdaps:main"
48
49
  "rdaown" = "rda_python_miscs.rdaown:main"
49
50
  "rdacp.py" = "rda_python_miscs.rdacp:main"
@@ -0,0 +1,279 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ ##################################################################################
4
+ #
5
+ # Title: gdexls
6
+ # Author: Zaihua Ji, zji@ucar.edu
7
+ # Date: 10/20/2020
8
+ # 2025-03-10 transferred to package rda_python_miscs from
9
+ # https://github.com/NCAR/rda-utility-programs.git
10
+ # 2025-09-21 copied from rdals to gdexls
11
+ # Purpose: list files/directories in a local directory and show additional
12
+ # information recorded in RDADB if any
13
+ #
14
+ # Github: https://github.com/NCAR/rda-python-miscs.git
15
+ #
16
+ ##################################################################################
17
+ #
18
+ import re
19
+ import os
20
+ import sys
21
+ import glob
22
+ from os import path as op
23
+ from rda_python_common import PgLOG
24
+ from rda_python_common import PgDBI
25
+ from rda_python_common import PgUtil
26
+ from rda_python_common import PgSplit
27
+
28
+ # define some constants for gdexls actions
29
+ DIDX = 3 # description column index
30
+ CLMT = 500 # reformat list if count reach this limit
31
+ WIDTHS = [0, 0, 0] # WIDTHS for formated display
32
+ ALIGNS = [0, 1, 1] # alignment, 0 - left; 1 - right
33
+
34
+ RDALS = {
35
+ 'd' : 0, # 1 to list directory information only
36
+ 'f' : 0, # 1 to list file information only
37
+ 'N' : 0, # 1 to list files unformatted
38
+ 'r' : 0, # 1 if recursive all
39
+ 'R' : 0, # > 0 to set recursive limit
40
+ 'D' : None, # specify delimiting symbols, default to ' '
41
+ }
42
+
43
+ LINFO = {
44
+ 'files' : [],
45
+ 'curdir' : None,
46
+ 'tpath' : None,
47
+ 'dhome' : None,
48
+ 'dsid' : None,
49
+ 'dcnt' : 0,
50
+ 'gcnt' : 0,
51
+ 'fcnt' : 0,
52
+ 'pcnt' : 0,
53
+ 'pgrecs' : []
54
+ }
55
+
56
+ #
57
+ # main function to run the application
58
+ #
59
+ def main():
60
+
61
+ PgDBI.view_dbinfo()
62
+ PgLOG.set_help_path(__file__)
63
+ PgLOG.PGLOG['LOGFILE'] = "gdexls.log" # set different log file
64
+ LINFO['curdir'] = get_real_path(os.getcwd())
65
+ argv = sys.argv[1:]
66
+ PgLOG.pglog("gdexls {} ({})".format(' '.join(argv), LINFO['curdir']))
67
+ option = defopt = 'l'
68
+ for arg in argv:
69
+ if re.match(r'-(h|-*help|\?)$', arg): PgLOG.show_usage("gdexls")
70
+ ms = re.match(r'-(\w)$', arg)
71
+ if ms:
72
+ option = ms.group(1)
73
+ if option not in RDALS: PgLOG.pglog(arg + ": Unknown Option", PgLOG.LGEREX)
74
+ if 'dfNr'.find(option) > -1:
75
+ RDALS[option] = 1
76
+ option = defopt
77
+ continue
78
+ if not option: PgLOG.pglog(arg + ": Value provided without option", PgLOG.LGEREX)
79
+ if option == 'l':
80
+ LINFO['files'].append(get_real_path(arg))
81
+ defopt = None
82
+ else:
83
+ if option == 'R':
84
+ RDALS[option] = int(arg)
85
+ else:
86
+ RDALS[option] = arg
87
+ option = defopt
88
+
89
+ if not LINFO['files']:
90
+ LINFO['files'] = sorted(glob.glob('*')) # view all files in current directory
91
+ if not LINFO['files']:
92
+ sys.stderr.write(LINFO['curdir'] + ": Empty directory\n")
93
+ PgLOG.pgexit(1)
94
+
95
+ if not (RDALS['d'] or RDALS['f']):
96
+ RDALS['d'] = RDALS['f'] = 1 # list both directories and files as default
97
+ if not RDALS['D']: RDALS['D'] = '|' if RDALS['N'] else " " # default delimiter for no format display
98
+ if not RDALS['R'] and RDALS['r']: RDALS['R'] = 1000
99
+
100
+ display_top_list(LINFO['files']) # display or cache file/directory list
101
+ if LINFO['pcnt'] > 0: display_format_list() # if some left over
102
+
103
+ if (LINFO['dcnt'] + LINFO['gcnt'] + LINFO['fcnt']) > 1:
104
+ msg = ''
105
+ if LINFO['dcnt'] > 0:
106
+ s = 's' if LINFO['dcnt'] > 1 else ''
107
+ msg += "{} Dataset{}".format(LINFO['dcnt'], s)
108
+ if LINFO['gcnt'] > 0:
109
+ s = 's' if LINFO['gcnt'] > 1 else ''
110
+ if msg: msg += " & "
111
+ msg += "{} Group{}".format(LINFO['gcnt'], s)
112
+ if LINFO['fcnt'] > 0:
113
+ s = 's' if LINFO['fcnt'] > 1 else ''
114
+ if msg: msg += " & "
115
+ msg += "{} File{}".format(LINFO['fcnt'], s)
116
+ print("Total {} displayed".format(msg))
117
+ elif (LINFO['dcnt'] + LINFO['gcnt'] + LINFO['fcnt']) == 0:
118
+ sys.stderr.write((LINFO['tpath'] if LINFO['tpath'] else LINFO['curdir']) + ": No RDA data information found\n")
119
+ PgLOG.pgexit(1)
120
+
121
+ PgLOG.pgexit(0)
122
+
123
+ #
124
+ # display the top level list
125
+ #
126
+ def display_top_list(files):
127
+
128
+ for file in files:
129
+
130
+ if not op.exists(file):
131
+ sys.stderr.write(file + ": NOT exists\n")
132
+ continue
133
+
134
+ isdir = 1 if op.isdir(file) else 0
135
+ display = 1
136
+ if isdir and re.search(r'/$', file):
137
+ display = 0 # do not display the directory info if it is ended by '/'
138
+ file = re.sub(r'/$', '', file)
139
+
140
+ if not re.match(r'^/', file): file = PgLOG.join_paths(LINFO['curdir'], file)
141
+ LINFO['tpath'] = (op.dirname(file) if display else file) + "/"
142
+ if display: display_line(file, isdir)
143
+ if isdir and (RDALS['R'] or not display or not LINFO['dsid']):
144
+ fs = sorted(glob.glob(file + "/*"))
145
+ display_list(fs, 1)
146
+ if LINFO['pcnt'] > CLMT: display_format_list()
147
+
148
+ #
149
+ # recursively display directory/file info
150
+ #
151
+ def display_list(files, level):
152
+
153
+ for file in files:
154
+ isdir = 1 if op.isdir(file) else 0
155
+ display_line(file, isdir)
156
+ if isdir and level < RDALS['R']:
157
+ fs = sorted(glob.glob(file + "/*"))
158
+ display_list(fs, level+1)
159
+ if LINFO['pcnt'] > CLMT: display_format_list()
160
+
161
+ #
162
+ # find dataset/group info; display or cache file
163
+ #
164
+ def display_line(file, isdir):
165
+
166
+ getwfile = 1
167
+ if LINFO['dsid'] and LINFO['dhome']:
168
+ ms = re.match(r'^{}/(.*)$'.format(LINFO['dhome']), file)
169
+ if ms:
170
+ wfile = ms.group(1)
171
+ getwfile = 0
172
+ if getwfile:
173
+ LINFO['dsid'] = PgUtil.find_dataset_id(file, logact = PgLOG.LOGWRN)
174
+ if LINFO['dsid'] == None: return # skip for missing dsid
175
+
176
+ pgrec = PgDBI.pgget("dataset", "title, (dwebcnt + nwebcnt) nc, (dweb_size + nweb_size) ns", "dsid = '{}'".format(LINFO['dsid']), PgLOG.LGEREX)
177
+ if not pgrec: return None
178
+
179
+ LINFO['dhome'] = "{}/{}".format(PgLOG.PGLOG['DSDHOME'], LINFO['dsid'])
180
+ if LINFO['dhome'] == file:
181
+ file = re.sub(r'^{}'.format(LINFO['tpath']), '', file, 1)
182
+ if RDALS['d']:
183
+ title = pgrec['title'] if pgrec['title'] else ''
184
+ display_record(["D" + file, pgrec['ns'], str(pgrec['nc']), title])
185
+ LINFO['dcnt'] += 1
186
+ return
187
+
188
+ ms = re.match(r'^{}/(.*)$'.format(LINFO['dhome']), file)
189
+ if ms:
190
+ wfile = ms.group(1)
191
+ else:
192
+ return
193
+
194
+ if isdir:
195
+ if RDALS['d']: # check and display group info for directory
196
+ pgrec = PgDBI.pgget("dsgroup", "title, (dwebcnt + nwebcnt) nc, (dweb_size + nweb_size) ns",
197
+ "dsid = '{}' AND webpath = '{}'".format(LINFO['dsid'], wfile), PgLOG.LGEREX)
198
+ if pgrec:
199
+ file = re.sub(r'^{}'.format(LINFO['tpath']), '', file, 1)
200
+ title = pgrec['title'] if pgrec['title'] else ''
201
+ display_record(["G" + file, pgrec['ns'], str(pgrec['nc']), title])
202
+ LINFO['gcnt'] += 1
203
+
204
+ elif RDALS['f']: # check and display file info
205
+ pgrec = PgSplit.pgget_wfile(LINFO['dsid'], "data_size, data_format, note",
206
+ "wfile = '{}'".format(wfile), PgLOG.LGEREX)
207
+ if pgrec:
208
+ if pgrec['note']:
209
+ note = re.sub(r'\n', ' ', pgrec['note']) # remove '\n' in note
210
+ else:
211
+ note = ''
212
+ file = re.sub(r'^{}'.format(LINFO['tpath']), '', file, 1)
213
+ display_record(["F" + file, pgrec['data_size'], pgrec['data_format'], note])
214
+ LINFO['fcnt'] += 1
215
+
216
+ #
217
+ # display one file info
218
+ #
219
+ def display_record(disp):
220
+
221
+ disp[1] = get_float_string(disp[1])
222
+ if RDALS['N']:
223
+ print(RDALS['D'].join(disp))
224
+ else:
225
+ LINFO['pgrecs'].append(disp)
226
+ LINFO['pcnt'] += 1
227
+ for i in range(DIDX):
228
+ dlen = len(disp[i])
229
+ if dlen > WIDTHS[i]: WIDTHS[i] = dlen
230
+
231
+ #
232
+ # display cached list with format
233
+ #
234
+ def display_format_list():
235
+
236
+ for j in range(LINFO['pcnt']):
237
+ disp = LINFO['pgrecs'][j]
238
+ for i in range(DIDX):
239
+ if ALIGNS[i] == 1:
240
+ disp[i] = "{:>{}}".format(disp[i], WIDTHS[i])
241
+ else:
242
+ disp[i] = "{:{}}".format(disp[i], WIDTHS[i])
243
+ print(RDALS['D'].join(disp))
244
+
245
+ LINFO['pcnt'] = 0
246
+
247
+ #
248
+ # change size to floating point value with unit
249
+ #
250
+ def get_float_string(val):
251
+
252
+ units = ['B', 'K', 'M', 'G', 'T', 'P']
253
+
254
+ idx = 0
255
+ while val > 1000 and idx < 5:
256
+ val /= 1000
257
+ idx += 1
258
+
259
+ if idx > 0:
260
+ return "{:.2f}{}".format(val, units[idx])
261
+ else:
262
+ return "{}{}".format(val, units[idx])
263
+
264
+ #
265
+ # replace /gpfs to the path /glade
266
+ #
267
+ def get_real_path(path):
268
+
269
+ if re.match(r'^/gpfs/u', path):
270
+ path = re.sub(r'^/gpfs', '/glade', path, 1)
271
+ elif re.match(r'^/gpfs/csfs1/', path):
272
+ path = re.sub(r'^/gpfs/csfs1', '/glade/campaign', path, 1)
273
+
274
+ return path
275
+
276
+ #
277
+ # call main() to start program
278
+ #
279
+ if __name__ == "__main__": main()
@@ -0,0 +1,60 @@
1
+
2
+ List directory and file information of the current or specified directories
3
+ with metadata information if matched. Four columns are listed, they are Directory
4
+ Name, Data Volume, File Count, and Brief Description if the listed item is a
5
+ directory, and they are File Name, Data Size, Data Format, and Brief Description
6
+ if the listed item is a file.
7
+
8
+ A leading letter is displayed on each line to indicate what type item is listed;
9
+ including 'D' for a whole dataset, 'G' for a group or subgroup in a dataset,
10
+ and 'F' for a data file.
11
+
12
+ The output of directory/file list is formatted as default with double spaces
13
+ as delimiter and each column lined up vertically at least for the files under each
14
+ directory. Provide Option -N to display list without format. A delimiter symbol '|'
15
+ is defaulted if Option -N is present.
16
+
17
+ Usage: gdexls [-d] [-f] [-N] [-h] [-r] [-D DelimitSymbols] [-R RecursiveLevel] [Directory/File List]
18
+
19
+ - Option -d, list directory information only. Directory information
20
+ is included as default. Add this option to exclude file information;
21
+
22
+ - Option -f, list file information only. File information
23
+ is included as default. Add this option to exclude directory information;
24
+
25
+ - Option -N, list files unformatted;
26
+
27
+ - Option -h, display this help document;
28
+
29
+ - Option -r, list directories and files recursively;
30
+
31
+ - Option -R, list directories and files recursively up to the level
32
+ provided with this Option;
33
+
34
+ - Option -D, specify delimiting symbols for dividing the columns.
35
+ It defaults to " " for formatted output and '|' for unformatted output.
36
+ Make sure quote the symbols if any character in the symbols has Unix
37
+ meaning, for example -D '<:>';
38
+
39
+ - Directory/file List is optional; without specification, all directories
40
+ and files in the current directory are listed. Unix command line
41
+ wildcards are supported.
42
+
43
+ This utility program can be executed anywhere. Nothing is displayed if neither
44
+ directory nor file information pre-gathered in database.
45
+
46
+ For examples, to check directories and files of ds277.6, you can
47
+
48
+ 1. Change into the dataset home data directory as 'cd /PathTo/ds277.6' and
49
+ execute 'gdexls'; add recursive option '-r' to check directories and files
50
+ further into the sub-directories, or change directory into a sub-directory
51
+ to check files inside of it.
52
+
53
+ 2. Pass an absolute path to gdexls as 'gdexls /PathTo/ds277.6/' or as
54
+ 'gdexls /PathTo/ds277.6/*'; without the ending by '/' or an appended
55
+ wildcard symbol '*' information of the dataset itself is check unless
56
+ the recursive option '-r' or '-R RecursiveLevel' is present
57
+
58
+ 3. If the current directory is in another dataset home data directory,
59
+ such as /PathTo/ds277.7, you can pass a relative path to gdexls
60
+ as 'gdexls ../ds277.6/' or as 'gdexls ../ds277.6/*'
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: rda_python_miscs
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: RDA Python package to hold RDA miscellaneous utility programs
5
5
  Author-email: Zaihua Ji <zji@ucar.edu>
6
6
  Project-URL: Homepage, https://github.com/NCAR/rda-python-miscs
@@ -13,5 +13,6 @@ Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: rda_python_common
15
15
  Requires-Dist: rda_python_setuid
16
+ Dynamic: license-file
16
17
 
17
18
  RDA python package to hold miscellaneous utility programs.
@@ -5,6 +5,8 @@ pyproject.toml
5
5
  src/rda_python_miscs/__init__.py
6
6
  src/rda_python_miscs/bashqsub.py
7
7
  src/rda_python_miscs/bashqsub.usg
8
+ src/rda_python_miscs/gdexls.py
9
+ src/rda_python_miscs/gdexls.usg
8
10
  src/rda_python_miscs/pgwget.py
9
11
  src/rda_python_miscs/rdacp.py
10
12
  src/rda_python_miscs/rdacp.usg
@@ -1,5 +1,6 @@
1
1
  [console_scripts]
2
2
  bashqsub = rda_python_miscs.bashqsub:main
3
+ gdexls = rda_python_miscs.gdexls:main
3
4
  pgwget = rda_python_miscs.pgwget:main
4
5
  rdacp.py = rda_python_miscs.rdacp:main
5
6
  rdakill.py = rda_python_miscs.rdakill:main
@@ -1,10 +0,0 @@
1
- include src/rda_python_miscs/bashqsub.usg
2
- include src/rda_python_miscs/tcshqsub.usg
3
- include src/rda_python_miscs/rdasub.usg
4
- include src/rda_python_miscs/rdacp.usg
5
- include src/rda_python_miscs/rdakill.usg
6
- include src/rda_python_miscs/rdals.usg
7
- include src/rda_python_miscs/rdamod.usg
8
- include src/rda_python_miscs/rdaown.usg
9
- include src/rda_python_miscs/rdaps.usg
10
- include src/rda_python_miscs/rdazip.usg