opex-manifest-generator 1.3.5__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.
- opex_manifest_generator/__init__.py +3 -3
- opex_manifest_generator/cli.py +204 -123
- opex_manifest_generator/common.py +7 -7
- opex_manifest_generator/hash.py +4 -4
- opex_manifest_generator/metadata/EAD Template.xml +1 -1
- opex_manifest_generator/metadata/GDPR Template.xml +1 -1
- opex_manifest_generator/metadata/MODS Template.xml +1 -1
- opex_manifest_generator/opex_manifest.py +57 -57
- opex_manifest_generator/options/options.properties +1 -1
- opex_manifest_generator-1.3.6.dist-info/METADATA +619 -0
- opex_manifest_generator-1.3.6.dist-info/RECORD +16 -0
- opex_manifest_generator-1.3.6.dist-info/entry_points.txt +2 -0
- {opex_manifest_generator-1.3.5.dist-info → opex_manifest_generator-1.3.6.dist-info}/licenses/LICENSE.md +1 -1
- opex_manifest_generator-1.3.5.dist-info/METADATA +0 -557
- opex_manifest_generator-1.3.5.dist-info/RECORD +0 -16
- opex_manifest_generator-1.3.5.dist-info/entry_points.txt +0 -2
- {opex_manifest_generator-1.3.5.dist-info → opex_manifest_generator-1.3.6.dist-info}/WHEEL +0 -0
- {opex_manifest_generator-1.3.5.dist-info → opex_manifest_generator-1.3.6.dist-info}/top_level.txt +0 -0
|
@@ -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
|
|
12
|
-
import
|
|
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__ =
|
|
16
|
+
__version__ = metadata.version("opex_manifest_generator")
|
opex_manifest_generator/cli.py
CHANGED
|
@@ -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
|
|
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
|
|
17
|
-
|
|
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
|
-
|
|
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
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
35
|
-
help="Set to remove the files that have been zipped")
|
|
36
|
-
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
help = "
|
|
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
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
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
|
-
|
|
67
|
-
nargs = '?', choices = ['exact', '
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
102
|
-
help="Set
|
|
103
|
-
|
|
104
|
-
help="Set
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
parser.
|
|
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
|
-
|
|
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
|
-
|
|
129
|
-
|
|
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.
|
|
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", "
|
|
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", "
|
|
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", "
|
|
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", "
|
|
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"
|
|
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
|
-
{
|
|
215
|
-
|
|
216
|
-
|
|
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,
|
|
262
|
+
logger.info("Y not typed, safely aborted...")
|
|
244
263
|
raise SystemExit()
|
|
245
264
|
else:
|
|
246
|
-
logger.info("Confirmation
|
|
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,
|
|
275
|
+
logger.info("Y not typed, safely aborted...")
|
|
257
276
|
raise SystemExit()
|
|
258
277
|
else:
|
|
259
|
-
logger.info("Confirmation
|
|
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.
|
|
270
|
-
removal_flag = args.remove,
|
|
271
|
-
removal_export_flag = args.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
324
|
+
if x in ('SHA256', 'SHA-256', 'S256'):
|
|
302
325
|
x = 'SHA-256'
|
|
303
|
-
if x
|
|
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
|
-
|
|
389
|
+
def main():
|
|
314
390
|
try:
|
|
315
|
-
|
|
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()
|
|
@@ -31,7 +31,7 @@ def remove_tree(path: str, removed_list: list) -> None:
|
|
|
31
31
|
for dp,d,f in os.walk(path):
|
|
32
32
|
for fn in f:
|
|
33
33
|
removed_list.append(win_256_check(dp+win_path_delimiter()+fn))
|
|
34
|
-
logger.info(f'Removing {dp + win_path_delimiter() + fn}')
|
|
34
|
+
logger.info(f'Removing {dp + win_path_delimiter() + fn}')
|
|
35
35
|
for dn in d:
|
|
36
36
|
removed_list.append(win_256_check(dp+win_path_delimiter()+dn))
|
|
37
37
|
logger.info(f'Removing {dp + win_path_delimiter() + dn}')
|
|
@@ -45,7 +45,7 @@ def win_256_check(path) -> str:
|
|
|
45
45
|
if len(path) > 255 and sys.platform == "win32":
|
|
46
46
|
logger.debug(f'Path: {path} is greater than 255 Characters')
|
|
47
47
|
if path.startswith(u"\\\\?\\"):
|
|
48
|
-
path = path
|
|
48
|
+
path = path
|
|
49
49
|
else:
|
|
50
50
|
path = u"\\\\?\\" + path
|
|
51
51
|
return path
|
|
@@ -58,7 +58,7 @@ def filter_win_hidden(path: str) -> bool:
|
|
|
58
58
|
return False
|
|
59
59
|
else:
|
|
60
60
|
return False
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
def win_path_delimiter() -> str:
|
|
63
63
|
if sys.platform == "win32":
|
|
64
64
|
return "\\"
|
|
@@ -71,10 +71,10 @@ def check_nan(value) -> Optional[str]:
|
|
|
71
71
|
return value
|
|
72
72
|
|
|
73
73
|
def check_opex(opex_path:str) -> bool:
|
|
74
|
-
opex_path = opex_path + ".opex"
|
|
74
|
+
opex_path = opex_path + ".opex"
|
|
75
75
|
if os.path.exists(win_256_check(opex_path)):
|
|
76
76
|
return False
|
|
77
|
-
else:
|
|
77
|
+
else:
|
|
78
78
|
return True
|
|
79
79
|
|
|
80
80
|
def write_opex(path: str, opexxml: lxml.etree.Element) -> str:
|
|
@@ -87,5 +87,5 @@ def write_opex(path: str, opexxml: lxml.etree.Element) -> str:
|
|
|
87
87
|
return opex_path
|
|
88
88
|
|
|
89
89
|
def running_time(start_time) -> timedelta:
|
|
90
|
-
running_time = datetime.now() - start_time
|
|
91
|
-
return running_time
|
|
90
|
+
running_time = datetime.now() - start_time
|
|
91
|
+
return running_time
|
opex_manifest_generator/hash.py
CHANGED
|
@@ -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())
|