mantis-catalog 0.1.2__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.
@@ -0,0 +1,19 @@
1
+ Metadata-Version: 2.1
2
+ Name: mantis-catalog
3
+ Version: 0.1.2
4
+ Summary: M&NTIS library to manipulate catalog of resources
5
+ License: MIT
6
+ Author: AMOSSYS
7
+ Requires-Python: >=3.10,<4.0
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Requires-Dist: fsspec[s3]
15
+ Requires-Dist: omegaconf
16
+ Requires-Dist: universal-pathlib (>=0.2.6,<0.3.0)
17
+ Description-Content-Type: text/markdown
18
+
19
+
File without changes
@@ -0,0 +1,3 @@
1
+ # -*- coding: utf-8 -*-
2
+ # flake8: noqa
3
+ from mantis_catalog.path import *
@@ -0,0 +1,67 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (c) 2016-2025 AMOSSYS. All rights reserved.
4
+ #
5
+ # This file is part of Cyber Range AMOSSYS.
6
+ #
7
+ # Cyber Range AMOSSYS can not be copied and/or distributed without the express
8
+ # permission of AMOSSYS.
9
+ #
10
+ #
11
+ import enum
12
+ from dataclasses import dataclass
13
+ from dataclasses import field
14
+ from pathlib import Path
15
+ from typing import Dict
16
+ from typing import Optional
17
+
18
+ from omegaconf import OmegaConf
19
+ from omegaconf import SI
20
+
21
+
22
+ class StorageType(enum.Enum):
23
+ local = 1
24
+ s3 = 2
25
+
26
+
27
+ @dataclass
28
+ class BaseStorageConfig:
29
+ """Generic storage config dataclass"""
30
+
31
+
32
+ @dataclass
33
+ class LocalStorageConfig(BaseStorageConfig):
34
+ path: Path = SI("${oc.env:CATALOG_STORAGE_LOCAL_PATH}")
35
+
36
+
37
+ @dataclass
38
+ class S3StorageConfig(BaseStorageConfig):
39
+ access_key: Optional[str] = SI("${oc.env:CATALOG_STORAGE_S3_ACCESS_KEY,null}")
40
+ secret_key: Optional[str] = SI("${oc.env:CATALOG_STORAGE_S3_SECRET_KEY,null}")
41
+ endpoint_url: Optional[str] = SI("${oc.env:CATALOG_STORAGE_S3_ENDPOINT_URL,null}")
42
+ bucket_name: str = "${oc.env:CATALOG_STORAGE_S3_BUCKET_NAME}"
43
+ region: Optional[str] = SI("${oc.env:CATALOG_STORAGE_S3_REGION,null}")
44
+
45
+
46
+ @dataclass
47
+ class StorageConfig:
48
+ """Generic storage config dataclass"""
49
+
50
+ _backends: Dict[StorageType, BaseStorageConfig] = field(
51
+ default_factory=lambda: {
52
+ StorageType.local: LocalStorageConfig(),
53
+ StorageType.s3: S3StorageConfig(),
54
+ }
55
+ )
56
+ _type_name: str = "${.type}"
57
+ backend: BaseStorageConfig = SI("${._backends[${._type_name}]}")
58
+ type: StorageType = SI("${oc.env:CATALOG_STORAGE_TYPE,local}")
59
+ path_prefix: str = "${oc.env:CATALOG_STORAGE_PATH_PREFIX,''}"
60
+
61
+
62
+ @dataclass
63
+ class CatalogConfig:
64
+ storage: StorageConfig = field(default_factory=StorageConfig)
65
+
66
+
67
+ catalog_config = OmegaConf.structured(CatalogConfig)
@@ -0,0 +1,76 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ from pathlib import Path
4
+
5
+ from mantis_catalog.config import catalog_config
6
+ from mantis_catalog.config import StorageType
7
+ from upath import UPath
8
+ from upath.registry import register_implementation
9
+
10
+
11
+ class ResourcePath(UPath):
12
+ def __init__(self, *args, **kwargs):
13
+ storage_backend = catalog_config.storage.backend
14
+ match catalog_config.storage.type:
15
+ case StorageType.local:
16
+ path = UPath(storage_backend.path, protocol="local")
17
+ case StorageType.s3:
18
+ path = UPath(
19
+ "s3://",
20
+ endpoint_url=storage_backend.endpoint_url,
21
+ key=storage_backend.access_key,
22
+ secret=storage_backend.secret_key,
23
+ bucket=storage_backend.bucket_name,
24
+ )
25
+ case _:
26
+ raise ValueError("Invalid storage backend type")
27
+ self.__path = path
28
+ super().__init__(*args, **kwargs)
29
+ self._fs_cached = path.fs
30
+
31
+ @property
32
+ def abstract_path(self):
33
+ return super().path
34
+
35
+ @property
36
+ def path(self):
37
+ # concatenate internal and external paths
38
+ path = os.path.relpath(super().path, self.root)
39
+ path = os.path.join(self.__path.path, path)
40
+ return os.path.normpath(path)
41
+
42
+ def __str__(self):
43
+ # get the abstract path
44
+ path = super().path
45
+ if self._protocol:
46
+ return f"{self._protocol}://{path}"
47
+ else:
48
+ return path
49
+
50
+
51
+ def copytree_path(source: Path, dest: Path):
52
+ """Copy a file tree with Path compatibility. If 'dest' does not
53
+ exist, it is created.
54
+
55
+ :param source: dir to copy from (objet Path).
56
+ :param dest: dir to copy to (objet Path).
57
+
58
+ """
59
+
60
+ dest.mkdir(parents=True, exist_ok=True)
61
+
62
+ for item in source.iterdir():
63
+ if item.is_dir():
64
+ copytree_path(item, dest / item.name)
65
+ else:
66
+ with item.open('rb') as src_file:
67
+ with (dest / item.name).open('wb') as dst_file:
68
+ dst_file.write(src_file.read())
69
+
70
+
71
+ register_implementation("resource", ResourcePath)
72
+
73
+ __all__ = [
74
+ "ResourcePath",
75
+ "UPath",
76
+ ]
@@ -0,0 +1,25 @@
1
+ [tool.poetry]
2
+ name = "mantis-catalog"
3
+ version = "0.1.2"
4
+ description = "M&NTIS library to manipulate catalog of resources"
5
+ readme = "README.md"
6
+ authors = ["AMOSSYS"]
7
+ license = "MIT"
8
+
9
+ [tool.poetry.dependencies]
10
+ python = "^3.10"
11
+ universal-pathlib = "^0.2.6"
12
+ fsspec = {extras = ["s3"], version = "*"}
13
+ omegaconf = "*"
14
+
15
+
16
+ [tool.poetry.group.dev.dependencies]
17
+ mypy = "*"
18
+ flake8 = "*"
19
+ coverage = "*"
20
+ pytest = "*"
21
+ black = "*"
22
+
23
+ [build-system]
24
+ requires = ["poetry-core"]
25
+ build-backend = "poetry.core.masonry.api"