muninn 7.0.2__tar.gz → 7.2.0__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 (68) hide show
  1. {muninn-7.0.2 → muninn-7.2.0}/CHANGES +11 -0
  2. {muninn-7.0.2 → muninn-7.2.0}/PKG-INFO +1 -1
  3. {muninn-7.0.2 → muninn-7.2.0}/muninn/__init__.py +1 -1
  4. {muninn-7.0.2 → muninn-7.2.0}/muninn/archive.py +41 -5
  5. {muninn-7.0.2 → muninn-7.2.0}/muninn/remote.py +9 -0
  6. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/pull.py +4 -0
  7. {muninn-7.0.2 → muninn-7.2.0}/muninn.egg-info/PKG-INFO +1 -1
  8. {muninn-7.0.2 → muninn-7.2.0}/setup.py +1 -1
  9. {muninn-7.0.2 → muninn-7.2.0}/DEVELOPER.md +0 -0
  10. {muninn-7.0.2 → muninn-7.2.0}/LICENSE +0 -0
  11. {muninn-7.0.2 → muninn-7.2.0}/MANIFEST.in +0 -0
  12. {muninn-7.0.2 → muninn-7.2.0}/README.md +0 -0
  13. {muninn-7.0.2 → muninn-7.2.0}/muninn/_compat.py +0 -0
  14. {muninn-7.0.2 → muninn-7.2.0}/muninn/config.py +0 -0
  15. {muninn-7.0.2 → muninn-7.2.0}/muninn/core.py +0 -0
  16. {muninn-7.0.2 → muninn-7.2.0}/muninn/database/__init__.py +0 -0
  17. {muninn-7.0.2 → muninn-7.2.0}/muninn/database/base.py +0 -0
  18. {muninn-7.0.2 → muninn-7.2.0}/muninn/database/blobgeometry.py +0 -0
  19. {muninn-7.0.2 → muninn-7.2.0}/muninn/database/ewkb.py +0 -0
  20. {muninn-7.0.2 → muninn-7.2.0}/muninn/database/postgresql.py +0 -0
  21. {muninn-7.0.2 → muninn-7.2.0}/muninn/database/sql.py +0 -0
  22. {muninn-7.0.2 → muninn-7.2.0}/muninn/database/sqlite.py +0 -0
  23. {muninn-7.0.2 → muninn-7.2.0}/muninn/enum.py +0 -0
  24. {muninn-7.0.2 → muninn-7.2.0}/muninn/exceptions.py +0 -0
  25. {muninn-7.0.2 → muninn-7.2.0}/muninn/extension.py +0 -0
  26. {muninn-7.0.2 → muninn-7.2.0}/muninn/function.py +0 -0
  27. {muninn-7.0.2 → muninn-7.2.0}/muninn/geometry.py +0 -0
  28. {muninn-7.0.2 → muninn-7.2.0}/muninn/language.py +0 -0
  29. {muninn-7.0.2 → muninn-7.2.0}/muninn/schema.py +0 -0
  30. {muninn-7.0.2 → muninn-7.2.0}/muninn/storage/__init__.py +0 -0
  31. {muninn-7.0.2 → muninn-7.2.0}/muninn/storage/base.py +0 -0
  32. {muninn-7.0.2 → muninn-7.2.0}/muninn/storage/fs.py +0 -0
  33. {muninn-7.0.2 → muninn-7.2.0}/muninn/storage/s3.py +0 -0
  34. {muninn-7.0.2 → muninn-7.2.0}/muninn/storage/swift.py +0 -0
  35. {muninn-7.0.2 → muninn-7.2.0}/muninn/struct.py +0 -0
  36. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/__init__.py +0 -0
  37. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/attach.py +0 -0
  38. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/destroy.py +0 -0
  39. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/export.py +0 -0
  40. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/hash.py +0 -0
  41. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/info.py +0 -0
  42. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/ingest.py +0 -0
  43. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/list_tags.py +0 -0
  44. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/prepare.py +0 -0
  45. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/remove.py +0 -0
  46. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/retrieve.py +0 -0
  47. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/search.py +0 -0
  48. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/strip.py +0 -0
  49. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/summary.py +0 -0
  50. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/sync.py +0 -0
  51. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/tag.py +0 -0
  52. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/untag.py +0 -0
  53. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/update.py +0 -0
  54. {muninn-7.0.2 → muninn-7.2.0}/muninn/tools/utils.py +0 -0
  55. {muninn-7.0.2 → muninn-7.2.0}/muninn/util.py +0 -0
  56. {muninn-7.0.2 → muninn-7.2.0}/muninn/visitor.py +0 -0
  57. {muninn-7.0.2 → muninn-7.2.0}/muninn.egg-info/SOURCES.txt +0 -0
  58. {muninn-7.0.2 → muninn-7.2.0}/muninn.egg-info/dependency_links.txt +0 -0
  59. {muninn-7.0.2 → muninn-7.2.0}/muninn.egg-info/entry_points.txt +0 -0
  60. {muninn-7.0.2 → muninn-7.2.0}/muninn.egg-info/top_level.txt +0 -0
  61. {muninn-7.0.2 → muninn-7.2.0}/setup.cfg +0 -0
  62. {muninn-7.0.2 → muninn-7.2.0}/test/coverage.sh +0 -0
  63. {muninn-7.0.2 → muninn-7.2.0}/test/data/README +0 -0
  64. {muninn-7.0.2 → muninn-7.2.0}/test/data/multi/1.txt +0 -0
  65. {muninn-7.0.2 → muninn-7.2.0}/test/data/multi/2.txt +0 -0
  66. {muninn-7.0.2 → muninn-7.2.0}/test/data/pi.txt +0 -0
  67. {muninn-7.0.2 → muninn-7.2.0}/test/product_type.py.template +0 -0
  68. {muninn-7.0.2 → muninn-7.2.0}/test/test.py +0 -0
@@ -1,3 +1,14 @@
1
+ 7.2.0 2025-10-29
2
+ ~~~~~~~~~~~~~~~~
3
+
4
+ * Added support for defining s3fs mappings in the muninn archive config
5
+ for mapping 'remote_url' s3 urls (mostly useful when storage=none).
6
+
7
+ 7.1.0 2025-10-20
8
+ ~~~~~~~~~~~~~~~~
9
+
10
+ * Added --update-properties option to muninn-pull.
11
+
1
12
  7.0.2 2025-10-10
2
13
  ~~~~~~~~~~~~~~~~
3
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.2
2
2
  Name: muninn
3
- Version: 7.0.2
3
+ Version: 7.2.0
4
4
  Summary: Data product catalogue and archive system
5
5
  Home-page: https://github.com/stcorp/muninn
6
6
  Author: S[&]T
@@ -4,7 +4,7 @@
4
4
 
5
5
  from __future__ import absolute_import, division, print_function
6
6
 
7
- __version__ = "7.0.2"
7
+ __version__ = "7.2.0"
8
8
  __copyright__ = "Copyright (C) 2014-2025 S[&]T, The Netherlands."
9
9
 
10
10
  __all__ = ["Error", "InternalError", "Struct", "Archive", "open", "config_path"]
@@ -245,6 +245,15 @@ class Archive(object):
245
245
 
246
246
  _register_extension(self, remote, 'muninn.remote', 'remote_backend')
247
247
 
248
+ # s3fs mappings
249
+ self.s3fs_mappings = {}
250
+ if configuration is not None and 's3fs' in configuration:
251
+ for mapping in configuration.get('s3fs').get('mappings').split(' '):
252
+ prefix, path = mapping.split('=')
253
+ if not prefix.startswith('s3://'):
254
+ raise Error("s3fs mapping '%s' does not start with an s3 url" % mapping)
255
+ self.s3fs_mappings[prefix] = path
256
+
248
257
  def __enter__(self):
249
258
  return self
250
259
 
@@ -638,8 +647,14 @@ class Archive(object):
638
647
  if self._storage is None:
639
648
  remote_url = product.core.remote_url
640
649
 
650
+ # apply s3fs mapping if applicable
651
+ for prefix in self.s3fs_mappings:
652
+ if remote_url.startswith(prefix):
653
+ remote_url = "file://" + self.s3fs_mappings[prefix] + remote_url[len(prefix):]
654
+ break
655
+
641
656
  if remote_url.startswith('file://'):
642
- product_path = product.core.remote_url[7:]
657
+ product_path = remote_url[7:]
643
658
  if os.path.isdir(product_path):
644
659
  paths = [os.path.join(product_path, basename) for basename in os.listdir(product_path)]
645
660
  else:
@@ -1315,12 +1330,16 @@ class Archive(object):
1315
1330
  product_path = self._product_path(product)
1316
1331
  return os.path.join(self._storage.global_prefix, product_path)
1317
1332
  if remote_url is not None:
1333
+ # apply s3fs mapping if applicable
1334
+ for prefix in self.s3fs_mappings:
1335
+ if remote_url.startswith(prefix):
1336
+ return self.s3fs_mappings[prefix] + remote_url[len(prefix):]
1318
1337
  if remote_url.startswith('file://'):
1319
1338
  return remote_url[7:]
1320
1339
  return remote_url
1321
1340
  return None
1322
1341
 
1323
- def pull(self, where="", parameters={}, verify_hash=False, verify_hash_download=False):
1342
+ def pull(self, where="", parameters={}, update_properties=False, verify_hash=False, verify_hash_download=False):
1324
1343
  """Pull one or more remote products into the archive.
1325
1344
 
1326
1345
  Products should have a valid remote_url core metadata field and they should not yet exist in the local
@@ -1329,6 +1348,9 @@ class Archive(object):
1329
1348
  Arguments:
1330
1349
  where -- Search expression or one or more product uuid(s) or properties.
1331
1350
  parameters -- Parameters referenced in the search expression (if any).
1351
+ update_properties -- If set to True then, after the pull, metadata and tags will be extracted from the
1352
+ product using the analyze() function of the product type plugin, and the catalog entry
1353
+ for the product will be updated with this metadata and tags.
1332
1354
  verify_hash -- If set to True then, after the pull, the product in the archive will be matched against
1333
1355
  the hash from the metadata (only if the metadata contained a hash).
1334
1356
  verify_hash_download -- If set to True then, before the product is stored in the archive, the pulled
@@ -1365,10 +1387,20 @@ class Archive(object):
1365
1387
  if len(paths) > 1 and not use_enclosing_directory:
1366
1388
  raise Error("cannot pull multi-file product without enclosing directory")
1367
1389
 
1390
+ # extract properties/tags if an update is requested
1391
+ if update_properties:
1392
+ properties, tags = self._analyze_paths(plugin, paths)
1393
+ else:
1394
+ properties = Struct({'core': Struct()})
1395
+ tags = []
1396
+ core = properties.core
1397
+
1368
1398
  # reactivate and update archive_date, size
1369
1399
  product_path = self._product_path(product)
1370
1400
  size = self._storage.size(product_path)
1371
- metadata = {'active': True, 'archive_date': self._database.server_time_utc(), 'size': size}
1401
+ core.active = True
1402
+ core.archive_date = self._database.server_time_utc()
1403
+ core.size = size
1372
1404
  if 'hash' not in product.core or product.core.hash is None:
1373
1405
  hash_type = self._plugin_hash_type(plugin)
1374
1406
  if hash_type is not None:
@@ -1376,8 +1408,12 @@ class Archive(object):
1376
1408
  hash = util.product_hash(paths, hash_type=hash_type)
1377
1409
  except EnvironmentError as _error:
1378
1410
  raise Error("cannot determine product hash [%s]" % (_error,))
1379
- metadata['hash'] = hash
1380
- self.update_properties(Struct({'core': metadata}), product.core.uuid)
1411
+ # update hash
1412
+ core.hash = hash
1413
+ self.update_properties(properties, product.core.uuid, create_namespaces=update_properties)
1414
+
1415
+ if tags:
1416
+ self._database.tag(product.core.uuid, tags)
1381
1417
 
1382
1418
  # verify product hash.
1383
1419
  if verify_hash and 'hash' in product.core:
@@ -289,6 +289,15 @@ class FTPBackend(RemoteBackend):
289
289
 
290
290
  class S3Backend(RemoteBackend):
291
291
  def pull(self, archive, product, target_dir):
292
+ # apply s3fs mapping if applicable
293
+ for prefix in archive.s3fs_mappings:
294
+ if product.core.remote_url.startswith(prefix):
295
+ source_path = archive.s3fs_mappings[prefix] + product.core.remote_url[len(prefix):]
296
+ if not os.path.exists(source_path):
297
+ raise DownloadError("s3fs path %s (for %s) does not exist" % (source_path, product.core.remote_url))
298
+ target_path = os.path.join(target_dir, os.path.basename(source_path))
299
+ util.copy_path(source_path, target_path)
300
+ return self.auto_extract(target_path, product)
292
301
  credentials = get_credentials(archive, product.core.remote_url)
293
302
  paths = download_s3(product.core.remote_url, target_dir, credentials=credentials)
294
303
  if len(paths) == 1:
@@ -15,12 +15,14 @@ class PullProcessor(Processor):
15
15
  def __init__(self, args):
16
16
  super(PullProcessor, self).__init__(args)
17
17
  self.args = args
18
+ self.update_properties = True if args.update_properties else False
18
19
  self.verify_hash = True if args.verify_hash else False
19
20
  self.verify_hash_download = True if args.verify_hash_download else False
20
21
 
21
22
  def perform_operation(self, archive, product):
22
23
  archive.pull(
23
24
  product.core.uuid,
25
+ update_properties=self.update_properties,
24
26
  verify_hash=self.verify_hash,
25
27
  verify_hash_download=self.verify_hash_download
26
28
  )
@@ -44,6 +46,8 @@ def pull(args):
44
46
 
45
47
  def main():
46
48
  parser = create_parser(description="Pull remote files into the archive.", parallel=True)
49
+ parser.add_argument("--update-properties", action="store_true",
50
+ help="update properties in catalog as if the product was ingested using muninn-ingest")
47
51
  parser.add_argument("--verify-hash", action="store_true",
48
52
  help="verify the hash of the product after it has been put in the archive")
49
53
  parser.add_argument("--verify-hash-download", action="store_true",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.2
2
2
  Name: muninn
3
- Version: 7.0.2
3
+ Version: 7.2.0
4
4
  Summary: Data product catalogue and archive system
5
5
  Home-page: https://github.com/stcorp/muninn
6
6
  Author: S[&]T
@@ -15,7 +15,7 @@ requirements = []
15
15
 
16
16
  setup(
17
17
  name="muninn",
18
- version="7.0.2",
18
+ version="7.2.0",
19
19
  description="Data product catalogue and archive system",
20
20
  url="https://github.com/stcorp/muninn",
21
21
  author="S[&]T",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes