PyS3Uploader 0.2.4a0__py3-none-any.whl → 0.3.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.
Potentially problematic release.
This version of PyS3Uploader might be problematic. Click here for more details.
- pys3uploader/__init__.py +4 -0
- pys3uploader/logger.py +100 -0
- {s3 → pys3uploader}/uploader.py +14 -10
- {pys3uploader-0.2.4a0.dist-info → pys3uploader-0.3.0.dist-info}/METADATA +8 -6
- pys3uploader-0.3.0.dist-info/RECORD +11 -0
- pys3uploader-0.3.0.dist-info/top_level.txt +1 -0
- pys3uploader-0.2.4a0.dist-info/RECORD +0 -11
- pys3uploader-0.2.4a0.dist-info/top_level.txt +0 -1
- s3/__init__.py +0 -3
- s3/logger.py +0 -45
- {s3 → pys3uploader}/exceptions.py +0 -0
- {s3 → pys3uploader}/tree.py +0 -0
- {s3 → pys3uploader}/utils.py +0 -0
- {pys3uploader-0.2.4a0.dist-info → pys3uploader-0.3.0.dist-info}/LICENSE +0 -0
- {pys3uploader-0.2.4a0.dist-info → pys3uploader-0.3.0.dist-info}/WHEEL +0 -0
pys3uploader/__init__.py
ADDED
pys3uploader/logger.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Loads a default logger with StreamHandler set to DEBUG mode.
|
|
2
|
+
|
|
3
|
+
>>> logging.Logger
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from enum import IntEnum, StrEnum
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LogHandler(StrEnum):
|
|
14
|
+
"""Logging handlers to choose from when default logger is used.
|
|
15
|
+
|
|
16
|
+
>>> LogHandler
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
file = "file"
|
|
21
|
+
stdout = "stdout"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class LogLevel(IntEnum):
|
|
25
|
+
"""Logging levels to choose from when default logger is used.
|
|
26
|
+
|
|
27
|
+
>>> LogLevel
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
debug = logging.DEBUG
|
|
32
|
+
info = logging.INFO
|
|
33
|
+
warning = logging.WARNING
|
|
34
|
+
error = logging.ERROR
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def _missing_(cls, value):
|
|
38
|
+
"""Allow constructing from string names."""
|
|
39
|
+
if isinstance(value, str):
|
|
40
|
+
value = value.lower()
|
|
41
|
+
for member in cls:
|
|
42
|
+
if member.name == value:
|
|
43
|
+
return member
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def stream_handler() -> logging.StreamHandler:
|
|
48
|
+
"""Creates a ``StreamHandler`` and assigns a default format to it.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
logging.StreamHandler:
|
|
52
|
+
Returns an instance of the ``StreamHandler`` object.
|
|
53
|
+
"""
|
|
54
|
+
handler = logging.StreamHandler()
|
|
55
|
+
handler.setFormatter(fmt=default_format())
|
|
56
|
+
return handler
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def file_handler() -> logging.FileHandler:
|
|
60
|
+
"""Creates a ``StreamHandler`` and assigns a default format to it.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
logging.StreamHandler:
|
|
64
|
+
Returns an instance of the ``StreamHandler`` object.
|
|
65
|
+
"""
|
|
66
|
+
os.makedirs("logs", exist_ok=True)
|
|
67
|
+
filename = os.path.join("logs", datetime.now().strftime("PyS3Uploader_%d-%m-%Y_%H:%M.log"))
|
|
68
|
+
handler = logging.FileHandler(filename, mode="a")
|
|
69
|
+
handler.setFormatter(fmt=default_format())
|
|
70
|
+
return handler
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def default_format() -> logging.Formatter:
|
|
74
|
+
"""Creates a logging ``Formatter`` with a custom message and datetime format.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
logging.Formatter:
|
|
78
|
+
Returns an instance of the ``Formatter`` object.
|
|
79
|
+
"""
|
|
80
|
+
return logging.Formatter(
|
|
81
|
+
fmt="%(asctime)s - %(levelname)s - [%(module)s:%(lineno)d] - %(funcName)s - %(message)s",
|
|
82
|
+
datefmt="%b-%d-%Y %I:%M:%S %p",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def setup_logger(handler: LogHandler, level: LogLevel):
|
|
87
|
+
"""Creates a default logger with debug mode enabled.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
logging.Logger:
|
|
91
|
+
Returns an instance of the ``Logger`` object.
|
|
92
|
+
"""
|
|
93
|
+
logger = logging.getLogger(__name__)
|
|
94
|
+
if handler == LogHandler.file:
|
|
95
|
+
logger.addHandler(hdlr=file_handler())
|
|
96
|
+
elif handler == LogHandler.stdout:
|
|
97
|
+
logger.addHandler(hdlr=stream_handler())
|
|
98
|
+
|
|
99
|
+
logger.setLevel(level)
|
|
100
|
+
return logger
|
{s3 → pys3uploader}/uploader.py
RENAMED
|
@@ -10,9 +10,9 @@ from botocore.config import Config
|
|
|
10
10
|
from botocore.exceptions import ClientError
|
|
11
11
|
from tqdm import tqdm
|
|
12
12
|
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
13
|
+
from pys3uploader.exceptions import BucketNotFound
|
|
14
|
+
from pys3uploader.logger import LogHandler, LogLevel, setup_logger
|
|
15
|
+
from pys3uploader.utils import (
|
|
16
16
|
RETRY_CONFIG,
|
|
17
17
|
UploadResults,
|
|
18
18
|
convert_seconds,
|
|
@@ -45,6 +45,8 @@ class Uploader:
|
|
|
45
45
|
aws_secret_access_key: str = None,
|
|
46
46
|
retry_config: Config = RETRY_CONFIG,
|
|
47
47
|
logger: logging.Logger = None,
|
|
48
|
+
log_handler: LogHandler = LogHandler.stdout,
|
|
49
|
+
log_level: LogLevel = LogLevel.debug,
|
|
48
50
|
env_file: str = None,
|
|
49
51
|
):
|
|
50
52
|
"""Initiates all the necessary args and creates a boto3 session with retry logic.
|
|
@@ -63,6 +65,8 @@ class Uploader:
|
|
|
63
65
|
aws_access_key_id: AWS access key ID.
|
|
64
66
|
aws_secret_access_key: AWS secret access key.
|
|
65
67
|
logger: Bring your own logger.
|
|
68
|
+
log_handler: Default log handler, can be ``file`` or ``stdout``.
|
|
69
|
+
log_level: Default log level, can be ``debug``, ``info``, ``warning`` or ``error``.
|
|
66
70
|
env_file: Dotenv file (.env) filepath to load environment variables.
|
|
67
71
|
|
|
68
72
|
See Also:
|
|
@@ -85,7 +89,7 @@ class Uploader:
|
|
|
85
89
|
If a filepath is provided, PyS3Uploader loads it directly or searches the root directory for the file.
|
|
86
90
|
If no filepath is provided, PyS3Uploader searches the current directory for a .env file.
|
|
87
91
|
"""
|
|
88
|
-
self.logger = logger or
|
|
92
|
+
self.logger = logger or setup_logger(handler=LogHandler(log_handler), level=LogLevel(log_level))
|
|
89
93
|
self.env_file = env_file or getenv("ENV_FILE", default=".env")
|
|
90
94
|
|
|
91
95
|
# Check for env_file in current working directory
|
|
@@ -184,13 +188,13 @@ class Uploader:
|
|
|
184
188
|
"""
|
|
185
189
|
if self.overwrite:
|
|
186
190
|
return True
|
|
191
|
+
try:
|
|
192
|
+
file_size = os.path.getsize(filepath)
|
|
193
|
+
except (OSError, PermissionError) as error:
|
|
194
|
+
self.logger.error(error)
|
|
195
|
+
file_size = 0
|
|
187
196
|
# Indicates that the object path already exists in S3
|
|
188
197
|
if object_size := self.object_size_map.get(objectpath):
|
|
189
|
-
try:
|
|
190
|
-
file_size = os.path.getsize(filepath)
|
|
191
|
-
except (OSError, PermissionError) as error:
|
|
192
|
-
self.logger.error(error)
|
|
193
|
-
return True
|
|
194
198
|
if object_size == file_size:
|
|
195
199
|
self.logger.info("S3 object %s exists, and size [%d] matches, skipping..", objectpath, object_size)
|
|
196
200
|
return False
|
|
@@ -198,7 +202,7 @@ class Uploader:
|
|
|
198
202
|
"S3 object %s exists, but size mismatch. Local: [%d], S3: [%d]", objectpath, file_size, object_size
|
|
199
203
|
)
|
|
200
204
|
else:
|
|
201
|
-
self.logger.debug("S3 object '%s' doesn't exist, uploading..", objectpath)
|
|
205
|
+
self.logger.debug("S3 object '%s' of size [%d bytes] doesn't exist, uploading..", objectpath, file_size)
|
|
202
206
|
return True
|
|
203
207
|
|
|
204
208
|
def _uploader(self, filepath: str, objectpath: str) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: PyS3Uploader
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Python module to upload objects to an S3 bucket.
|
|
5
5
|
Author-email: Vignesh Rao <svignesh1793@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -29,7 +29,7 @@ Project-URL: Homepage, https://github.com/thevickypedia/PyS3Uploader
|
|
|
29
29
|
Project-URL: Docs, https://thevickypedia.github.io/PyS3Uploader/
|
|
30
30
|
Project-URL: Source, https://github.com/thevickypedia/PyS3Uploader
|
|
31
31
|
Project-URL: Bug Tracker, https://github.com/thevickypedia/PyS3Uploader/issues
|
|
32
|
-
Keywords:
|
|
32
|
+
Keywords: pys3uploader
|
|
33
33
|
Classifier: Development Status :: 1 - Planning
|
|
34
34
|
Classifier: Intended Audience :: Information Technology
|
|
35
35
|
Classifier: Operating System :: OS Independent
|
|
@@ -85,10 +85,10 @@ pip install PyS3Uploader
|
|
|
85
85
|
|
|
86
86
|
##### Upload objects in parallel
|
|
87
87
|
```python
|
|
88
|
-
import
|
|
88
|
+
import pys3uploader
|
|
89
89
|
|
|
90
90
|
if __name__ == '__main__':
|
|
91
|
-
wrapper =
|
|
91
|
+
wrapper = pys3uploader.Uploader(
|
|
92
92
|
bucket_name="BUCKET_NAME",
|
|
93
93
|
upload_dir="FULL_PATH_TO_UPLOAD",
|
|
94
94
|
exclude_prefix="PART_OF_UPLOAD_DIR_TO_EXCLUDE"
|
|
@@ -98,10 +98,10 @@ if __name__ == '__main__':
|
|
|
98
98
|
|
|
99
99
|
##### Upload objects in sequence
|
|
100
100
|
```python
|
|
101
|
-
import
|
|
101
|
+
import pys3uploader
|
|
102
102
|
|
|
103
103
|
if __name__ == '__main__':
|
|
104
|
-
wrapper =
|
|
104
|
+
wrapper = pys3uploader.Uploader(
|
|
105
105
|
bucket_name="BUCKET_NAME",
|
|
106
106
|
upload_dir="FULL_PATH_TO_UPLOAD",
|
|
107
107
|
exclude_prefix="PART_OF_UPLOAD_DIR_TO_EXCLUDE"
|
|
@@ -121,6 +121,8 @@ if __name__ == '__main__':
|
|
|
121
121
|
- **file_exclusion** - Sequence of files to exclude during upload. Defaults to ``None``
|
|
122
122
|
- **folder_exclusion** - Sequence of directories to exclude during upload. Defaults to ``None``
|
|
123
123
|
- **logger** - Bring your own custom pre-configured logger. Defaults to on-screen logging.
|
|
124
|
+
- **log_handler** - Choose between `stdout` vs `file` logging. Defaults to `pys3uploader.LogHandler.stdout`
|
|
125
|
+
- **log_level** - Choose the logging level. Defaults to `pys3uploader.LogLevel.debug`
|
|
124
126
|
- **env_file** – Path to a `.env` file for loading environment variables. Defaults to scanning the current directory.
|
|
125
127
|
<br><br>
|
|
126
128
|
- **region_name** - AWS region name. Defaults to the env var `AWS_DEFAULT_REGION`
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
pys3uploader/__init__.py,sha256=QszR24KVfcJXbrJI0oxZCIaMs5GOtwnIbtfrY2Zj7Nk,143
|
|
2
|
+
pys3uploader/exceptions.py,sha256=hH3jlMOe8yjBatQK9EdndWZz4QESU74KSY_iDhQ37SY,2585
|
|
3
|
+
pys3uploader/logger.py,sha256=igwMubdTQ_GrMkwie5DAIvmxIcgj6a9UA_EGFrwFYiQ,2571
|
|
4
|
+
pys3uploader/tree.py,sha256=DiQ2ekMMaj2m_P3-iKkEqSuJCJZ_UZxcAwHtAoPVa5c,1824
|
|
5
|
+
pys3uploader/uploader.py,sha256=-PRwu2RvzExjLTKbw9oQuFcyNI0Uxi1IsoJu6e6wayY,14258
|
|
6
|
+
pys3uploader/utils.py,sha256=NbF28CYviK_St5qd1EOumMVyus9BvQON7clUFeR_SEQ,4473
|
|
7
|
+
pys3uploader-0.3.0.dist-info/LICENSE,sha256=8k-hEraOzyum0GvmmK65YxNRTFXK7eIFHJ0OshJXeTk,1068
|
|
8
|
+
pys3uploader-0.3.0.dist-info/METADATA,sha256=0eS5eoAsatnmMi_wanq_kzHTZGVTvwo2c4pR_CIa3T4,8039
|
|
9
|
+
pys3uploader-0.3.0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
|
|
10
|
+
pys3uploader-0.3.0.dist-info/top_level.txt,sha256=lVIFMMoUx7dj_myetBmOUQTJiOzz5VyDqchnQElmrWw,13
|
|
11
|
+
pys3uploader-0.3.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pys3uploader
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
s3/__init__.py,sha256=qPNHkWhXCMoofZe0kidyKkQ8YX3Ke0U35ViBo-oEWp0,68
|
|
2
|
-
s3/exceptions.py,sha256=hH3jlMOe8yjBatQK9EdndWZz4QESU74KSY_iDhQ37SY,2585
|
|
3
|
-
s3/logger.py,sha256=oH540oq8jY723jA4lDWlgfFPLbNgGXTkDwFpB7TLO_o,1196
|
|
4
|
-
s3/tree.py,sha256=DiQ2ekMMaj2m_P3-iKkEqSuJCJZ_UZxcAwHtAoPVa5c,1824
|
|
5
|
-
s3/uploader.py,sha256=VZOajOlWLWU-E34qS40YH8VUH_RCoiVvIOUP3kSzyMA,13868
|
|
6
|
-
s3/utils.py,sha256=NbF28CYviK_St5qd1EOumMVyus9BvQON7clUFeR_SEQ,4473
|
|
7
|
-
pys3uploader-0.2.4a0.dist-info/LICENSE,sha256=8k-hEraOzyum0GvmmK65YxNRTFXK7eIFHJ0OshJXeTk,1068
|
|
8
|
-
pys3uploader-0.2.4a0.dist-info/METADATA,sha256=LCV-hgBLudyY3q9dq5E2sg63OnapaoEYv2ggUqDsc7I,7797
|
|
9
|
-
pys3uploader-0.2.4a0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
|
|
10
|
-
pys3uploader-0.2.4a0.dist-info/top_level.txt,sha256=iQp4y1P58Q633gj8M08kHE4mqqT0hixuDWcniDk_RJ4,3
|
|
11
|
-
pys3uploader-0.2.4a0.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
s3
|
s3/__init__.py
DELETED
s3/logger.py
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"""Loads a default logger with StreamHandler set to DEBUG mode.
|
|
2
|
-
|
|
3
|
-
>>> logging.Logger
|
|
4
|
-
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import logging
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def default_handler() -> logging.StreamHandler:
|
|
11
|
-
"""Creates a ``StreamHandler`` and assigns a default format to it.
|
|
12
|
-
|
|
13
|
-
Returns:
|
|
14
|
-
logging.StreamHandler:
|
|
15
|
-
Returns an instance of the ``StreamHandler`` object.
|
|
16
|
-
"""
|
|
17
|
-
handler = logging.StreamHandler()
|
|
18
|
-
handler.setFormatter(fmt=default_format())
|
|
19
|
-
return handler
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def default_format() -> logging.Formatter:
|
|
23
|
-
"""Creates a logging ``Formatter`` with a custom message and datetime format.
|
|
24
|
-
|
|
25
|
-
Returns:
|
|
26
|
-
logging.Formatter:
|
|
27
|
-
Returns an instance of the ``Formatter`` object.
|
|
28
|
-
"""
|
|
29
|
-
return logging.Formatter(
|
|
30
|
-
fmt="%(asctime)s - %(levelname)s - [%(module)s:%(lineno)d] - %(funcName)s - %(message)s",
|
|
31
|
-
datefmt="%b-%d-%Y %I:%M:%S %p",
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def default_logger() -> logging.Logger:
|
|
36
|
-
"""Creates a default logger with debug mode enabled.
|
|
37
|
-
|
|
38
|
-
Returns:
|
|
39
|
-
logging.Logger:
|
|
40
|
-
Returns an instance of the ``Logger`` object.
|
|
41
|
-
"""
|
|
42
|
-
logger = logging.getLogger(__name__)
|
|
43
|
-
logger.addHandler(hdlr=default_handler())
|
|
44
|
-
logger.setLevel(level=logging.DEBUG)
|
|
45
|
-
return logger
|
|
File without changes
|
{s3 → pys3uploader}/tree.py
RENAMED
|
File without changes
|
{s3 → pys3uploader}/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|