FileBackup 0.3.6__py3-none-any.whl → 0.4.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.
- FileBackup/DataStore/FastGlacierDataStore.py +7 -5
- FileBackup/DataStore/S3BrowserDataStore.py +81 -0
- FileBackup/Impl/Common.py +48 -1
- FileBackup/__init__.py +1 -1
- {FileBackup-0.3.6.dist-info → FileBackup-0.4.0.dist-info}/METADATA +9 -9
- {FileBackup-0.3.6.dist-info → FileBackup-0.4.0.dist-info}/RECORD +10 -9
- {FileBackup-0.3.6.dist-info → FileBackup-0.4.0.dist-info}/WHEEL +1 -1
- {FileBackup-0.3.6.dist-info → FileBackup-0.4.0.dist-info}/LICENSE.txt +0 -0
- {FileBackup-0.3.6.dist-info → FileBackup-0.4.0.dist-info}/entry_points.txt +0 -0
- {FileBackup-0.3.6.dist-info → FileBackup-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -70,10 +70,12 @@ class FastGlacierDataStore(BulkStorageDataStore):
|
|
|
70
70
|
)
|
|
71
71
|
return
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
command_line = f'glacier-con upload "{self.account_name}" "{local_path / "*"}" "{self.aws_region}" "{self._glacier_dir.as_posix()}"'
|
|
73
|
+
self._validated_command_line = True
|
|
75
74
|
|
|
76
|
-
|
|
75
|
+
with dm.Nested("Uploading to Fast Glacier...") as upload_dm:
|
|
76
|
+
command_line = f'glacier-con upload "{self.account_name}" "{local_path / "*"}" "{self.aws_region}" "{self._glacier_dir.as_posix()}"'
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
upload_dm.WriteVerbose(f"Command Line: {command_line}\n\n")
|
|
79
|
+
|
|
80
|
+
with upload_dm.YieldStream() as stream:
|
|
81
|
+
upload_dm.result = SubprocessEx.Stream(command_line, stream)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# ----------------------------------------------------------------------
|
|
2
|
+
# |
|
|
3
|
+
# | S3BrowserDataStore.py
|
|
4
|
+
# |
|
|
5
|
+
# | David Brownell <db@DavidBrownell.com>
|
|
6
|
+
# | 2025-02-23 14:08:12
|
|
7
|
+
# |
|
|
8
|
+
# ----------------------------------------------------------------------
|
|
9
|
+
# |
|
|
10
|
+
# | Copyright David Brownell 2025
|
|
11
|
+
# | Distributed under the MIT License.
|
|
12
|
+
# |
|
|
13
|
+
# ----------------------------------------------------------------------
|
|
14
|
+
"""Contains the S3BrowserDataStore object"""
|
|
15
|
+
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Optional
|
|
18
|
+
|
|
19
|
+
from dbrownell_Common.Streams.DoneManager import DoneManager # type: ignore[import-untyped]
|
|
20
|
+
from dbrownell_Common import SubprocessEx # type: ignore[import-untyped]
|
|
21
|
+
from dbrownell_Common.Types import override # type: ignore[import-untyped]
|
|
22
|
+
|
|
23
|
+
from FileBackup.DataStore.Interfaces.BulkStorageDataStore import BulkStorageDataStore
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ----------------------------------------------------------------------
|
|
27
|
+
class S3BrowserDataStore(BulkStorageDataStore):
|
|
28
|
+
"""Data store that uses the S3 Browser application (https://s3browser.com/)"""
|
|
29
|
+
|
|
30
|
+
# ----------------------------------------------------------------------
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
account_name: str,
|
|
34
|
+
bucket_name: str,
|
|
35
|
+
s3_dir: Optional[Path],
|
|
36
|
+
) -> None:
|
|
37
|
+
super(S3BrowserDataStore, self).__init__()
|
|
38
|
+
|
|
39
|
+
self.account_name = account_name
|
|
40
|
+
self.bucket_name = bucket_name
|
|
41
|
+
|
|
42
|
+
self._s3_dir = self.bucket_name / (s3_dir or Path())
|
|
43
|
+
|
|
44
|
+
self._validated_command_line = False
|
|
45
|
+
|
|
46
|
+
# ----------------------------------------------------------------------
|
|
47
|
+
@override
|
|
48
|
+
def ExecuteInParallel(self) -> bool:
|
|
49
|
+
return False
|
|
50
|
+
|
|
51
|
+
# ----------------------------------------------------------------------
|
|
52
|
+
@override
|
|
53
|
+
def Upload(
|
|
54
|
+
self,
|
|
55
|
+
dm: DoneManager,
|
|
56
|
+
local_path: Path,
|
|
57
|
+
) -> None:
|
|
58
|
+
if self._validated_command_line is False:
|
|
59
|
+
with dm.Nested(
|
|
60
|
+
"Validating S3 Browser on the command line...",
|
|
61
|
+
suffix="\n",
|
|
62
|
+
) as check_dm:
|
|
63
|
+
result = SubprocessEx.Run("s3browser-cli license show")
|
|
64
|
+
|
|
65
|
+
check_dm.WriteVerbose(result.output)
|
|
66
|
+
|
|
67
|
+
if result.returncode != 0:
|
|
68
|
+
check_dm.WriteError(
|
|
69
|
+
"S3 Browser is not available; please make sure it exists in the path and run the script again.\n"
|
|
70
|
+
)
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
self._validated_command_line = True
|
|
74
|
+
|
|
75
|
+
with dm.Nested("Uploading via S3 Browser...") as upload_dm:
|
|
76
|
+
command_line = f's3browser-cli file upload "{self.account_name}" "{local_path / "*"}" "{self._s3_dir.as_posix()}"'
|
|
77
|
+
|
|
78
|
+
upload_dm.WriteVerbose(f"Command Line: {command_line}\n\n")
|
|
79
|
+
|
|
80
|
+
with upload_dm.YieldStream() as stream:
|
|
81
|
+
upload_dm.result = SubprocessEx.Stream(command_line, stream)
|
FileBackup/Impl/Common.py
CHANGED
|
@@ -22,7 +22,16 @@ from contextlib import contextmanager
|
|
|
22
22
|
from dataclasses import dataclass, field
|
|
23
23
|
from enum import auto, Enum
|
|
24
24
|
from pathlib import Path
|
|
25
|
-
from typing import
|
|
25
|
+
from typing import (
|
|
26
|
+
Any,
|
|
27
|
+
Callable,
|
|
28
|
+
cast,
|
|
29
|
+
Iterable,
|
|
30
|
+
Iterator,
|
|
31
|
+
Optional,
|
|
32
|
+
Pattern,
|
|
33
|
+
TYPE_CHECKING,
|
|
34
|
+
)
|
|
26
35
|
from urllib import parse as urlparse
|
|
27
36
|
|
|
28
37
|
from dbrownell_Common import ExecuteTasks # type: ignore[import-untyped]
|
|
@@ -35,6 +44,7 @@ from FileBackup.DataStore.FastGlacierDataStore import FastGlacierDataStore
|
|
|
35
44
|
from FileBackup.DataStore.FileSystemDataStore import FileSystemDataStore
|
|
36
45
|
from FileBackup.DataStore.Interfaces.DataStore import DataStore, ItemType
|
|
37
46
|
from FileBackup.DataStore.Interfaces.FileBasedDataStore import FileBasedDataStore
|
|
47
|
+
from FileBackup.DataStore.S3BrowserDataStore import S3BrowserDataStore
|
|
38
48
|
from FileBackup.DataStore.SFTPDataStore import SFTPDataStore, SSH_PORT
|
|
39
49
|
|
|
40
50
|
if TYPE_CHECKING:
|
|
@@ -79,6 +89,22 @@ FAST_GLACIER_TEMPLATE_REGEX = re.compile(
|
|
|
79
89
|
[sep] )\/(?#
|
|
80
90
|
Posix Working Dir )(?P<working_dir>.+)(?#
|
|
81
91
|
Working Dir End ))?(?#
|
|
92
|
+
End )$(?#
|
|
93
|
+
)""",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
S3_BROWSER_TEMPLATE_REGEX = re.compile(
|
|
98
|
+
r"""(?#
|
|
99
|
+
Start )^(?#
|
|
100
|
+
Prefix )s3_browser:\/\/(?#
|
|
101
|
+
Account Name )(?P<account_name>[^@]+)(?#
|
|
102
|
+
[sep] )@(?#
|
|
103
|
+
Bucket Name )(?P<bucket_name>[^\/]+)(?#
|
|
104
|
+
Working Dir Begin )(?:(?#
|
|
105
|
+
Posix Working Dir )(?P<working_dir>.+)(?#
|
|
106
|
+
Working Dir End ))?(?#
|
|
107
|
+
End )$(?#
|
|
82
108
|
)""",
|
|
83
109
|
)
|
|
84
110
|
|
|
@@ -288,6 +314,17 @@ def GetDestinationHelp() -> str:
|
|
|
288
314
|
fast_glacier://MyFastGlacierAccount@us-west-2
|
|
289
315
|
fast_glacier://MyFastGlacierAccount@us-west-2/Glacier/Dir
|
|
290
316
|
|
|
317
|
+
S3 Browser
|
|
318
|
+
----------
|
|
319
|
+
Write content using the S3 Browser application (https://s3browser.com/).
|
|
320
|
+
|
|
321
|
+
Format:
|
|
322
|
+
s3_browser://<s3_browser_account_name>@<bucket_name>[/<working_dir>]
|
|
323
|
+
|
|
324
|
+
Examples:
|
|
325
|
+
s3_browser://MyS3BrowserAccount@MyBucket
|
|
326
|
+
s3_browser://MyS3BrowserAccount@MyBucket/A/Working/Dir
|
|
327
|
+
|
|
291
328
|
""",
|
|
292
329
|
).replace("\n", "\n\n")
|
|
293
330
|
|
|
@@ -337,6 +374,16 @@ def YieldDataStore(
|
|
|
337
374
|
)
|
|
338
375
|
return
|
|
339
376
|
|
|
377
|
+
# S3 Browser
|
|
378
|
+
s3_browser_match = S3_BROWSER_TEMPLATE_REGEX.match(destination)
|
|
379
|
+
if s3_browser_match:
|
|
380
|
+
yield S3BrowserDataStore(
|
|
381
|
+
s3_browser_match.group("account_name"),
|
|
382
|
+
s3_browser_match.group("bucket_name"),
|
|
383
|
+
Path(s3_browser_match.group("working_dir") or ""),
|
|
384
|
+
)
|
|
385
|
+
return
|
|
386
|
+
|
|
340
387
|
# Create a FileSystemDataStore instance
|
|
341
388
|
is_local_filesystem_override_value_for_testing: Optional[bool] = None
|
|
342
389
|
|
FileBackup/__init__.py
CHANGED
|
@@ -9,4 +9,4 @@
|
|
|
9
9
|
# Note that this value will be overwritten by calls to `python ../../Build.py update_version` based
|
|
10
10
|
# on changes observed in the git repository. The default value below will be used until the value
|
|
11
11
|
# here is explicitly updated by the Continuous Integration system as part of a commit.
|
|
12
|
-
__version__ = "0.
|
|
12
|
+
__version__ = "0.4.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: FileBackup
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Tool for creating and restoring file system backups.
|
|
5
5
|
Author-email: David Brownell <github@DavidBrownell.com>
|
|
6
6
|
License: MIT
|
|
@@ -28,15 +28,15 @@ Classifier: Topic :: System :: Systems Administration
|
|
|
28
28
|
Classifier: Topic :: Utilities
|
|
29
29
|
Description-Content-Type: text/markdown
|
|
30
30
|
License-File: LICENSE.txt
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist: paramiko
|
|
33
|
-
Requires-Dist: typer
|
|
31
|
+
Requires-Dist: dbrownell_Common
|
|
32
|
+
Requires-Dist: paramiko~=3.4
|
|
33
|
+
Requires-Dist: typer~=0.9
|
|
34
34
|
Provides-Extra: dev
|
|
35
|
-
Requires-Dist:
|
|
35
|
+
Requires-Dist: dbrownell_DevTools; extra == "dev"
|
|
36
36
|
Provides-Extra: package
|
|
37
|
-
Requires-Dist: build
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist: twine
|
|
37
|
+
Requires-Dist: build~=1.2; extra == "package"
|
|
38
|
+
Requires-Dist: cx_Freeze~=6.15; extra == "package"
|
|
39
|
+
Requires-Dist: twine~=5.1; extra == "package"
|
|
40
40
|
|
|
41
41
|
# FileBackup
|
|
42
42
|
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
FileBackup/Mirror.py,sha256=FA9vfvPHOJzmN__Tx09ndWMeMTSWcED52BuVfeOBuKc,23904
|
|
2
2
|
FileBackup/Offsite.py,sha256=2kK5ToJIHXIAPChtREcztp1e1L95ZJF6adIk-8d5V8g,62796
|
|
3
3
|
FileBackup/Snapshot.py,sha256=r6l35Tl75WIQALtzN81r62XNkzJiTddzuihmlSb56Aw,27336
|
|
4
|
-
FileBackup/__init__.py,sha256=
|
|
4
|
+
FileBackup/__init__.py,sha256=HCvFRVx_mOm1khMXjjxM4UX5ljGM23mVGc5wKNrJRJY,597
|
|
5
5
|
FileBackup/CommandLine/CommandLineArguments.py,sha256=79K4jVxtZ8xk1TfSJT8KIdkqZFjCEAspoIKP21GUXxE,2410
|
|
6
6
|
FileBackup/CommandLine/EntryPoint.py,sha256=Fn62wtKV6uiTJ1dQpolNFUyWWeUOKKgetOFSXPgoe-w,1813
|
|
7
7
|
FileBackup/CommandLine/MirrorEntryPoint.py,sha256=ZQ3mz0AgBwwn7n9uOuxN-lEQvm22u8SQbpWASkvRsAA,6800
|
|
8
8
|
FileBackup/CommandLine/OffsiteEntryPoint.py,sha256=enbgeD_nhdR2T6UufySt33f4P2FnOVzsHiEktyVtLlo,12528
|
|
9
9
|
FileBackup/CommandLine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
FileBackup/DataStore/FastGlacierDataStore.py,sha256=
|
|
10
|
+
FileBackup/DataStore/FastGlacierDataStore.py,sha256=5J4W9FqB92hnHoRoZLo-DfMQ6uyjaOAWWrnuc0pvnJo,3017
|
|
11
11
|
FileBackup/DataStore/FileSystemDataStore.py,sha256=XUvIQe2Yl-W6OPfvsJlPzDPsGclDOkKlozO0GJ-05bo,6791
|
|
12
|
+
FileBackup/DataStore/S3BrowserDataStore.py,sha256=3NHl-advSbyXuL1kDu1wswbcAZbhmAGDu8yzlOuY5Us,2954
|
|
12
13
|
FileBackup/DataStore/SFTPDataStore.py,sha256=TKz-hwwHg4avxKHDFRRz7FlKx3d40wT15ug1gCpu6VU,11374
|
|
13
14
|
FileBackup/DataStore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
15
|
FileBackup/DataStore/Interfaces/BulkStorageDataStore.py,sha256=qZo92nPDP_aVTxlohsc1ySnU9Skgxgo7Mj_tT0KxFZ8,1310
|
|
15
16
|
FileBackup/DataStore/Interfaces/DataStore.py,sha256=FpQmxoqBS5indJYRxibkSXHTgk7U6HFyViI0BDqCcVw,1169
|
|
16
17
|
FileBackup/DataStore/Interfaces/FileBasedDataStore.py,sha256=eMA_cQ-CED83z5uMDQZ18UFzBRvaXOwWz67kVu-2ftM,5307
|
|
17
18
|
FileBackup/DataStore/Interfaces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
FileBackup/Impl/Common.py,sha256=
|
|
19
|
+
FileBackup/Impl/Common.py,sha256=L444spBwjUULSQcAGYV-90dHRFNgglC7k962NshpIJ8,25261
|
|
19
20
|
FileBackup/Impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
FileBackup-0.
|
|
21
|
-
FileBackup-0.
|
|
22
|
-
FileBackup-0.
|
|
23
|
-
FileBackup-0.
|
|
24
|
-
FileBackup-0.
|
|
25
|
-
FileBackup-0.
|
|
21
|
+
FileBackup-0.4.0.dist-info/LICENSE.txt,sha256=6ycKI8SWG920Saey4PGi5YUVLX0C_8hfqJr7Q0sqGI8,1071
|
|
22
|
+
FileBackup-0.4.0.dist-info/METADATA,sha256=QemMImLG2dvbvLt8t68rCA9YxYwWIdjtoL6cSTpkwo0,3291
|
|
23
|
+
FileBackup-0.4.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
24
|
+
FileBackup-0.4.0.dist-info/entry_points.txt,sha256=OlHrvdhWJQGIp4vCUJAqOWxW7y0ZH59qQ-2ImWFUcPI,69
|
|
25
|
+
FileBackup-0.4.0.dist-info/top_level.txt,sha256=mXd2b6GEOpQCnmzgYEb6c_rfwlgP3RgmMuVDkQasxKw,11
|
|
26
|
+
FileBackup-0.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|