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,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"
|