digitalhub 0.13.0b1__py3-none-any.whl → 0.13.0b3__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.
- digitalhub/__init__.py +1 -1
- digitalhub/context/api.py +5 -5
- digitalhub/context/builder.py +3 -5
- digitalhub/context/context.py +9 -1
- digitalhub/entities/_base/material/entity.py +3 -3
- digitalhub/entities/dataitem/crud.py +10 -2
- digitalhub/entities/dataitem/table/entity.py +3 -3
- digitalhub/entities/dataitem/utils.py +1 -2
- digitalhub/entities/task/_base/models.py +12 -3
- digitalhub/factory/factory.py +25 -3
- digitalhub/factory/utils.py +11 -3
- digitalhub/runtimes/_base.py +1 -1
- digitalhub/runtimes/builder.py +18 -1
- digitalhub/stores/client/__init__.py +12 -0
- digitalhub/stores/client/_base/api_builder.py +14 -0
- digitalhub/stores/client/_base/client.py +93 -0
- digitalhub/stores/client/_base/key_builder.py +28 -0
- digitalhub/stores/client/_base/params_builder.py +14 -0
- digitalhub/stores/client/api.py +10 -5
- digitalhub/stores/client/builder.py +3 -1
- digitalhub/stores/client/dhcore/api_builder.py +17 -0
- digitalhub/stores/client/dhcore/client.py +276 -58
- digitalhub/stores/client/dhcore/configurator.py +336 -141
- digitalhub/stores/client/dhcore/error_parser.py +35 -1
- digitalhub/stores/client/dhcore/params_builder.py +113 -17
- digitalhub/stores/client/dhcore/utils.py +32 -14
- digitalhub/stores/client/local/api_builder.py +17 -0
- digitalhub/stores/client/local/client.py +6 -8
- digitalhub/stores/credentials/api.py +8 -8
- digitalhub/stores/credentials/configurator.py +176 -3
- digitalhub/stores/credentials/enums.py +16 -3
- digitalhub/stores/credentials/handler.py +73 -45
- digitalhub/stores/credentials/ini_module.py +59 -27
- digitalhub/stores/credentials/store.py +33 -1
- digitalhub/stores/data/_base/store.py +8 -3
- digitalhub/stores/data/api.py +20 -16
- digitalhub/stores/data/builder.py +3 -9
- digitalhub/stores/data/s3/configurator.py +64 -23
- digitalhub/stores/data/s3/store.py +30 -27
- digitalhub/stores/data/s3/utils.py +9 -9
- digitalhub/stores/data/sql/configurator.py +23 -22
- digitalhub/stores/data/sql/store.py +14 -16
- digitalhub/utils/exceptions.py +6 -0
- digitalhub/utils/file_utils.py +53 -30
- digitalhub/utils/generic_utils.py +41 -33
- digitalhub/utils/git_utils.py +24 -14
- digitalhub/utils/io_utils.py +19 -18
- digitalhub/utils/uri_utils.py +31 -31
- {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/METADATA +1 -1
- {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/RECORD +53 -53
- {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/WHEEL +0 -0
- {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/licenses/AUTHORS +0 -0
- {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/licenses/LICENSE +0 -0
|
@@ -15,11 +15,10 @@ import botocore.client # pylint: disable=unused-import
|
|
|
15
15
|
from boto3.s3.transfer import TransferConfig
|
|
16
16
|
from botocore.exceptions import ClientError, NoCredentialsError
|
|
17
17
|
|
|
18
|
-
from digitalhub.stores.credentials.enums import CredsOrigin
|
|
19
18
|
from digitalhub.stores.data._base.store import Store
|
|
20
19
|
from digitalhub.stores.data.s3.utils import get_bucket_name
|
|
21
20
|
from digitalhub.stores.readers.data.api import get_reader_by_object
|
|
22
|
-
from digitalhub.utils.exceptions import StoreError
|
|
21
|
+
from digitalhub.utils.exceptions import ConfigError, StoreError
|
|
23
22
|
from digitalhub.utils.file_utils import get_file_info_from_s3, get_file_mime_type
|
|
24
23
|
from digitalhub.utils.types import SourcesOrListOfSources
|
|
25
24
|
|
|
@@ -614,55 +613,59 @@ class S3Store(Store):
|
|
|
614
613
|
"""
|
|
615
614
|
return boto3.client("s3", **cfg)
|
|
616
615
|
|
|
617
|
-
def _check_factory(self,
|
|
616
|
+
def _check_factory(self, s3_path: str, retry: bool = True) -> tuple[S3Client, str]:
|
|
618
617
|
"""
|
|
619
|
-
|
|
618
|
+
Checks if the S3 bucket collected from the URI is accessible.
|
|
619
|
+
|
|
620
|
+
Parameters
|
|
621
|
+
----------
|
|
622
|
+
s3_path : str
|
|
623
|
+
Path to the S3 bucket (e.g., 's3://bucket/path').
|
|
624
|
+
retry : bool, optional
|
|
625
|
+
Whether to retry the operation if a ConfigError is raised. Default is True.
|
|
620
626
|
|
|
621
627
|
Returns
|
|
622
628
|
-------
|
|
623
|
-
tuple
|
|
624
|
-
|
|
625
|
-
"""
|
|
626
|
-
bucket = self._get_bucket(root)
|
|
629
|
+
tuple of S3Client and str
|
|
630
|
+
Tuple containing the S3 client object and the name of the S3 bucket.
|
|
627
631
|
|
|
628
|
-
|
|
632
|
+
Raises
|
|
633
|
+
------
|
|
634
|
+
ConfigError
|
|
635
|
+
If access to the specified bucket is not available and retry is False.
|
|
636
|
+
"""
|
|
637
|
+
bucket = self._get_bucket(s3_path)
|
|
629
638
|
try:
|
|
630
|
-
cfg = self._configurator.get_client_config(
|
|
639
|
+
cfg = self._configurator.get_client_config()
|
|
631
640
|
client = self._get_client(cfg)
|
|
632
641
|
self._check_access_to_storage(client, bucket)
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
return client, bucket
|
|
642
|
+
return client, bucket
|
|
643
|
+
except ConfigError as e:
|
|
644
|
+
if retry:
|
|
645
|
+
self._configurator.eval_change_origin()
|
|
646
|
+
return self._check_factory(s3_path, False)
|
|
647
|
+
raise e
|
|
641
648
|
|
|
642
649
|
def _check_access_to_storage(self, client: S3Client, bucket: str) -> None:
|
|
643
650
|
"""
|
|
644
|
-
|
|
651
|
+
Checks if the S3 bucket is accessible by sending a head_bucket request.
|
|
645
652
|
|
|
646
653
|
Parameters
|
|
647
654
|
----------
|
|
648
655
|
client : S3Client
|
|
649
|
-
|
|
656
|
+
S3 client object.
|
|
650
657
|
bucket : str
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
Returns
|
|
654
|
-
-------
|
|
655
|
-
None
|
|
658
|
+
Name of the S3 bucket.
|
|
656
659
|
|
|
657
660
|
Raises
|
|
658
661
|
------
|
|
659
|
-
|
|
662
|
+
ConfigError
|
|
660
663
|
If access to the specified bucket is not available.
|
|
661
664
|
"""
|
|
662
665
|
try:
|
|
663
666
|
client.head_bucket(Bucket=bucket)
|
|
664
667
|
except (ClientError, NoCredentialsError) as err:
|
|
665
|
-
raise
|
|
668
|
+
raise ConfigError(f"No access to s3 bucket! Error: {err}")
|
|
666
669
|
|
|
667
670
|
@staticmethod
|
|
668
671
|
def _get_key(path: str) -> str:
|
|
@@ -16,34 +16,34 @@ from digitalhub.utils.exceptions import StoreError
|
|
|
16
16
|
|
|
17
17
|
def get_bucket_name(path: str) -> str:
|
|
18
18
|
"""
|
|
19
|
-
|
|
19
|
+
Extract the bucket name from an S3 path.
|
|
20
20
|
|
|
21
21
|
Parameters
|
|
22
22
|
----------
|
|
23
23
|
path : str
|
|
24
|
-
|
|
24
|
+
S3 URI (e.g., 's3://bucket/key').
|
|
25
25
|
|
|
26
26
|
Returns
|
|
27
27
|
-------
|
|
28
28
|
str
|
|
29
|
-
The bucket name.
|
|
29
|
+
The bucket name extracted from the URI.
|
|
30
30
|
"""
|
|
31
31
|
return urlparse(path).netloc
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
def get_bucket_and_key(path: str) -> tuple[str, str]:
|
|
35
35
|
"""
|
|
36
|
-
|
|
36
|
+
Extract the bucket name and key from an S3 path.
|
|
37
37
|
|
|
38
38
|
Parameters
|
|
39
39
|
----------
|
|
40
40
|
path : str
|
|
41
|
-
|
|
41
|
+
S3 URI (e.g., 's3://bucket/key').
|
|
42
42
|
|
|
43
43
|
Returns
|
|
44
44
|
-------
|
|
45
|
-
tuple
|
|
46
|
-
|
|
45
|
+
tuple of str
|
|
46
|
+
Tuple containing (bucket, key) extracted from the URI.
|
|
47
47
|
"""
|
|
48
48
|
parsed = urlparse(path)
|
|
49
49
|
return parsed.netloc, parsed.path
|
|
@@ -51,7 +51,7 @@ def get_bucket_and_key(path: str) -> tuple[str, str]:
|
|
|
51
51
|
|
|
52
52
|
def get_s3_source(bucket: str, key: str, filename: Path) -> None:
|
|
53
53
|
"""
|
|
54
|
-
|
|
54
|
+
Download an object from S3 and save it to a local file.
|
|
55
55
|
|
|
56
56
|
Parameters
|
|
57
57
|
----------
|
|
@@ -60,7 +60,7 @@ def get_s3_source(bucket: str, key: str, filename: Path) -> None:
|
|
|
60
60
|
key : str
|
|
61
61
|
S3 object key.
|
|
62
62
|
filename : Path
|
|
63
|
-
|
|
63
|
+
Local path where the downloaded object will be saved.
|
|
64
64
|
|
|
65
65
|
Returns
|
|
66
66
|
-------
|
|
@@ -15,18 +15,19 @@ class SqlStoreConfigurator(Configurator):
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
keys = [
|
|
18
|
-
CredsEnvVar.DB_USERNAME,
|
|
19
|
-
CredsEnvVar.DB_PASSWORD,
|
|
20
|
-
CredsEnvVar.DB_HOST,
|
|
21
|
-
CredsEnvVar.DB_PORT,
|
|
22
|
-
CredsEnvVar.DB_DATABASE,
|
|
18
|
+
CredsEnvVar.DB_USERNAME.value,
|
|
19
|
+
CredsEnvVar.DB_PASSWORD.value,
|
|
20
|
+
CredsEnvVar.DB_HOST.value,
|
|
21
|
+
CredsEnvVar.DB_PORT.value,
|
|
22
|
+
CredsEnvVar.DB_DATABASE.value,
|
|
23
|
+
CredsEnvVar.DB_PLATFORM.value,
|
|
23
24
|
]
|
|
24
25
|
required_keys = [
|
|
25
|
-
CredsEnvVar.DB_USERNAME,
|
|
26
|
-
CredsEnvVar.DB_PASSWORD,
|
|
27
|
-
CredsEnvVar.DB_HOST,
|
|
28
|
-
CredsEnvVar.DB_PORT,
|
|
29
|
-
CredsEnvVar.DB_DATABASE,
|
|
26
|
+
CredsEnvVar.DB_USERNAME.value,
|
|
27
|
+
CredsEnvVar.DB_PASSWORD.value,
|
|
28
|
+
CredsEnvVar.DB_HOST.value,
|
|
29
|
+
CredsEnvVar.DB_PORT.value,
|
|
30
|
+
CredsEnvVar.DB_DATABASE.value,
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
def __init__(self):
|
|
@@ -37,30 +38,30 @@ class SqlStoreConfigurator(Configurator):
|
|
|
37
38
|
# Configuration methods
|
|
38
39
|
##############################
|
|
39
40
|
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
def load_env_vars(self) -> None:
|
|
42
|
+
"""
|
|
43
|
+
Load the credentials from the environment.
|
|
44
|
+
"""
|
|
45
|
+
env_creds = self._creds_handler.load_from_env(self.keys)
|
|
43
46
|
self._creds_handler.set_credentials(self._env, env_creds)
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
def load_file_vars(self) -> None:
|
|
49
|
+
"""
|
|
50
|
+
Load the credentials from the file.
|
|
51
|
+
"""
|
|
52
|
+
file_creds = self._creds_handler.load_from_file(self.keys)
|
|
47
53
|
self._creds_handler.set_credentials(self._file, file_creds)
|
|
48
54
|
|
|
49
|
-
def get_sql_conn_string(self
|
|
55
|
+
def get_sql_conn_string(self) -> str:
|
|
50
56
|
"""
|
|
51
57
|
Get the connection string from environment variables.
|
|
52
58
|
|
|
53
|
-
Parameters
|
|
54
|
-
----------
|
|
55
|
-
origin : str
|
|
56
|
-
The origin of the credentials.
|
|
57
|
-
|
|
58
59
|
Returns
|
|
59
60
|
-------
|
|
60
61
|
str
|
|
61
62
|
The connection string.
|
|
62
63
|
"""
|
|
63
|
-
creds = self.get_credentials(
|
|
64
|
+
creds = self.get_credentials(self._origin)
|
|
64
65
|
user = creds[CredsEnvVar.DB_USERNAME.value]
|
|
65
66
|
password = creds[CredsEnvVar.DB_PASSWORD.value]
|
|
66
67
|
host = creds[CredsEnvVar.DB_HOST.value]
|
|
@@ -14,10 +14,9 @@ from sqlalchemy import MetaData, Table, create_engine, select
|
|
|
14
14
|
from sqlalchemy.engine import Engine
|
|
15
15
|
from sqlalchemy.exc import SQLAlchemyError
|
|
16
16
|
|
|
17
|
-
from digitalhub.stores.credentials.enums import CredsOrigin
|
|
18
17
|
from digitalhub.stores.data._base.store import Store
|
|
19
18
|
from digitalhub.stores.readers.data.api import get_reader_by_object
|
|
20
|
-
from digitalhub.utils.exceptions import StoreError
|
|
19
|
+
from digitalhub.utils.exceptions import ConfigError, StoreError
|
|
21
20
|
from digitalhub.utils.types import SourcesOrListOfSources
|
|
22
21
|
|
|
23
22
|
if typing.TYPE_CHECKING:
|
|
@@ -287,21 +286,16 @@ class SqlStore(Store):
|
|
|
287
286
|
# Helper methods
|
|
288
287
|
##############################
|
|
289
288
|
|
|
290
|
-
def _get_connection_string(self
|
|
289
|
+
def _get_connection_string(self) -> str:
|
|
291
290
|
"""
|
|
292
291
|
Get the connection string.
|
|
293
292
|
|
|
294
|
-
Parameters
|
|
295
|
-
----------
|
|
296
|
-
origin : str
|
|
297
|
-
The origin of the credentials.
|
|
298
|
-
|
|
299
293
|
Returns
|
|
300
294
|
-------
|
|
301
295
|
str
|
|
302
296
|
The connection string.
|
|
303
297
|
"""
|
|
304
|
-
return self._configurator.get_sql_conn_string(
|
|
298
|
+
return self._configurator.get_sql_conn_string()
|
|
305
299
|
|
|
306
300
|
def _get_engine(self, origin: str, schema: str | None = None) -> Engine:
|
|
307
301
|
"""
|
|
@@ -330,12 +324,14 @@ class SqlStore(Store):
|
|
|
330
324
|
except Exception as ex:
|
|
331
325
|
raise StoreError(f"Something wrong with connection string. Arguments: {str(ex.args)}")
|
|
332
326
|
|
|
333
|
-
def _check_factory(self, schema: str | None = None) -> Engine:
|
|
327
|
+
def _check_factory(self, retry: bool = True, schema: str | None = None) -> Engine:
|
|
334
328
|
"""
|
|
335
329
|
Check if the database is accessible and return the engine.
|
|
336
330
|
|
|
337
331
|
Parameters
|
|
338
332
|
----------
|
|
333
|
+
retry : bool
|
|
334
|
+
Whether to retry if the database is not accessible.
|
|
339
335
|
schema : str
|
|
340
336
|
The schema.
|
|
341
337
|
|
|
@@ -345,12 +341,14 @@ class SqlStore(Store):
|
|
|
345
341
|
The database engine.
|
|
346
342
|
"""
|
|
347
343
|
try:
|
|
348
|
-
engine = self._get_engine(
|
|
349
|
-
self._check_access_to_storage(engine)
|
|
350
|
-
except StoreError:
|
|
351
|
-
engine = self._get_engine(CredsOrigin.FILE.value, schema)
|
|
344
|
+
engine = self._get_engine(schema)
|
|
352
345
|
self._check_access_to_storage(engine)
|
|
353
|
-
|
|
346
|
+
return engine
|
|
347
|
+
except ConfigError as e:
|
|
348
|
+
if retry:
|
|
349
|
+
self._configurator.eval_change_origin()
|
|
350
|
+
return self._check_factory(retry=False, schema=schema)
|
|
351
|
+
raise e
|
|
354
352
|
|
|
355
353
|
@staticmethod
|
|
356
354
|
def _parse_path(path: str) -> dict:
|
|
@@ -435,4 +433,4 @@ class SqlStore(Store):
|
|
|
435
433
|
engine.connect()
|
|
436
434
|
except SQLAlchemyError:
|
|
437
435
|
engine.dispose()
|
|
438
|
-
raise
|
|
436
|
+
raise ConfigError("No access to db!")
|
digitalhub/utils/exceptions.py
CHANGED
digitalhub/utils/file_utils.py
CHANGED
|
@@ -16,6 +16,21 @@ from pydantic import BaseModel
|
|
|
16
16
|
class FileInfo(BaseModel):
|
|
17
17
|
"""
|
|
18
18
|
File info class.
|
|
19
|
+
|
|
20
|
+
Attributes
|
|
21
|
+
----------
|
|
22
|
+
path : str or None
|
|
23
|
+
Path to the file.
|
|
24
|
+
name : str or None
|
|
25
|
+
Name of the file.
|
|
26
|
+
content_type : str or None
|
|
27
|
+
MIME type of the file.
|
|
28
|
+
size : int or None
|
|
29
|
+
Size of the file in bytes.
|
|
30
|
+
hash : str or None
|
|
31
|
+
Hash of the file contents.
|
|
32
|
+
last_modified : str or None
|
|
33
|
+
Last modified date/time in ISO format.
|
|
19
34
|
"""
|
|
20
35
|
|
|
21
36
|
path: Optional[str] = None
|
|
@@ -25,13 +40,21 @@ class FileInfo(BaseModel):
|
|
|
25
40
|
hash: Optional[str] = None
|
|
26
41
|
last_modified: Optional[str] = None
|
|
27
42
|
|
|
28
|
-
def to_dict(self):
|
|
43
|
+
def to_dict(self) -> dict:
|
|
44
|
+
"""
|
|
45
|
+
Convert FileInfo to dictionary.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
dict
|
|
50
|
+
Dictionary representation of the FileInfo object.
|
|
51
|
+
"""
|
|
29
52
|
return self.model_dump()
|
|
30
53
|
|
|
31
54
|
|
|
32
55
|
def calculate_blob_hash(data_path: str) -> str:
|
|
33
56
|
"""
|
|
34
|
-
Calculate the hash of a file.
|
|
57
|
+
Calculate the SHA-256 hash of a file.
|
|
35
58
|
|
|
36
59
|
Parameters
|
|
37
60
|
----------
|
|
@@ -41,7 +64,7 @@ def calculate_blob_hash(data_path: str) -> str:
|
|
|
41
64
|
Returns
|
|
42
65
|
-------
|
|
43
66
|
str
|
|
44
|
-
The hash of the file.
|
|
67
|
+
The SHA-256 hash of the file, prefixed with 'sha256:'.
|
|
45
68
|
"""
|
|
46
69
|
with open(data_path, "rb") as f:
|
|
47
70
|
data = f.read()
|
|
@@ -50,7 +73,7 @@ def calculate_blob_hash(data_path: str) -> str:
|
|
|
50
73
|
|
|
51
74
|
def get_file_size(data_path: str) -> int:
|
|
52
75
|
"""
|
|
53
|
-
Get the size of a file.
|
|
76
|
+
Get the size of a file in bytes.
|
|
54
77
|
|
|
55
78
|
Parameters
|
|
56
79
|
----------
|
|
@@ -60,14 +83,14 @@ def get_file_size(data_path: str) -> int:
|
|
|
60
83
|
Returns
|
|
61
84
|
-------
|
|
62
85
|
int
|
|
63
|
-
|
|
86
|
+
Size of the file in bytes.
|
|
64
87
|
"""
|
|
65
88
|
return Path(data_path).stat().st_size
|
|
66
89
|
|
|
67
90
|
|
|
68
91
|
def get_file_mime_type(data_path: str) -> str | None:
|
|
69
92
|
"""
|
|
70
|
-
Get the
|
|
93
|
+
Get the MIME type of a file.
|
|
71
94
|
|
|
72
95
|
Parameters
|
|
73
96
|
----------
|
|
@@ -76,15 +99,15 @@ def get_file_mime_type(data_path: str) -> str | None:
|
|
|
76
99
|
|
|
77
100
|
Returns
|
|
78
101
|
-------
|
|
79
|
-
str
|
|
80
|
-
The
|
|
102
|
+
str or None
|
|
103
|
+
The MIME type of the file, or None if unknown.
|
|
81
104
|
"""
|
|
82
105
|
return guess_type(data_path)[0]
|
|
83
106
|
|
|
84
107
|
|
|
85
108
|
def get_path_name(data_path: str) -> str:
|
|
86
109
|
"""
|
|
87
|
-
Get the name of a file.
|
|
110
|
+
Get the name of a file from its path.
|
|
88
111
|
|
|
89
112
|
Parameters
|
|
90
113
|
----------
|
|
@@ -101,7 +124,7 @@ def get_path_name(data_path: str) -> str:
|
|
|
101
124
|
|
|
102
125
|
def get_last_modified(data_path: str) -> str:
|
|
103
126
|
"""
|
|
104
|
-
Get the last modified date of a file.
|
|
127
|
+
Get the last modified date/time of a file in ISO format.
|
|
105
128
|
|
|
106
129
|
Parameters
|
|
107
130
|
----------
|
|
@@ -111,7 +134,7 @@ def get_last_modified(data_path: str) -> str:
|
|
|
111
134
|
Returns
|
|
112
135
|
-------
|
|
113
136
|
str
|
|
114
|
-
The last modified date
|
|
137
|
+
The last modified date/time in ISO format.
|
|
115
138
|
"""
|
|
116
139
|
path = Path(data_path)
|
|
117
140
|
timestamp = path.stat().st_mtime
|
|
@@ -120,7 +143,7 @@ def get_last_modified(data_path: str) -> str:
|
|
|
120
143
|
|
|
121
144
|
def get_s3_path(src_path: str) -> str:
|
|
122
145
|
"""
|
|
123
|
-
Get the S3
|
|
146
|
+
Get the S3 URI of a file path.
|
|
124
147
|
|
|
125
148
|
Parameters
|
|
126
149
|
----------
|
|
@@ -130,26 +153,26 @@ def get_s3_path(src_path: str) -> str:
|
|
|
130
153
|
Returns
|
|
131
154
|
-------
|
|
132
155
|
str
|
|
133
|
-
The S3
|
|
156
|
+
The S3 URI of the file.
|
|
134
157
|
"""
|
|
135
158
|
return Path(src_path).as_uri()
|
|
136
159
|
|
|
137
160
|
|
|
138
161
|
def get_file_info_from_local(path: str, src_path: str) -> None | dict:
|
|
139
162
|
"""
|
|
140
|
-
Get file info from path.
|
|
163
|
+
Get file info from a local path.
|
|
141
164
|
|
|
142
165
|
Parameters
|
|
143
166
|
----------
|
|
144
167
|
path : str
|
|
145
168
|
Target path of the object.
|
|
146
169
|
src_path : str
|
|
147
|
-
Local path of
|
|
170
|
+
Local path of the source file.
|
|
148
171
|
|
|
149
172
|
Returns
|
|
150
173
|
-------
|
|
151
|
-
dict
|
|
152
|
-
File info.
|
|
174
|
+
dict or None
|
|
175
|
+
File info dictionary, or None if an error occurs.
|
|
153
176
|
"""
|
|
154
177
|
try:
|
|
155
178
|
name = get_path_name(path)
|
|
@@ -172,19 +195,19 @@ def get_file_info_from_local(path: str, src_path: str) -> None | dict:
|
|
|
172
195
|
|
|
173
196
|
def get_file_info_from_s3(path: str, metadata: dict) -> None | dict:
|
|
174
197
|
"""
|
|
175
|
-
Get file info from
|
|
198
|
+
Get file info from S3 metadata.
|
|
176
199
|
|
|
177
200
|
Parameters
|
|
178
201
|
----------
|
|
179
202
|
path : str
|
|
180
203
|
Object source path.
|
|
181
204
|
metadata : dict
|
|
182
|
-
Metadata of the object from S3.
|
|
205
|
+
Metadata dictionary of the object from S3.
|
|
183
206
|
|
|
184
207
|
Returns
|
|
185
208
|
-------
|
|
186
|
-
dict
|
|
187
|
-
File info.
|
|
209
|
+
dict or None
|
|
210
|
+
File info dictionary, or None if an error occurs.
|
|
188
211
|
"""
|
|
189
212
|
try:
|
|
190
213
|
size = metadata["ContentLength"]
|
|
@@ -214,17 +237,17 @@ def get_file_info_from_s3(path: str, metadata: dict) -> None | dict:
|
|
|
214
237
|
|
|
215
238
|
def eval_zip_type(source: str) -> bool:
|
|
216
239
|
"""
|
|
217
|
-
Evaluate zip
|
|
240
|
+
Evaluate whether the source is a zip file.
|
|
218
241
|
|
|
219
242
|
Parameters
|
|
220
243
|
----------
|
|
221
244
|
source : str
|
|
222
|
-
Source.
|
|
245
|
+
Source file path.
|
|
223
246
|
|
|
224
247
|
Returns
|
|
225
248
|
-------
|
|
226
249
|
bool
|
|
227
|
-
True if path is zip.
|
|
250
|
+
True if the path is a zip file, False otherwise.
|
|
228
251
|
"""
|
|
229
252
|
extension = source.endswith(".zip")
|
|
230
253
|
mime_zip = get_file_mime_type(source) == "application/zip"
|
|
@@ -233,34 +256,34 @@ def eval_zip_type(source: str) -> bool:
|
|
|
233
256
|
|
|
234
257
|
def eval_text_type(source: str) -> bool:
|
|
235
258
|
"""
|
|
236
|
-
Evaluate text
|
|
259
|
+
Evaluate whether the source is a plain text file.
|
|
237
260
|
|
|
238
261
|
Parameters
|
|
239
262
|
----------
|
|
240
263
|
source : str
|
|
241
|
-
Source.
|
|
264
|
+
Source file path.
|
|
242
265
|
|
|
243
266
|
Returns
|
|
244
267
|
-------
|
|
245
268
|
bool
|
|
246
|
-
True if path is text.
|
|
269
|
+
True if the path is a plain text file, False otherwise.
|
|
247
270
|
"""
|
|
248
271
|
return get_file_mime_type(source) == "text/plain"
|
|
249
272
|
|
|
250
273
|
|
|
251
274
|
def eval_py_type(source: str) -> bool:
|
|
252
275
|
"""
|
|
253
|
-
Evaluate
|
|
276
|
+
Evaluate whether the source is a Python file.
|
|
254
277
|
|
|
255
278
|
Parameters
|
|
256
279
|
----------
|
|
257
280
|
source : str
|
|
258
|
-
Source.
|
|
281
|
+
Source file path.
|
|
259
282
|
|
|
260
283
|
Returns
|
|
261
284
|
-------
|
|
262
285
|
bool
|
|
263
|
-
True if path is
|
|
286
|
+
True if the path is a Python file, False otherwise.
|
|
264
287
|
"""
|
|
265
288
|
extension = source.endswith(".py")
|
|
266
289
|
mime_py = get_file_mime_type(source) == "text/x-python"
|