opex-manifest-generator 1.1.12__py3-none-any.whl → 1.2.0__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.
@@ -5,9 +5,7 @@ author: Christopher Prince
5
5
  license: Apache License 2.0"
6
6
  """
7
7
 
8
- import argparse
9
- import os
10
- import time
8
+ import argparse, os, inspect, time
11
9
  from opex_manifest_generator.opex_manifest import OpexManifestGenerator
12
10
  import importlib.metadata
13
11
 
@@ -39,7 +37,7 @@ def parse_args():
39
37
  help = "Remove and log empty directories from root. Log will be exported to 'meta' / output folder.")
40
38
  parser.add_argument("-o", "--output", required = False, nargs = 1,
41
39
  help = "Sets the output to send any generated files to. Will not affect creation of a meta dir.")
42
- parser.add_argument("-dmd", "--disable-meta-dir", required = False, action = 'store_false',
40
+ parser.add_argument("--disable-meta-dir", required = False, action = 'store_false',
43
41
  help = """Set whether to disable the creation of a 'meta' directory for generated files,
44
42
  default behaviour is to always generate this directory""")
45
43
  parser.add_argument("-clr", "--clear-opex", required = False, action = 'store_true', default = False,
@@ -66,13 +64,19 @@ def parse_args():
66
64
  parser.add_argument("-fmt", "--output-format", required = False, default = "xlsx", choices = ['xlsx', 'csv'],
67
65
  help="Set whether to output to an xlsx or csv format")
68
66
  parser.add_argument("-v", "--version", action = 'version', version = '%(prog)s {version}'.format(version = importlib.metadata.version("opex_manifest_generator")))
69
- parser.add_argument("--accession-mode", required=False, choices=["file",'directory','both'],
67
+ parser.add_argument("--accession-mode", nargs = '?', required=False, const='file', default=None, choices=["file",'directory','both'],
70
68
  help="""Set the mode when utilising the Accession option in autoclass.
71
69
  file - only adds on files, folder - only adds on folders, both - adds on files and folders""")
72
70
  parser.add_argument("--hidden", required = False, action = 'store_true', default = False,
73
71
  help="Set whether to include hidden files and folders")
74
72
  parser.add_argument("--print-xmls", required = False, action = "store_true", default = False,
75
73
  help="Prints the elements from your xmls to the consoles")
74
+ parser.add_argument("-key","--keywords", nargs = '*', default = None)
75
+ parser.add_argument("-keym","--keywords-mode", nargs = '?', const = "intialise", default = "intialise", choices = ['intialise','firstletters'])
76
+ parser.add_argument("--keywords-retain-order", required = False, default = False, action = 'store_true')
77
+ parser.add_argument("--keywords-abbreviation-number", required = False, nargs='?', default = -3, type = int)
78
+ parser.add_argument("--sort-by", required=False, nargs = '?', default = 'foldersfirst', choices = ['foldersfirst','alphabetical'], type=str.lower)
79
+ parser.add_argument("-dlm", "--delimiter", required=False,nargs = '?', type = str)
76
80
  args = parser.parse_args()
77
81
  return args
78
82
 
@@ -94,6 +98,8 @@ def run_cli():
94
98
  if args.print_xmls:
95
99
  OpexManifestGenerator.print_descriptive_xmls()
96
100
  acc_prefix = None
101
+ if args.autoclass in {"accession", "a", "accession-generic", "ag", "both", "b", "both-generic", "bg"} and args.accession_mode is None:
102
+ args.accession_mode = "file"
97
103
  if args.prefix:
98
104
  if args.autoclass in {"both", "b", "both-generic", "bg"}:
99
105
  if len(args.prefix) < 2 or len(args.prefix) > 2:
@@ -129,11 +135,20 @@ def run_cli():
129
135
  raise SystemExit
130
136
  if args.fixity:
131
137
  print(f'Fixity is activated, using {args.fixity} algorithm')
138
+ if args.sort_by:
139
+ if args.sort_by == "foldersfirst":
140
+ sort_key = lambda x: (os.path.isfile(x), str.casefold(x))
141
+ elif args.sort_by == "alphabetical":
142
+ sort_key = str.casefold
132
143
  if args.remove:
133
- i = "y"
134
- # i = input(inspect.cleandoc("""You have enabled the remove functionality.
135
- # This action will remove files listed for removal, it is irreversible.
136
- # Please type Y to confirm, otherwise program will close: """))
144
+ print(inspect.cleandoc("""****
145
+ You have enabled the remove functionality of the program. This action will remove all files and folders listed for removal and any sub-files/sub-folders.
146
+
147
+ This process will permanently delete the selected items, with no way recover the items.
148
+
149
+ ****"""))
150
+ time.sleep(2)
151
+ i = input(inspect.cleandoc("Please type Y if you wish to proceed, otherwise the program will close: "))
137
152
  if not i.lower() == "y":
138
153
  print("Closing program..."); time.sleep(3); raise SystemExit()
139
154
  time.sleep(3)
@@ -141,6 +156,7 @@ def run_cli():
141
156
  output_path = args.output,
142
157
  autoclass_flag = args.autoclass,
143
158
  prefix = args.prefix,
159
+ accession_mode=args.accession_mode,
144
160
  acc_prefix = acc_prefix,
145
161
  empty_flag = args.remove_empty,
146
162
  remove_flag = args.remove,
@@ -155,7 +171,13 @@ def run_cli():
155
171
  zip_flag = args.zip,
156
172
  input = args.input,
157
173
  output_format = args.output_format,
158
- options_file=args.options_file).main()
174
+ options_file=args.options_file,
175
+ keywords = args.keywords,
176
+ keywords_mode = args.keywords_mode,
177
+ keywords_retain_order = args.keywords_retain_order,
178
+ sort_key = sort_key,
179
+ delimiter = args.delimiter,
180
+ keywords_abbreviation_number = args.keywords_abbreviation_number).main()
159
181
 
160
182
  if __name__ == "__main__":
161
183
  run_cli()
@@ -25,12 +25,18 @@ def win_256_check(path: str):
25
25
 
26
26
  def filter_win_hidden(path: str):
27
27
  if sys.platform =="win32":
28
- if bool(os.stat(path).st_file_attribute & stat.FILE_ATTRIBUTE_HIDDEN) is True:
28
+ if bool(os.stat(path).st_file_attributes & stat.FILE_ATTRIBUTE_HIDDEN) is True:
29
29
  return True
30
30
  else:
31
31
  return False
32
32
  else:
33
33
  return False
34
+
35
+ def win_path_delimiter():
36
+ if sys.platform == "win32":
37
+ return "\\"
38
+ else:
39
+ return "/"
34
40
 
35
41
  def check_nan(value):
36
42
  if str(value).lower() in {"nan","nat"}:
@@ -21,13 +21,14 @@ import configparser
21
21
  class OpexManifestGenerator():
22
22
  def __init__(self,
23
23
  root: str,
24
- output_path: os.path = os.getcwd(),
24
+ output_path: str = os.getcwd(),
25
25
  meta_dir_flag: bool = True,
26
- metadata_dir: os = os.path.join(os.path.dirname(os.path.realpath(__file__)), "metadata"),
26
+ metadata_dir: str = os.path.join(os.path.dirname(os.path.realpath(__file__)), "metadata"),
27
27
  metadata_flag: str = 'none',
28
28
  autoclass_flag: str = None,
29
29
  prefix: str = None,
30
30
  acc_prefix: str = None,
31
+ accession_mode: str = False,
31
32
  startref: int = 1,
32
33
  algorithm: str = None,
33
34
  empty_flag: bool = False,
@@ -39,7 +40,13 @@ class OpexManifestGenerator():
39
40
  hidden_flag: bool = False,
40
41
  output_format: str = "xlsx",
41
42
  print_xmls_flag: bool = False,
42
- options_file: str = os.path.join(os.path.dirname(__file__),'options.properties')):
43
+ options_file: str = os.path.join(os.path.dirname(__file__),'options.properties'),
44
+ keywords: list = None,
45
+ keywords_mode: str = "intitalise",
46
+ keywords_retain_order: bool = False,
47
+ sort_key = lambda x: (os.path.isfile(x), str.casefold(x)),
48
+ keywords_abbreviation_number: int = 3,
49
+ delimiter = "/"):
43
50
 
44
51
  self.root = os.path.abspath(root)
45
52
  self.opexns = "http://www.openpreservationexchange.org/opex/v1.2"
@@ -49,6 +56,8 @@ class OpexManifestGenerator():
49
56
  self.algorithm = algorithm
50
57
  self.empty_flag = empty_flag
51
58
  self.remove_flag = remove_flag
59
+ if self.remove_flag:
60
+ self.remove_list = []
52
61
  self.export_flag = export_flag
53
62
  self.startref = startref
54
63
  self.autoclass_flag = autoclass_flag
@@ -57,6 +66,7 @@ class OpexManifestGenerator():
57
66
  self.meta_dir_flag = meta_dir_flag
58
67
  self.prefix = prefix
59
68
  self.acc_prefix = acc_prefix
69
+ self.accession_mode = accession_mode
60
70
  self.input = input
61
71
  self.hidden_flag = hidden_flag
62
72
  self.zip_flag = zip_flag
@@ -65,13 +75,18 @@ class OpexManifestGenerator():
65
75
  self.metadata_dir = metadata_dir
66
76
  self.print_xmls_flag = print_xmls_flag
67
77
  self.parse_config(options_file=os.path.abspath(options_file))
78
+ self.keywords_list = keywords
79
+ self.keywords_mode = keywords_mode
80
+ self.keywords_retain_order = keywords_retain_order
81
+ self.sort_key = sort_key
82
+ self.keywords_abbreviation_number = keywords_abbreviation_number
68
83
 
69
84
  self.title_flag = False
70
85
  self.description_flag = False
71
86
  self.security_flag = False
72
87
  self.ignore_flag = False
73
88
  self.sourceid_flag = False
74
- self.hash_from_spread = False
89
+ self.hash_from_spread = False
75
90
 
76
91
  def parse_config(self, options_file: str = 'options.properties'):
77
92
  config = configparser.ConfigParser()
@@ -130,10 +145,19 @@ class OpexManifestGenerator():
130
145
 
131
146
  def init_df(self):
132
147
  if self.autoclass_flag:
133
- if self.autoclass_flag in {"catalog", "c", "catalog-generic", "cg"}:
134
- ac = ClassificationGenerator(self.root, output_path = self.output_path, prefix = self.prefix, start_ref = self.startref, empty_flag = self.empty_flag, accession_flag = False)
135
- elif self.autoclass_flag in {"accession", "a", "accession-generic", "ag", "both", "b", "both-generic", "bg"}:
136
- ac = ClassificationGenerator(self.root, output_path = self.output_path, prefix = self.prefix, accprefix = self.acc_prefix, start_ref = self.startref, empty_flag = self.empty_flag, accession_flag="File")
148
+ ac = ClassificationGenerator(self.root,
149
+ output_path = self.output_path,
150
+ prefix = self.prefix,
151
+ accprefix = self.acc_prefix,
152
+ start_ref = self.startref,
153
+ empty_flag = self.empty_flag,
154
+ accession_flag=self.accession_mode,
155
+ keywords = self.keywords_list,
156
+ keywords_mode = self.keywords_mode,
157
+ keywords_retain_order = self.keywords_retain_order,
158
+ sort_key = self.sort_key,
159
+ keywords_abbreviation_number = self.keywords_abbreviation_number,
160
+ delimiter = self.delimiter)
137
161
  self.df = ac.init_dataframe()
138
162
  if self.autoclass_flag in {"accession", "a", "accesion-generic", "ag"}:
139
163
  self.df = self.df.drop('Archive_Reference', axis=1)
@@ -188,19 +212,25 @@ class OpexManifestGenerator():
188
212
  print('Error Looking up XIP Metadata')
189
213
  print(e)
190
214
 
191
- def remove_df_lookup(self, path: str, idx: pd.Index):
215
+ def remove_df_lookup(self, path: str, removed_list: list, idx: pd.Index):
192
216
  try:
193
217
  if idx.empty:
194
218
  return False
195
219
  else:
196
220
  remove = check_nan(self.df[REMOVAL_FIELD].loc[idx].item())
197
- if remove:
221
+ if remove is True:
222
+ removed_list.append(path)
198
223
  print(f"Removing: {path}")
199
- # Not functioning correctly
200
224
  if os.path.isdir(path):
225
+ for dp,d,f in os.walk(path):
226
+ for fn in f:
227
+ removed_list.append(win_256_check(dp+win_path_delimiter()+fn))
228
+ for dn in d:
229
+ removed_list.append(win_256_check(dp+win_path_delimiter()+dn))
201
230
  shutil.rmtree(path)
202
231
  else:
203
- os.remove(path)
232
+ if os.path.exists(path):
233
+ os.remove(path)
204
234
  return True
205
235
  else:
206
236
  return False
@@ -285,7 +315,7 @@ class OpexManifestGenerator():
285
315
  xml_file = ET.parse(path)
286
316
  root_element = ET.QName(xml_file.find('.'))
287
317
  root_element_ln = root_element.localname
288
- root_element_ns = root_element.namespace
318
+ #root_element_ns = root_element.namespace
289
319
  elements_list = []
290
320
  for elem in xml_file.findall('.//'):
291
321
  elem_path = xml_file.getelementpath(elem)
@@ -336,10 +366,10 @@ class OpexManifestGenerator():
336
366
  val = datetime.datetime.strftime(val, "%Y-%m-%dT%H:%M:%S.000Z")
337
367
  if self.metadata_flag in {'e','exact'}:
338
368
  n = path.replace(localname + ":", f"{{{ns}}}")
339
- elem = xml_new.find(f'/{n}')
369
+ elem = xml_new.find(f'./{n}')
340
370
  elif self.metadata_flag in {'f', 'flat'}:
341
371
  n = name.split(':')[-1]
342
- elem = xml_new.find(f'//{{{ns}}}{n}')
372
+ elem = xml_new.find(f'.//{{{ns}}}{n}')
343
373
  elem.text = str(val)
344
374
  except KeyError as e:
345
375
  print('Key Error: please ensure column header\'s are an exact match...')
@@ -407,6 +437,9 @@ class OpexManifestGenerator():
407
437
  if self.algorithm:
408
438
  output_path = define_output_file(self.output_path, self.root, self.meta_dir_flag, output_suffix = "_Fixities", output_format = "txt")
409
439
  export_list_txt(self.list_fixity, output_path)
440
+ if self.remove_flag:
441
+ output_path = define_output_file(self.output_path, self.root, self.meta_dir_flag, output_suffix = "_Removed", output_format = "txt")
442
+ export_list_txt(self.remove_list, output_path)
410
443
  print_running_time(self.start_time)
411
444
 
412
445
  class OpexDir(OpexManifestGenerator):
@@ -418,23 +451,35 @@ class OpexDir(OpexManifestGenerator):
418
451
  self.folder_path = folder_path.replace(u'\\\\?\\', "")
419
452
  else:
420
453
  self.folder_path = folder_path
421
- if self.OMG.autoclass_flag not in {None, "g","generic"}:
422
- index = self.OMG.index_df_lookup(self.folder_path)
454
+ if any([self.OMG.input,
455
+ self.OMG.autoclass_flag in {"c","catalog","a","accession","b","both","cg","catalog-generic","ag","accession-generic","bg","both-generic"},
456
+ self.OMG.ignore_flag,
457
+ self.OMG.remove_flag,
458
+ self.OMG.sourceid_flag,
459
+ self.OMG.title_flag,
460
+ self.OMG.description_flag,
461
+ self.OMG.security_flag]):
462
+ index = self.OMG.index_df_lookup(self.folder_path)
463
+ elif self.OMG.autoclass_flag in {None, "g","generic"}:
464
+ index = None
423
465
  else:
424
- index = None
466
+ index = None
425
467
  if self.OMG.ignore_flag or self.OMG.remove_flag:
426
468
  if self.OMG.ignore_flag:
427
469
  self.ignore = self.OMG.ignore_df_lookup(index)
428
470
  if self.ignore:
429
471
  return
472
+ else:
473
+ self.ignore = False
430
474
  if self.OMG.remove_flag:
431
- self.removal = self.OMG.remove_df_lookup(self.folder_path, index)
475
+ self.removal = self.OMG.remove_df_lookup(self.folder_path, self.OMG.remove_list, index)
432
476
  if self.removal:
433
477
  return
478
+ else:
479
+ self.removal = False
434
480
  else:
435
481
  self.ignore = False
436
482
  self.removal = False
437
-
438
483
  self.xmlroot = ET.Element(f"{{{self.opexns}}}OPEXMetadata", nsmap={"opex":self.opexns})
439
484
  self.transfer = ET.SubElement(self.xmlroot, f"{{{self.opexns}}}Transfer")
440
485
  self.manifest = ET.SubElement(self.transfer, f"{{{self.opexns}}}Manifest")
@@ -481,23 +526,29 @@ class OpexDir(OpexManifestGenerator):
481
526
  print('Failed to Filter')
482
527
  print(e)
483
528
  raise SystemError()
484
-
485
529
 
486
530
  def generate_opex_dirs(self, path: str):
487
531
  self = OpexDir(self.OMG, path)
488
532
  opex_path = os.path.join(os.path.abspath(self.folder_path), os.path.basename(self.folder_path))
489
- for f_path in self.filter_directories(path):
490
- if f_path.endswith('.opex'):
491
- pass
492
- elif os.path.isdir(f_path):
493
- if not self.ignore:
494
- self.folder = ET.SubElement(self.folders, f"{{{self.opexns}}}Folder")
495
- self.folder.text = str(os.path.basename(f_path))
496
- self.generate_opex_dirs(f_path)
497
- else:
498
- OpexFile(self.OMG, f_path, self.OMG.algorithm)
499
- if check_opex(opex_path):
500
- if not self.ignore:
533
+ if self.removal is True:
534
+ pass
535
+ else:
536
+ for f_path in self.filter_directories(path):
537
+ if f_path.endswith('.opex'):
538
+ pass
539
+ elif os.path.isdir(f_path):
540
+ if self.ignore is True:
541
+ pass
542
+ else:
543
+ self.folder = ET.SubElement(self.folders, f"{{{self.opexns}}}Folder")
544
+ self.folder.text = str(os.path.basename(f_path))
545
+ self.generate_opex_dirs(f_path)
546
+ else:
547
+ OpexFile(self.OMG, f_path, self.OMG.algorithm)
548
+ if self.removal is True or self.ignore is True:
549
+ pass
550
+ else:
551
+ if check_opex(opex_path):
501
552
  for f_path in self.filter_directories(path):
502
553
  if os.path.isfile(f_path):
503
554
  file = ET.SubElement(self.files, f"{{{self.opexns}}}File")
@@ -508,8 +559,8 @@ class OpexDir(OpexManifestGenerator):
508
559
  file.set("size", str(os.path.getsize(f_path)))
509
560
  file.text = str(os.path.basename(f_path))
510
561
  write_opex(opex_path, self.xmlroot)
511
- else:
512
- print(f"Avoiding override, Opex exists at: {opex_path}")
562
+ else:
563
+ print(f"Avoiding override, Opex exists at: {opex_path}")
513
564
 
514
565
  class OpexFile(OpexManifestGenerator):
515
566
  def __init__(self, OMG: OpexManifestGenerator, file_path: str, algorithm: str = None, title: str = None, description: str = None, security: str = None):
@@ -531,17 +582,24 @@ class OpexFile(OpexManifestGenerator):
531
582
  index = self.OMG.index_df_lookup(self.file_path)
532
583
  elif self.OMG.autoclass_flag is None or self.OMG.autoclass_flag in {"g","generic"}:
533
584
  index = None
534
- if self.OMG.ignore_flag:
535
- self.ignore = self.OMG.ignore_df_lookup(index)
536
- if self.ignore:
537
- #WTF is this?
538
- return
539
- if self.OMG.remove_flag:
540
- removal = self.OMG.remove_df_lookup(self.file_path, index)
541
- if removal:
542
- return
585
+ else:
586
+ index = None
587
+ if self.OMG.ignore_flag or self.OMG.remove_flag:
588
+ if self.OMG.ignore_flag:
589
+ self.ignore = self.OMG.ignore_df_lookup(index)
590
+ if self.ignore:
591
+ return
592
+ else:
593
+ self.ignore = False
594
+ if self.OMG.remove_flag:
595
+ self.removal = self.OMG.remove_df_lookup(self.file_path, self.OMG.remove_list, index)
596
+ if self.removal:
597
+ return
598
+ else:
599
+ self.removal = False
543
600
  else:
544
601
  self.ignore = False
602
+ self.removal = False
545
603
  self.algorithm = algorithm
546
604
  if self.OMG.title_flag or self.OMG.description_flag or self.OMG.security_flag:
547
605
  self.title, self.description, self.security = self.OMG.xip_df_lookup(index)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: opex_manifest_generator
3
- Version: 1.1.12
3
+ Version: 1.2.0
4
4
  Summary: Opex Manifest Generator Tool for use with Opex / Preservica
5
5
  Author-email: Christopher Prince <c.pj.prince@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/CPJPRINCE/opex_manifest_generator
@@ -10,8 +10,7 @@ Classifier: License :: OSI Approved :: Apache Software License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Topic :: System :: Archiving
12
12
  License-File: LICENSE.md
13
- Requires-Dist: auto-classification-generator
13
+ Requires-Dist: auto_classification_generator
14
14
  Requires-Dist: pandas
15
15
  Requires-Dist: openpyxl
16
16
  Requires-Dist: lxml
17
-
@@ -1,8 +1,8 @@
1
1
  opex_manifest_generator/__init__.py,sha256=fsN-dLjNMn-AfjeG2jkryzIa69bY09B5xLTqWedOv_w,461
2
- opex_manifest_generator/cli.py,sha256=SvSEAzVXqL-L5NgM7kd5TZ18f47-uMo90g_2zzWVJHY,10179
3
- opex_manifest_generator/common.py,sha256=dJGRQicA7B9n5WXpG5pJlV0fzO0itF6GyDXWTJ-5mxs,1782
2
+ opex_manifest_generator/cli.py,sha256=Y8oo1CZzx_AXfXmjtBbhGgn3j53t2KgeBlB-5Pc_ZZI,12030
3
+ opex_manifest_generator/common.py,sha256=vVDNlERDoI2WxEhpDYqnJC7oC9N1xQC2yxHjwuNus4Y,1895
4
4
  opex_manifest_generator/hash.py,sha256=mpLP-BqqDC7BuQQ5TEc4jaIBGabW-qVr128JaZq54mY,992
5
- opex_manifest_generator/opex_manifest.py,sha256=NkvgVR2C5QIJPq3kIcjjAURh3uaO4P2CGpEiIP76N6Q,29209
5
+ opex_manifest_generator/opex_manifest.py,sha256=VBbArkAfDRmTuf59RDS5MZtPfrW2gcMetrLNxXwnCcs,32055
6
6
  opex_manifest_generator/options.properties,sha256=UKERpUH6M6SWXbXN2XitbPd1FvT4LlCbLfoHbdWuDAQ,286
7
7
  opex_manifest_generator/metadata/DublinCore Template.xml,sha256=csNGXzSH27Whs4BQNuwMZl8nLSdDq7Y_OblTfzeBqWQ,775
8
8
  opex_manifest_generator/metadata/EAD Template.xml,sha256=OsWjUfKiLAsc1zqm56auyFSDYMuZpu6a49AFgqZNzlU,2167
@@ -14,9 +14,9 @@ opex_manifest_generator/samples/spreads/dctemplate.xlsx,sha256=R33CNcBK3s-KFYEhm
14
14
  opex_manifest_generator/samples/spreads/eadtemplate.xlsx,sha256=4lrP0LLZXwv73fl3fvqr7yqpdDJuRj2D4ZADQ4OS6Ps,19299
15
15
  opex_manifest_generator/samples/spreads/gdprtemplate.xlsx,sha256=3k6FpN6n83yF5wYd64Yy8Rxv2b1Z497icIB8UBGDW-M,18662
16
16
  opex_manifest_generator/samples/spreads/modstemplate.xlsx,sha256=5kNpp4Cju_POvnTrgFk34OJVe5yc6o3R4ZNX2TT8zAc,19509
17
- opex_manifest_generator-1.1.12.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
18
- opex_manifest_generator-1.1.12.dist-info/METADATA,sha256=3-2EQByfb-0uIK_MYB081jqy6D7jxQ7Vzj-EWNsjBIM,687
19
- opex_manifest_generator-1.1.12.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
20
- opex_manifest_generator-1.1.12.dist-info/entry_points.txt,sha256=WGMc3hWlqOsQ8DcTuy8-DyBbJKkWNImT4J1FasVDHts,70
21
- opex_manifest_generator-1.1.12.dist-info/top_level.txt,sha256=K48eGnaDLVO6YDJdAZLqbeoZvJHBGX25cvYT-i8gWt0,24
22
- opex_manifest_generator-1.1.12.dist-info/RECORD,,
17
+ opex_manifest_generator-1.2.0.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
18
+ opex_manifest_generator-1.2.0.dist-info/METADATA,sha256=1q9TcPKrkgUQMiloGdUIBH09N2DfFAVSFkxGIJ2JGeI,685
19
+ opex_manifest_generator-1.2.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
20
+ opex_manifest_generator-1.2.0.dist-info/entry_points.txt,sha256=WGMc3hWlqOsQ8DcTuy8-DyBbJKkWNImT4J1FasVDHts,70
21
+ opex_manifest_generator-1.2.0.dist-info/top_level.txt,sha256=K48eGnaDLVO6YDJdAZLqbeoZvJHBGX25cvYT-i8gWt0,24
22
+ opex_manifest_generator-1.2.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.5.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5