opex-manifest-generator 1.3.4__py3-none-any.whl → 1.3.6__py3-none-any.whl

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.
@@ -8,9 +8,9 @@ license: Apache License 2.0"
8
8
  from .opex_manifest import OpexManifestGenerator,OpexDir,OpexFile
9
9
  from .hash import HashGenerator
10
10
  from .common import *
11
- from .cli import parse_args,run_cli
12
- import importlib.metadata
11
+ from .cli import create_parser,run_cli
12
+ from importlib import metadata
13
13
 
14
14
  __author__ = "Christopher Prince (c.pj.prince@gmail.com)"
15
15
  __license__ = "Apache License Version 2.0"
16
- __version__ = importlib.metadata.version("opex_manifest_generator")
16
+ __version__ = metadata.version("opex_manifest_generator")
@@ -7,75 +7,77 @@ license: Apache License 2.0"
7
7
 
8
8
  import argparse, os, inspect, time, logging
9
9
  from opex_manifest_generator.opex_manifest import OpexManifestGenerator
10
- import importlib.metadata
10
+ from importlib import metadata
11
11
  from datetime import datetime
12
- from opex_manifest_generator.common import running_time
12
+ from opex_manifest_generator.common import running_time
13
13
 
14
14
  logger = logging.getLogger(__name__)
15
15
 
16
- def parse_args():
17
- parser = argparse.ArgumentParser(description = "OPEX Manifest Generator for Preservica Uploads")
16
+ def _get_version():
17
+ try:
18
+ return metadata.version("opex_manifest_generator")
19
+ except metadata.PackageNotFoundError:
20
+ return "0.0.0"
21
+
22
+ def create_parser():
23
+
24
+ parser = argparse.ArgumentParser(prog="Opex_Manifest_Generator", description = "OPEX Manifest Generator for Preservica Uploads")
25
+
26
+ parser.add_argument("-v", "--version", action = 'version', version = '%(prog)s {version}'.format(version =_get_version())),
18
27
  parser.add_argument('root', nargs='?', default = os.getcwd(),
19
28
  help = """The root path to generate Opexes for, will recursively traverse all sub-directories.
20
29
  Generates an Opex for each folder & (depending on options) file in the directory tree.""")
21
- parser.add_argument("-fx", "--fixity", required = False, nargs = '*', default = None,
30
+
31
+
32
+ opexgroup = parser.add_argument_group('Opex Options', 'Options that control the generation of Opex Manifests')
33
+
34
+ opexgroup.add_argument("-fx", "--fixity", required = False, nargs = '*', default = None,
22
35
  choices = ['SHA-1', 'MD5', 'SHA-256', 'SHA-512'], type = fixity_helper, action=EmptyIsTrueFixity,
23
- help="Generates a hash for each file and adds it to the opex, can select one or more algorithms to utilise. -fx SHA-1 MD5")
24
- parser.add_argument("--pax-fixity", required = False, action = 'store_true', default = False,
36
+ help="Generates a hash for each file and adds it to the opex.\n" \
37
+ "Can select one or more algorithms to utilise: {-fx MD5 SHA-1}\n" \
38
+ "If no algorithm is specified defaults to SHA-1.\n")
39
+ opexgroup.add_argument("--pax-fixity", required = False, action = 'store_true', default = False,
25
40
  help="""Enables use of PAX fixity generation, in line with Preservica's Recommendation.
26
41
  "Files / folders ending in .pax or .pax.zip will have individual files in folder / zip added to Opex.""")
27
- parser.add_argument("--fixity-export", required = False, action = 'store_false', default = True,
28
- help="""Set whether to export the generated fixity list to a text file in the meta directory.
29
- Enabled by default, disable with this flag.""")
30
- parser.add_argument("--prevent-all-exports", required = False, action = 'store_true', default = False,
31
- help="Set to prevent all exports (Fixity, Removal, Empty) from being created in the meta directory.")
32
- parser.add_argument("-z", "--zip", required = False, action = 'store_true',
42
+ opexgroup.add_argument("-z", "--zip", required = False, action = 'store_true',
33
43
  help="Set to zip files")
34
- parser.add_argument("--zip-remove-files", required = False, action = 'store_true',
35
- help="Set to remove the files that have been zipped")
36
- parser.add_argument("--remove-empty", required = False, action = 'store_true', default = False,
44
+ opexgroup.add_argument("--remove-zipped-files", required = False, action = 'store_true',
45
+ help="Set to remove the original files that have been zipped")
46
+ opexgroup.add_argument("--remove-empty", required = False, action = 'store_true', default = False,
37
47
  help = "Remove and log empty directories from root. Log will be exported to 'meta' / output folder.")
38
- parser.add_argument("--empty-export", required = False, action = 'store_false', default = True,
39
- help="""Set whether to export the generated empty list to a text file in the meta directory.
40
- Enabled by default, disable with this flag.""")
41
- parser.add_argument("--hidden", required = False, action = 'store_true', default = False,
48
+ opexgroup.add_argument("--hidden", required = False, action = 'store_true', default = False,
42
49
  help="Set whether to include hidden files and folders")
43
- parser.add_argument("-o", "--output", required = False, nargs = '?',
44
- help = "Sets the output to send any generated files (Remove Empty, Fixity List, Autoref Export) to. Will not affect creation of a meta dir.")
45
- parser.add_argument("-clr", "--clear-opex", required = False, action = 'store_true', default = False,
46
- help = """Clears existing opex files from a directory. If set with no further options will only clear opexes;
50
+ opexgroup.add_argument("-clr", "--clear-opex", required = False, action = 'store_true', default = False,
51
+ help = """Clears existing opex files from a directory. If set with no further options will only clear opexes;
47
52
  if multiple options are set will clear opexes and then run the program""")
48
- parser.add_argument("-opt","--options-file", required = False, default=os.path.join(os.path.dirname(__file__),'options','options.properties'),
53
+ opexgroup.add_argument("-opt","--options-file", required = False, default=os.path.join(os.path.dirname(__file__),'options','options.properties'),
49
54
  help="Specify a custom Options file, changing the set presets for column headers (Title,Description,etc)")
50
- parser.add_argument("--autoref-options", required = False, default = None,
51
- help="Specify a custom Auto Reference Options file, changing the set presets for Auto Reference Generator")
52
- parser.add_argument("--disable-meta-dir", required = False, action = 'store_false',
53
- help = """Set whether to disable the creation of a 'meta' directory for generated files,
54
- default behaviour is to always generate this directory""")
55
- # Input Options
56
- parser.add_argument("-i", "--input", required = False, nargs='?',
55
+
56
+ inputgroup = parser.add_argument_group('Input Override Options', 'Options that control the Input Override features')
57
+ inputgroup.add_argument("-i", "--input", required = False, nargs='?',
57
58
  help="Set to utilise a CSV / XLSX spreadsheet to import data from")
58
- parser.add_argument("-rm", "--remove", required = False, action = "store_true", default = False,
59
- help="Set whether to enable removals of files and folders from a directory. ***Currently in testing")
60
- parser.add_argument("--removal-export", required = False, action = 'store_false', default = True,
61
- help="""Set whether to export the generated removals list to a text file in the meta directory.
62
- Enabled by default, disable with this flag.""")
63
- parser.add_argument("-mdir","--metadata-dir", required=False, nargs= '?',
59
+ inputgroup.add_argument("-mdir","--metadata-dir", required=False, nargs= '?',
64
60
  default = os.path.join(os.path.dirname(os.path.realpath(__file__)), "metadata"),
65
61
  help="Specify the metadata directory to pull XML files from")
66
- parser.add_argument("-m", "--metadata", required = False, const = 'e', default = None,
67
- nargs = '?', choices = ['exact', 'e', 'flat', 'f'], type = str.lower,
62
+ inputgroup.add_argument("-m", "--metadata", required = False, const = 'e', default = None,
63
+ nargs = '?', choices = ['exact', 'flat'], type = metadata_helper,
68
64
  help="Set whether to include xml metadata fields in the generation of the Opex")
69
- parser.add_argument("--print-xmls", required = False, action = "store_true", default = False,
65
+ inputgroup.add_argument("-rm", "--remove", required = False, action = "store_true", default = False,
66
+ help="Set whether to enable removals of files and folders from a directory. ***Currently in testing")
67
+ inputgroup.add_argument("--print-xmls", required = False, action = "store_true", default = False,
70
68
  help="Prints the elements from your xmls to the consoles")
71
- parser.add_argument("--convert-xmls", required=False, action ='store_true', default = False,
69
+ inputgroup.add_argument("--convert-xmls", required=False, action ='store_true', default = False,
72
70
  help="Convert XMLs templates files in mdir to spreadsheets/csv files")
73
-
71
+ inputgroup.add_argument("--autoref-options", required = False, default = None,
72
+ help="Specify a custom Auto Reference Options file, changing the set presets for Input Override / Auto Reference Generator")
73
+
74
74
  # Auto Reference Options
75
- parser.add_argument("-r", "--autoref", required = False,
76
- choices = ['catalog', 'c', 'accession', 'a', 'both', 'b', 'generic', 'g', 'catalog-generic', 'cg', "accession-generic", "ag", "both-generic", "bg"],
77
- type = str.lower,
78
- help="""Toggles whether to utilise the auto_reference_generator
75
+ autorefgroup = parser.add_argument_group('Auto Reference Generator Options', 'Options that control the Auto Reference Generator features')
76
+
77
+ autorefgroup.add_argument("-r", "--autoref", required = False,
78
+ choices = ['catalog', 'accession', 'both', 'generic', 'catalog-generic', "accession-generic", "both-generic"],
79
+ type = autoref_helper,
80
+ help="""Toggles whether to utilise the auto_reference_generator
79
81
  to generate an on the fly Reference listing.\n
80
82
  There are several options, {catalog} will generate
81
83
  a Archival Reference following an ISAD(G) structure.\n
@@ -85,48 +87,71 @@ def parse_args():
85
87
  if used in conjunction with one of the above options:
86
88
  {generic-catalog,generic-accession, generic-both} it will do both simultaneously.
87
89
  """)
88
- parser.add_argument("-p", "--prefix", required = False, nargs = '+',
90
+ autorefgroup.add_argument("-p", "--prefix", required = False, nargs = '+',
89
91
  help= """Assign a prefix when utilising the --autoref option. Prefix will append any text before all generated text.
90
- When utilising the {both} option fill in like: [catalog-prefix, accession-prefix] without square brackets.
92
+ When utilising the {both} option fill in like: [catalog-prefix, accession-prefix] without square brackets.
91
93
  """)
92
- parser.add_argument("-s", "--suffix", required = False, nargs = '?', default = '',
94
+ autorefgroup.add_argument("-s", "--suffix", required = False, nargs = '?', default = '',
93
95
  help= "Assign a suffix when utilising the --autoref option. Suffix will append any text after all generated text.")
94
- parser.add_argument("--suffix-option", required = False, choices= ['apply_to_files','apply_to_folders','apply_to_both'], default = 'apply_to_files',
96
+ autorefgroup.add_argument("--suffix-option", required = False, choices= ['file', 'directory', 'both'], type = suffix_helper, default = 'apply_to_files',
95
97
  help = "Set whether to apply the suffix to files, folders or both when utilising the --autoref option.")
96
- parser.add_argument("--accession-mode", nargs = '?', required=False, const='file', default=None, choices=["file",'directory','both'],
98
+ autorefgroup.add_argument("--accession-mode", nargs = '?', required=False, const='file', default=None, choices=["file", 'directory', 'both'], type = suffix_helper,
97
99
  help="""Set the mode when utilising the Accession option in autoref.
98
100
  file - only adds on files, folder - only adds on folders, both - adds on files and folders""")
99
- parser.add_argument("-str", "--start-ref", required = False, type=int, nargs = '?', default = 1,
101
+ autorefgroup.add_argument("-str", "--start-ref", required = False, type=int, nargs = '?', default = 1,
100
102
  help="Set a custom Starting reference for the Auto Reference Generator. The generated reference will")
101
- parser.add_argument("-ex", "--export-autoref", required = False, action = 'store_true', default = False,
102
- help="Set whether to export the generated references to an AutoRef spreadsheet")
103
- parser.add_argument("-fmt", "--output-format", required = False, default = "xlsx", choices = ['xlsx', 'csv','json','ods','xml'],
104
- help="Set whether to export AutoRef Spreadsheet to: xlsx, csv, json, ods or xml format")
105
- parser.add_argument("-dlm", "--delimiter", required=False,nargs = '?', type = str, default = '/',
106
- help="Set a custom delimiter for generated references, default is '/'")
107
- parser.add_argument("-key","--keywords", nargs = '*', default = None,
103
+ autorefgroup.add_argument("-dlm", "--delimiter", required=False,nargs = '?', type = str, default = '/',
104
+ help="Set a custom delimiter for generated references, default is '/'")
105
+ autorefgroup.add_argument("--sort-by", required=False, nargs = '?', default = 'folders_first', choices = ['folders_first','alphabetical'], type=str.lower,
106
+ help = "Set the sorting method, 'folders_first' sorts folders first then files alphabetically; 'alphabetically' sorts alphabetically (ignoring folder distinction)")
107
+
108
+ keywordsgroup = parser.add_argument_group('Keyword Options', 'Options that control the Keyword features for Auto Reference Generation')
109
+
110
+ keywordsgroup.add_argument("-key","--keywords", nargs = '*', default = None,
108
111
  help = "Set to replace reference numbers with given Keywords for folders (only Folders atm). Can be a list of keywords or a JSON file mapping folder names to keywords.")
109
- parser.add_argument("-keym","--keywords-mode", nargs = '?', const = "initialise", choices = ['initialise','firstletters','from_json'], default = 'initialise',
112
+ keywordsgroup.add_argument("-keym","--keywords-mode", nargs = '?', const = "initialise", choices = ['initialise','firstletters','from_json'], default = 'initialise',
110
113
  help = "Set to alternate keyword mode: 'initialise' will use initials of words; 'firstletters' will use the first letters of the string; 'from_json' will use a JSON file mapping names to keywords")
111
- parser.add_argument("--keywords-case-sensitivity", required = False, action = 'store_false', default = True,
114
+ keywordsgroup.add_argument("--keywords-case-sensitivity", required = False, action = 'store_false', default = True,
112
115
  help = "Set to change case keyword matching sensitivity. By default keyword matching is insensitive")
113
- parser.add_argument("--keywords-retain-order", required = False, default = False, action = 'store_true',
116
+ keywordsgroup.add_argument("--keywords-retain-order", required = False, default = False, action = 'store_true',
114
117
  help = "Set when using keywords to continue reference numbering. If not used keywords don't 'count' to reference numbering, e.g. if using initials 'Project Alpha' -> 'PA' then the next folder/file will still be '001' not '003'")
115
- parser.add_argument("--keywords-abbreviation-number", required = False, nargs='+', default = None, type = int,
118
+ keywordsgroup.add_argument("--keywords-abbreviation-number", required = False, nargs='+', default = None, type = int,
116
119
  help = "Set to set the number of letters to abbreviate for 'firstletters' mode, does not impact 'initialise' mode.")
117
- parser.add_argument("--sort-by", required=False, nargs = '?', default = 'folders_first', choices = ['folders_first','alphabetical'], type=str.lower,
118
- help = "Set the sorting method, 'folders_first' sorts folders first then files alphabetically; 'alphabetically' sorts alphabetically (ignoring folder distinction)")
119
- parser.add_argument("--log-level", required=False, nargs='?', choices=['DEBUG','INFO','WARNING','ERROR'], default=None, type=str.upper,
120
+
121
+
122
+ exportgroup = parser.add_argument_group('Export Options', 'Options that control various export features')
123
+
124
+ exportgroup.add_argument("--log-level", required=False, nargs='?', choices=['DEBUG','INFO','WARNING','ERROR'], default=None, type=str.upper,
120
125
  help="Set the logging level (default: INFO)")
121
- parser.add_argument("--log-file", required=False, nargs='?', default=None,
126
+ exportgroup.add_argument("--log-file", required=False, nargs='?', default=None,
122
127
  help="Optional path to write logs to a file (default: stdout)")
123
- parser.add_argument("-v", "--version", action = 'version', version = '%(prog)s {version}'.format(version = importlib.metadata.version("opex_manifest_generator")))
124
128
 
125
- args = parser.parse_args()
126
- return args
127
129
 
128
- def run_cli():
129
- args = parse_args()
130
+ exportgroup.add_argument("-o", "--output", required = False, nargs = '?',
131
+ help = "Sets the output of the meta folder to send any generated files (Remove Empty, Fixity List, Autoref Export) to. Can be used in conjunction with --disable-meta-dir to set output location without generating meta directory.")
132
+
133
+ exportgroup.add_argument("--disable-meta-dir", required = False, action = 'store_false',
134
+ help = """Set whether to disable the creation of a 'meta' directory for generated files,
135
+ default behaviour is to always generate this directory""")
136
+ exportgroup.add_argument("--disable-all-exports", required = False, action = 'store_true', default = False,
137
+ help="Set to prevent all exports (Fixity, Removal, Empty) from being created in the meta directory.")
138
+ exportgroup.add_argument("--disable-fixity-export", required = False, action = 'store_false', default = True,
139
+ help="""Set whether to export the generated fixity list to a text file in the meta directory.
140
+ Enabled by default, disable with this flag.""")
141
+ exportgroup.add_argument("--disable-empty-export", required = False, action = 'store_false', default = True,
142
+ help="""Set whether to export the generated empty list to a text file in the meta directory.
143
+ Enabled by default, disable with this flag.""")
144
+ exportgroup.add_argument("--disable-removal-export", required = False, action = 'store_false', default = True,
145
+ help="""Set whether to export the generated removals list to a text file in the meta directory.
146
+ Enabled by default, disable with this flag.""")
147
+ exportgroup.add_argument("-ex", "--export-autoref", required = False, action = 'store_true', default = False,
148
+ help="Set whether to export the generated references to an AutoRef spreadsheet")
149
+ exportgroup.add_argument("-fmt", "--output-format", required = False, default = "xlsx", choices = ['xlsx', 'csv','json','ods','xml'], type=fmthelper,
150
+ help="Set whether to export AutoRef Spreadsheet to: xlsx, csv, json, ods or xml format")
151
+
152
+ return parser
153
+
154
+ def run_cli(args = None):
130
155
 
131
156
  # Configure logging early so other modules inherit the settings
132
157
  try:
@@ -145,14 +170,14 @@ def run_cli():
145
170
  'If you are utilising Windows ensure that the path does not end with \\\' or \\"')
146
171
  raise FileNotFoundError(f'Please ensure that root path {args.root} exists. \n' \
147
172
  'If you are utilising Windows ensure that the path does not end with \\\' or \\" ')
148
-
173
+
149
174
  if isinstance(args.root, str):
150
175
  args.root = args.root.strip("\"").rstrip("\\")
151
176
  logger.info(f"Running Opex Generation on: {args.root}")
152
177
 
153
178
  if not args.output:
154
179
  args.output = os.path.abspath(args.root)
155
- logger.debug(f'Output path set to root directory: {args.output}')
180
+ logger.debug(f'Output path set to root directory: {args.output}')
156
181
  else:
157
182
  args.output = os.path.abspath(args.output)
158
183
  logger.info(f'Output path set to {args.output}')
@@ -165,7 +190,7 @@ def run_cli():
165
190
  raise ValueError('Removal flag has been given without input, please ensure an input file is utilised when using this option.')
166
191
  if args.metadata is not None and not args.input:
167
192
  logger.warning(f'Warning: Metadata Flag has been given without Input. Metadata won\'t be generated.')
168
-
193
+
169
194
  if args.print_xmls:
170
195
  logger.info(f'Printing xmls in {args.metadata_dir} then ending')
171
196
  OpexManifestGenerator(root = args.root, metadata_dir=args.metadata_dir).print_descriptive_xmls()
@@ -175,21 +200,21 @@ def run_cli():
175
200
  OpexManifestGenerator(root = args.root, output_format=args.output_format, metadata_dir=args.metadata_dir).convert_descriptive_xmls()
176
201
  raise SystemExit()
177
202
 
178
- if args.prevent_all_exports:
203
+ if args.disable_all_exports:
179
204
  args.fixity_export_flag = False
180
205
  args.removal_export_flag = False
181
206
  args.empty_export_flag = False
182
207
  logger.info('All exports have been prevented via --prevent-all-exports flag.')
183
208
 
184
209
  acc_prefix = None
185
- if args.autoref in {"accession", "a", "accession-generic", "ag", "both", "b", "both-generic", "bg"} and args.accession_mode is None:
210
+ if args.autoref in {"accession", "accession-generic", "both", "both-generic"} and args.accession_mode is None:
186
211
  args.accession_mode = "file"
187
212
  logger.debug(f'Accession mode not set, defaulting to "file" mode for accession generation.')
188
213
 
189
214
  if args.prefix:
190
- if args.autoref in {"both", "b", "both-generic", "bg"}:
215
+ if args.autoref in {"both", "both-generic"}:
191
216
  if len(args.prefix) < 2 or len(args.prefix) > 2:
192
- logger.error('"Both" option is selected, please pass only two prefixes: [-p CATALOG_PREFIX ACCESSION_PREFIX]');
217
+ logger.error('"Both" option is selected, please pass only two prefixes: [-p CATALOG_PREFIX ACCESSION_PREFIX]');
193
218
  raise ValueError('"Both" option is selected, please pass only two prefixes: [-p CATALOG_PREFIX ACCESSION_PREFIX]')
194
219
  for n, a in enumerate(args.prefix):
195
220
  if n == 0:
@@ -197,29 +222,23 @@ def run_cli():
197
222
  elif n == 1:
198
223
  acc_prefix = str(a)
199
224
  logger.info(f"Prefixes are set as: \t Catalog: {args.prefix} \t Acc: {acc_prefix}")
200
- elif args.autoref in {"accession", "a", "accession-generic", "ag"}:
225
+ elif args.autoref in {"accession", "accession-generic"}:
201
226
  for a in args.prefix:
202
227
  acc_prefix = str(a)
203
- logger.info('Prefix is set as: ' + acc_prefix)
204
- elif args.autoref in {"catalog", "c", "catalog-generic", "cg"}:
228
+ logger.info('Prefix is set as: ' + acc_prefix)
229
+ elif args.autoref in {"catalog", "catalog-generic"}:
205
230
  acc_prefix = None
206
- for a in args.prefix:
231
+ for a in args.prefix:
207
232
  args.prefix = str(a)
208
233
  logger.info('Prefix is set as: ' + args.prefix)
209
- elif args.autoref in {"generic", "g"}:
234
+ elif args.autoref in {"generic"}:
210
235
  logger.info('Using Generic mode')
211
236
  pass
212
237
  else:
213
- logger.error('''An invalid option has been selected, please select a valid option:
214
- {c, catalog
215
- a, accession
216
- b, both
217
- g, generic
218
- cg, catalog-generic
219
- ag, accession-generic
220
- bg, both-generic}''')
221
- raise ValueError('An invalid option has been selected, please select a valid option.')
222
-
238
+ logger.error('''An invalid option has been selected, please select a valid option:
239
+ {catalog, accession, both, generic, catalog-generic, accession-generic, both-generic}''')
240
+ raise ValueError('An invalid option has been selected, please select a valid option.')
241
+
223
242
  if args.fixity:
224
243
  logger.info(f'Fixity is activated, using {args.fixity} algorithm')
225
244
 
@@ -240,10 +259,10 @@ def run_cli():
240
259
  "\n***"))
241
260
  i = input(inspect.cleandoc("Please type Y if you wish to proceed, otherwise the program will close: "))
242
261
  if not i.lower() == "y":
243
- logger.info("Y not typed, safetly aborted...")
262
+ logger.info("Y not typed, safely aborted...")
244
263
  raise SystemExit()
245
264
  else:
246
- logger.info("Confirmation recieved proceeding to remove files")
265
+ logger.info("Confirmation received proceeding to remove files")
247
266
 
248
267
  if args.remove_empty:
249
268
  logger.warning(inspect.cleandoc("\n***WARNING***" \
@@ -253,35 +272,37 @@ def run_cli():
253
272
  "\n***"))
254
273
  i = input(inspect.cleandoc("Please type Y if you wish to proceed, otherwise the program will close: "))
255
274
  if not i.lower() == "y":
256
- logger.info("Y not typed, safetly aborted...")
275
+ logger.info("Y not typed, safely aborted...")
257
276
  raise SystemExit()
258
277
  else:
259
- logger.info("Confirmation recieved proceeding to remove empty folders...")
278
+ logger.info("Confirmation received proceeding to remove empty folders...")
260
279
 
261
280
  start_time = datetime.now()
262
- OpexManifestGenerator(root = args.root,
263
- output_path = args.output,
264
- autoref_flag = args.autoref,
265
- prefix = args.prefix,
281
+ OpexManifestGenerator(root = args.root,
282
+ output_path = args.output,
283
+ autoref_flag = args.autoref,
284
+ prefix = args.prefix,
285
+ suffix = args.suffix,
286
+ suffix_option = args.suffix_option,
266
287
  accession_mode=args.accession_mode,
267
- acc_prefix = acc_prefix,
268
- empty_flag = args.remove_empty,
269
- empty_export_flag = args.empty_export,
270
- removal_flag = args.remove,
271
- removal_export_flag = args.removal_export,
272
- clear_opex_flag = args.clear_opex,
288
+ acc_prefix = acc_prefix,
289
+ empty_flag = args.remove_empty,
290
+ empty_export_flag = args.disable_empty_export,
291
+ removal_flag = args.remove,
292
+ removal_export_flag = args.disable_removal_export,
293
+ clear_opex_flag = args.clear_opex,
273
294
  algorithm = args.fixity,
274
295
  pax_fixity= args.pax_fixity,
275
- fixity_export_flag = args.fixity_export,
276
- start_ref = args.start_ref,
277
- export_flag = args.export_autoref,
278
- meta_dir_flag = args.disable_meta_dir,
296
+ fixity_export_flag = args.disable_fixity_export,
297
+ start_ref = args.start_ref,
298
+ export_flag = args.export_autoref,
299
+ meta_dir_flag = args.disable_meta_dir,
279
300
  metadata_flag = args.metadata,
280
301
  metadata_dir = args.metadata_dir,
281
302
  hidden_flag= args.hidden,
282
- zip_flag = args.zip,
283
- zip_file_removal= args.zip_remove_files,
284
- input = args.input,
303
+ zip_flag = args.zip,
304
+ zip_file_removal= args.remove_zipped_files,
305
+ input = args.input,
285
306
  output_format = args.output_format,
286
307
  options_file=args.options_file,
287
308
  keywords = args.keywords,
@@ -292,26 +313,86 @@ def run_cli():
292
313
  keywords_abbreviation_number = args.keywords_abbreviation_number,
293
314
  sort_key = sort_key,
294
315
  ).main()
295
- logger.info(f"Run Complete! Ran for: {running_time(start_time)}")
316
+ logger.info(f"Run Complete! Ran for: {running_time(start_time)}")
296
317
 
297
318
  def fixity_helper(x: str):
298
319
  x = x.upper()
299
- if x == 'SHA1':
320
+ if x in ('MD5', 'M5', 'M'):
321
+ x = 'MD5'
322
+ if x in ('SHA1', 'SHA-1', 'S1'):
300
323
  x = 'SHA-1'
301
- if x == 'SHA256':
324
+ if x in ('SHA256', 'SHA-256', 'S256'):
302
325
  x = 'SHA-256'
303
- if x == 'SHA512':
326
+ if x in ('SHA512', 'SHA-512', 'S512'):
304
327
  x = 'SHA-512'
305
328
  return x.upper()
306
329
 
330
+ def autoref_helper(x: str):
331
+ x = x.lower()
332
+ if x in ('c', 'catalog', 'catalogue', 'cat'):
333
+ x = 'catalog'
334
+ if x == ('a', 'accession', 'acc'):
335
+ x = 'accession'
336
+ if x == ('b', 'both', 'all'):
337
+ x = 'both'
338
+ if x == ('g', 'generic', 'gen'):
339
+ x = 'generic'
340
+ if x == ('cg', 'catalog-generic', 'catalogue-generic', 'cat-generic', 'catalogue-gen', 'cat-gen', 'catalog-gen'):
341
+ x = 'catalog-generic'
342
+ if x == ('ag', 'accession-generic', 'acc-generic', 'accession-gen', 'acc-gen'):
343
+ x = 'accession-generic'
344
+ if x == ('bg', 'both-generic', 'all-generic', 'all-gen'):
345
+ x = 'both-generic'
346
+ return x.lower()
347
+
348
+ def suffix_helper(x: str):
349
+ x = x.lower()
350
+ if x in ('f', 'file', 'files'):
351
+ x = 'file'
352
+ if x in ('d', 'dir', 'dirs', 'folders', 'folder', 'directory'):
353
+ x = 'directory'
354
+ if x in ('b', 'both'):
355
+ x = 'both'
356
+ return x.lower()
357
+
358
+ def metadata_helper(x: str):
359
+ x = x.lower()
360
+ if x in ('e', 'exact'):
361
+ x = 'exact'
362
+ if x in ('f', 'flat'):
363
+ x = 'flat'
364
+ return x.lower()
365
+
366
+ def fmthelper(x: str):
367
+ x = x.lower()
368
+ if x in ('xlsx', 'xlsm', 'xltx', 'xltm', 'xlsb', 'xls', 'excel', 'xl'):
369
+ x = 'xlsx'
370
+ if x in ('csv', 'txt', 'comma', 'comma_separated', 'c'):
371
+ x = 'csv'
372
+ if x in ('json', 'jsn', 'j'):
373
+ x = 'json'
374
+ if x in ('ods', 'open_document_spreadsheet', 'o'):
375
+ x = 'ods'
376
+ if x in ('xml', 'html', 'htm'):
377
+ x = 'xml'
378
+ if x in ('dict','dictionary', 'd'):
379
+ x = 'dict'
380
+ return x.lower()
381
+
382
+
307
383
  class EmptyIsTrueFixity(argparse.Action):
308
384
  def __call__(self, parser, namespace, values, option_string=None):
309
385
  if len(values) == 0:
310
386
  values = ["SHA-1"]
311
387
  setattr(namespace, self.dest, values)
312
388
 
313
- if __name__ == "__main__":
389
+ def main():
314
390
  try:
315
- run_cli()
391
+ parser = create_parser()
392
+ args = parser.parse_args()
393
+ run_cli(args)
316
394
  except KeyboardInterrupt:
317
- logger.warning("Process interrupted by user, exiting...")
395
+ logger.warning("Process interrupted by user, exiting...")
396
+
397
+ if __name__ == "__main__":
398
+ main()
@@ -7,6 +7,7 @@ license: Apache License 2.0"
7
7
 
8
8
  import zipfile, os, sys, stat, shutil, logging, lxml
9
9
  from datetime import datetime, timedelta
10
+ from typing import Optional
10
11
 
11
12
  logger = logging.getLogger(__name__)
12
13
 
@@ -30,7 +31,7 @@ def remove_tree(path: str, removed_list: list) -> None:
30
31
  for dp,d,f in os.walk(path):
31
32
  for fn in f:
32
33
  removed_list.append(win_256_check(dp+win_path_delimiter()+fn))
33
- logger.info(f'Removing {dp + win_path_delimiter() + fn}')
34
+ logger.info(f'Removing {dp + win_path_delimiter() + fn}')
34
35
  for dn in d:
35
36
  removed_list.append(win_256_check(dp+win_path_delimiter()+dn))
36
37
  logger.info(f'Removing {dp + win_path_delimiter() + dn}')
@@ -44,7 +45,7 @@ def win_256_check(path) -> str:
44
45
  if len(path) > 255 and sys.platform == "win32":
45
46
  logger.debug(f'Path: {path} is greater than 255 Characters')
46
47
  if path.startswith(u"\\\\?\\"):
47
- path = path
48
+ path = path
48
49
  else:
49
50
  path = u"\\\\?\\" + path
50
51
  return path
@@ -57,23 +58,23 @@ def filter_win_hidden(path: str) -> bool:
57
58
  return False
58
59
  else:
59
60
  return False
60
-
61
+
61
62
  def win_path_delimiter() -> str:
62
63
  if sys.platform == "win32":
63
64
  return "\\"
64
65
  else:
65
66
  return "/"
66
67
 
67
- def check_nan(value) -> str | None:
68
+ def check_nan(value) -> Optional[str]:
68
69
  if str(value).lower() in {"nan","nat"}:
69
70
  value = None
70
71
  return value
71
72
 
72
73
  def check_opex(opex_path:str) -> bool:
73
- opex_path = opex_path + ".opex"
74
+ opex_path = opex_path + ".opex"
74
75
  if os.path.exists(win_256_check(opex_path)):
75
76
  return False
76
- else:
77
+ else:
77
78
  return True
78
79
 
79
80
  def write_opex(path: str, opexxml: lxml.etree.Element) -> str:
@@ -86,5 +87,5 @@ def write_opex(path: str, opexxml: lxml.etree.Element) -> str:
86
87
  return opex_path
87
88
 
88
89
  def running_time(start_time) -> timedelta:
89
- running_time = datetime.now() - start_time
90
- return running_time
90
+ running_time = datetime.now() - start_time
91
+ return running_time
@@ -6,7 +6,7 @@ license: Apache License 2.0"
6
6
  """
7
7
 
8
8
  import hashlib, logging
9
- from opex_manifest_generator.common import win_256_check
9
+ from opex_manifest_generator.common import win_256_check
10
10
 
11
11
  logger = logging.getLogger(__name__)
12
12
 
@@ -47,7 +47,7 @@ class HashGenerator():
47
47
  except Exception as e:
48
48
  logger.exception(f'Error Generating Hash: {e}')
49
49
  raise
50
-
50
+
51
51
  def hash_generator_pax_zip(self, filename: str, z):
52
52
  if self.algorithm in ("SHA1","SHA-1"):
53
53
  hash = hashlib.sha1()
@@ -61,7 +61,7 @@ class HashGenerator():
61
61
  hash = hashlib.sha1()
62
62
  logger.info(f'Generating Fixity using {self.algorithm} for: {filename}')
63
63
  try:
64
- with z.open(filename, 'r') as data:
64
+ with z.open(filename, 'r') as data:
65
65
  while True:
66
66
  buff = data.read(self.buffer)
67
67
  if not buff:
@@ -77,4 +77,4 @@ class HashGenerator():
77
77
  except Exception as e:
78
78
  logger.exception(f'Error Generating Hash: {e}')
79
79
  raise
80
- return str(hash.hexdigest().upper())
80
+ return str(hash.hexdigest().upper())
@@ -99,4 +99,4 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:is
99
99
  <p></p>
100
100
  </processinfo>
101
101
  </archdesc>
102
- </ead:ead>
102
+ </ead:ead>
@@ -6,4 +6,4 @@
6
6
  <recordobjecteddate></recordobjecteddate>
7
7
  <recipientdisclosurecategory></recipientdisclosurecategory>
8
8
  <timelimitforerasure></timelimitforerasure>
9
- </gdpr>
9
+ </gdpr>
@@ -64,4 +64,4 @@
64
64
  <note type="bibliography" displayLabel="Bibliography"></note>
65
65
  <note type="other" displayLabel="Other descriptive data"></note>
66
66
  <note type="processinfo" displayLabel="Processing Information"></note>
67
- </mods>
67
+ </mods>