rda-python-miscs 2.0.11__tar.gz → 2.0.12__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 (53) hide show
  1. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/PKG-INFO +1 -1
  2. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/pyproject.toml +1 -1
  3. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/pg_rst.py +110 -12
  4. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs.egg-info/PKG-INFO +1 -1
  5. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/LICENSE +0 -0
  6. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/MANIFEST.in +0 -0
  7. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/README.md +0 -0
  8. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/setup.cfg +0 -0
  9. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/__init__.py +0 -0
  10. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/bash_qsub.py +0 -0
  11. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/bashqsub.py +0 -0
  12. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/bashqsub.usg +0 -0
  13. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/gdex_ls.py +0 -0
  14. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/gdexls.py +0 -0
  15. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/gdexls.usg +0 -0
  16. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/gdexls_standalone.py +0 -0
  17. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/pg_docs.py +0 -0
  18. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/pg_wget.py +0 -0
  19. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/pgwget.py +0 -0
  20. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rda_cp.py +0 -0
  21. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rda_kill.py +0 -0
  22. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rda_mod.py +0 -0
  23. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rda_own.py +0 -0
  24. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rda_ps.py +0 -0
  25. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rda_sub.py +0 -0
  26. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rda_zip.py +0 -0
  27. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdacp.py +0 -0
  28. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdacp.usg +0 -0
  29. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdakill.py +0 -0
  30. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdakill.usg +0 -0
  31. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdals.py +0 -0
  32. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdals.usg +0 -0
  33. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdamod.py +0 -0
  34. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdamod.usg +0 -0
  35. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdaown.py +0 -0
  36. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdaown.usg +0 -0
  37. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdaps.py +0 -0
  38. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdaps.usg +0 -0
  39. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdasub.py +0 -0
  40. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdasub.usg +0 -0
  41. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdazip.py +0 -0
  42. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rdazip.usg +0 -0
  43. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rst_templates/index.rst.temp +0 -0
  44. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/rst_templates/section.rst.temp +0 -0
  45. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/tcsh_qsub.py +0 -0
  46. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/tcshqsub.py +0 -0
  47. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs/tcshqsub.usg +0 -0
  48. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs.egg-info/SOURCES.txt +0 -0
  49. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs.egg-info/dependency_links.txt +0 -0
  50. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs.egg-info/entry_points.txt +0 -0
  51. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs.egg-info/requires.txt +0 -0
  52. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/src/rda_python_miscs.egg-info/top_level.txt +0 -0
  53. {rda_python_miscs-2.0.11 → rda_python_miscs-2.0.12}/tests/test_miscs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rda_python_miscs
3
- Version: 2.0.11
3
+ Version: 2.0.12
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
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "rda_python_miscs"
9
- version = "2.0.11"
9
+ version = "2.0.12"
10
10
  authors = [
11
11
  { name="Zaihua Ji", email="zji@ucar.edu" },
12
12
  ]
@@ -18,6 +18,7 @@ import re
18
18
  import inspect
19
19
  import argparse
20
20
  import importlib
21
+ import importlib.util
21
22
  from os import path as op
22
23
  from rda_python_common.pg_file import PgFile
23
24
  from rda_python_common.pg_util import PgUtil
@@ -1164,6 +1165,62 @@ class PgRST(PgFile, PgUtil):
1164
1165
 
1165
1166
  return opts, alias, origin
1166
1167
 
1168
+ def load_opts_alias_from_pyfile(self, pyfile):
1169
+ """Load OPTS and ALIAS from a Python file given by path.
1170
+
1171
+ Uses ``importlib.util.spec_from_file_location`` to import the file
1172
+ without requiring it to be on ``sys.path``. Resolution order mirrors
1173
+ :meth:`load_opts_alias`: class attributes first, then module-level.
1174
+
1175
+ Args:
1176
+ pyfile (str): Absolute or relative path to the Python source file.
1177
+
1178
+ Returns:
1179
+ tuple[dict, dict]: ``(OPTS, ALIAS)`` where ALIAS defaults to ``{}``
1180
+ when not found.
1181
+
1182
+ Raises:
1183
+ SystemExit: via :func:`PgLOG.pglog` (``LGWNEX``) if the file
1184
+ cannot be loaded or ``OPTS`` cannot be found.
1185
+ """
1186
+ pyfile = op.abspath(pyfile)
1187
+ modname = op.splitext(op.basename(pyfile))[0]
1188
+ try:
1189
+ spec = importlib.util.spec_from_file_location(modname, pyfile)
1190
+ mod = importlib.util.module_from_spec(spec)
1191
+ spec.loader.exec_module(mod)
1192
+ except Exception as exc:
1193
+ self.pglog(
1194
+ "Cannot load module from '{}': {}".format(pyfile, exc),
1195
+ self.LGWNEX,
1196
+ )
1197
+
1198
+ cls = next(
1199
+ (obj for _, obj in inspect.getmembers(mod, inspect.isclass)
1200
+ if obj.__module__ == modname),
1201
+ None,
1202
+ )
1203
+
1204
+ if cls is not None:
1205
+ obj = cls()
1206
+ opts = getattr(obj, 'OPTS', None)
1207
+ alias = getattr(obj, 'ALIAS', None)
1208
+ else:
1209
+ opts = getattr(mod, 'OPTS', None)
1210
+ alias = getattr(mod, 'ALIAS', None)
1211
+
1212
+ if opts is None:
1213
+ self.pglog(
1214
+ "File '{}' does not define OPTS (checked class and "
1215
+ "module level)".format(pyfile),
1216
+ self.LGWNEX,
1217
+ )
1218
+
1219
+ if alias is None:
1220
+ alias = {}
1221
+
1222
+ return opts, alias
1223
+
1167
1224
 
1168
1225
  # ---------------------------------------------------------------------------
1169
1226
  # Command-line entry point
@@ -1174,40 +1231,81 @@ def main():
1174
1231
  parser = argparse.ArgumentParser(
1175
1232
  description=(
1176
1233
  "Convert a .usg help document to reStructuredText (.rst) using RST templates. "
1177
- "OPTS and ALIAS are loaded from rda_python_<docname>/<docname>.py: "
1178
- "the module is searched first for module-level OPTS/ALIAS variables, "
1179
- "then for a class defined in that module that carries both as class "
1180
- "attributes."
1234
+ "OPTS and ALIAS are loaded from rda_python_<docname>/<docname>.py "
1235
+ "(or from --pyfile if given): "
1236
+ "the module is searched first for a class that carries both as class "
1237
+ "attributes, then for module-level OPTS/ALIAS variables."
1181
1238
  ),
1182
1239
  formatter_class=argparse.RawDescriptionHelpFormatter,
1183
1240
  )
1184
1241
  parser.add_argument(
1185
1242
  'docname',
1243
+ nargs='?',
1244
+ default=None,
1186
1245
  help=(
1187
1246
  "Short document name, e.g. 'dsarch' or 'dsupdt'. "
1188
- "The module rda_python_<docname>/<docname>.py must be importable "
1189
- "and must define OPTS (and optionally ALIAS) either at module "
1190
- "level or as class attributes."
1247
+ "Required unless --usgfile is given, in which case the name is "
1248
+ "derived from the .usg filename by removing the extension."
1191
1249
  ),
1192
1250
  )
1193
1251
  parser.add_argument(
1194
- '--docdir',
1252
+ '-u', '--usgfile',
1253
+ default=None,
1254
+ metavar='FILE',
1255
+ help=(
1256
+ "Path to the .usg source document. When given, docname is derived "
1257
+ "from the filename by removing the .usg extension, and ORIGIN is set "
1258
+ "to the directory containing the file."
1259
+ ),
1260
+ )
1261
+ parser.add_argument(
1262
+ '-p', '--pyfile',
1263
+ default=None,
1264
+ metavar='FILE',
1265
+ help=(
1266
+ "Path to a Python file that defines OPTS (and optionally ALIAS) "
1267
+ "either at module level or as class attributes. When given, the "
1268
+ "module-import convention (rda_python_<docname>/<docname>.py) is "
1269
+ "bypassed."
1270
+ ),
1271
+ )
1272
+ parser.add_argument(
1273
+ '-d', '--docdir',
1195
1274
  default=None,
1196
1275
  metavar='DIR',
1197
1276
  help=(
1198
1277
  "Root directory under which the per-document RST output directory "
1199
1278
  "is created (default: current working directory). "
1200
- "The final output lands in <docdir>/<docname>/."
1279
+ "The final output lands in <docdir>/."
1201
1280
  ),
1202
1281
  )
1203
1282
  args = parser.parse_args()
1204
1283
 
1205
1284
  pg = PgRST()
1206
- opts, alias, origin = pg.load_opts_alias(args.docname)
1207
- pg.DOCS['ORIGIN'] = origin
1285
+
1286
+ # Resolve docname: explicit arg takes priority, then derive from --usgfile.
1287
+ if args.docname:
1288
+ docname = args.docname
1289
+ elif args.usgfile:
1290
+ docname = op.splitext(op.basename(args.usgfile))[0]
1291
+ else:
1292
+ parser.error("docname is required when --usgfile is not given")
1293
+
1294
+ # Set ORIGIN from --usgfile directory when provided.
1295
+ if args.usgfile:
1296
+ pg.DOCS['ORIGIN'] = op.dirname(op.abspath(args.usgfile)) or os.getcwd()
1297
+
1298
+ # Load OPTS/ALIAS: from --pyfile path or via module-import convention.
1299
+ if args.pyfile:
1300
+ opts, alias = pg.load_opts_alias_from_pyfile(args.pyfile)
1301
+ else:
1302
+ opts, alias, origin = pg.load_opts_alias(docname)
1303
+ if not args.usgfile:
1304
+ pg.DOCS['ORIGIN'] = origin
1305
+
1208
1306
  if args.docdir is not None:
1209
1307
  pg.DOCS['DOCDIR'] = args.docdir
1210
- pg.process_docs(args.docname, opts, alias)
1308
+ pg.process_docs(docname, opts, alias)
1211
1309
 
1212
1310
  if __name__ == "__main__":
1213
1311
  main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rda_python_miscs
3
- Version: 2.0.11
3
+ Version: 2.0.12
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