fallbacks3 0.1.0__tar.gz → 0.2.0__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.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fallbacks3
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: S3-compatible storage library with automatic fallback support
5
5
  Author-email: Mila de Oliveira <mila.oliveira@palver.com.br>
6
6
  Project-URL: Homepage, https://github.com/palverdata/fallbacks3
7
7
  Project-URL: Repository, https://github.com/palverdata/fallbacks3
8
8
  Project-URL: Issues, https://github.com/palverdata/fallbacks3/issues
9
- Requires-Python: >=3.8
9
+ Requires-Python: >=3.9
10
10
  Description-Content-Type: text/markdown
11
11
  Requires-Dist: boto3>=1.26.0
12
12
  Requires-Dist: pydantic-settings>=2.0.0
@@ -85,6 +85,12 @@ stored_file_uri = storage.upload_file(
85
85
  )
86
86
  print(uri) # "ps3://palver-whatsapp/audio.mp3"
87
87
 
88
+ # Async upload (for async environments)
89
+ stored_file_uri = await storage.upload_file_async(
90
+ remote_file_uri="ps3://palver-whatsapp/audio.mp3",
91
+ local_file_path="/local/path/audio.mp3"
92
+ )
93
+
88
94
  # Download a file
89
95
  downloaded_file_path = storage.download_file(
90
96
  remote_file_uri="ps3://palver-whatsapp/audio.mp3",
@@ -115,6 +121,28 @@ stored_file_path = storage.upload_file(
115
121
 
116
122
  Raises an exception if both primary and fallback providers fail.
117
123
 
124
+ #### Async Upload
125
+
126
+ For async environments, use `upload_file_async()`:
127
+
128
+ ```python
129
+ import asyncio
130
+ from fallbacks3 import Storage
131
+
132
+ storage = Storage()
133
+
134
+ async def upload():
135
+ stored_file_uri = await storage.upload_file_async(
136
+ remote_file_uri="ps3://palver-whatsapp/audio.mp3",
137
+ local_file_path="/local/path/audio.mp3"
138
+ )
139
+ print(stored_file_uri) # "ps3://palver-whatsapp/audio.mp3"
140
+
141
+ asyncio.run(upload())
142
+ ```
143
+
144
+ The async method also supports automatic fallback, just like the synchronous version.
145
+
118
146
  ### Download and Signed URLs
119
147
 
120
148
  Download and signed URL generation use the provider specified in the remote file URI.
@@ -64,6 +64,12 @@ stored_file_uri = storage.upload_file(
64
64
  )
65
65
  print(uri) # "ps3://palver-whatsapp/audio.mp3"
66
66
 
67
+ # Async upload (for async environments)
68
+ stored_file_uri = await storage.upload_file_async(
69
+ remote_file_uri="ps3://palver-whatsapp/audio.mp3",
70
+ local_file_path="/local/path/audio.mp3"
71
+ )
72
+
67
73
  # Download a file
68
74
  downloaded_file_path = storage.download_file(
69
75
  remote_file_uri="ps3://palver-whatsapp/audio.mp3",
@@ -94,6 +100,28 @@ stored_file_path = storage.upload_file(
94
100
 
95
101
  Raises an exception if both primary and fallback providers fail.
96
102
 
103
+ #### Async Upload
104
+
105
+ For async environments, use `upload_file_async()`:
106
+
107
+ ```python
108
+ import asyncio
109
+ from fallbacks3 import Storage
110
+
111
+ storage = Storage()
112
+
113
+ async def upload():
114
+ stored_file_uri = await storage.upload_file_async(
115
+ remote_file_uri="ps3://palver-whatsapp/audio.mp3",
116
+ local_file_path="/local/path/audio.mp3"
117
+ )
118
+ print(stored_file_uri) # "ps3://palver-whatsapp/audio.mp3"
119
+
120
+ asyncio.run(upload())
121
+ ```
122
+
123
+ The async method also supports automatic fallback, just like the synchronous version.
124
+
97
125
  ### Download and Signed URLs
98
126
 
99
127
  Download and signed URL generation use the provider specified in the remote file URI.
@@ -1,7 +1,7 @@
1
+ import asyncio
1
2
  from fallbacks3.config import config
2
3
  from fallbacks3.provider import S3Provider
3
4
  from fallbacks3.utils.uri import build_provider_credentials, parse_uri
4
- from typing import Dict, Tuple
5
5
  from urllib.parse import ParseResult
6
6
 
7
7
 
@@ -27,7 +27,7 @@ class Storage:
27
27
  Raises:
28
28
  ValueError: If fallback_provider not found in providers
29
29
  """
30
- self.providers: Dict[str, S3Provider] = {}
30
+ self.providers: dict[str, S3Provider] = {}
31
31
 
32
32
  # Parse and initialize all providers
33
33
  for provider in providers.split(","):
@@ -89,6 +89,27 @@ class Storage:
89
89
  )
90
90
  raise
91
91
 
92
+ async def upload_file_async(
93
+ self, remote_file_uri: str, local_file_path: str
94
+ ) -> str:
95
+ """Upload a file asynchronously with automatic fallback on failure.
96
+
97
+ Args:
98
+ remote_file_uri: Remote file URI in format <provider>://<bucket>/<file_path>
99
+ Example: "ps3://palver-whatsapp/file.mp4"
100
+ local_file_path: Local path to the file to upload
101
+
102
+ Returns:
103
+ URI of uploaded file in format: <provider>://<bucket>/<file_path>
104
+
105
+ Raises:
106
+ ValueError: If provider is not configured
107
+ Exception: If upload fails on both primary and fallback providers
108
+ """
109
+ return await asyncio.to_thread(
110
+ self.upload_file, remote_file_uri, local_file_path
111
+ )
112
+
92
113
  def download_file(self, remote_file_uri: str, local_file_path: str) -> str:
93
114
  """Download a file from storage.
94
115
 
@@ -133,7 +154,7 @@ class Storage:
133
154
  expiration=expiration,
134
155
  )
135
156
 
136
- def _resolve_uri(self, uri: str) -> Tuple[ParseResult, S3Provider]:
157
+ def _resolve_uri(self, uri: str) -> tuple[ParseResult, S3Provider]:
137
158
  """Parse and validate URI, then return parsed URI and provider.
138
159
 
139
160
  Args:
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fallbacks3
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: S3-compatible storage library with automatic fallback support
5
5
  Author-email: Mila de Oliveira <mila.oliveira@palver.com.br>
6
6
  Project-URL: Homepage, https://github.com/palverdata/fallbacks3
7
7
  Project-URL: Repository, https://github.com/palverdata/fallbacks3
8
8
  Project-URL: Issues, https://github.com/palverdata/fallbacks3/issues
9
- Requires-Python: >=3.8
9
+ Requires-Python: >=3.9
10
10
  Description-Content-Type: text/markdown
11
11
  Requires-Dist: boto3>=1.26.0
12
12
  Requires-Dist: pydantic-settings>=2.0.0
@@ -85,6 +85,12 @@ stored_file_uri = storage.upload_file(
85
85
  )
86
86
  print(uri) # "ps3://palver-whatsapp/audio.mp3"
87
87
 
88
+ # Async upload (for async environments)
89
+ stored_file_uri = await storage.upload_file_async(
90
+ remote_file_uri="ps3://palver-whatsapp/audio.mp3",
91
+ local_file_path="/local/path/audio.mp3"
92
+ )
93
+
88
94
  # Download a file
89
95
  downloaded_file_path = storage.download_file(
90
96
  remote_file_uri="ps3://palver-whatsapp/audio.mp3",
@@ -115,6 +121,28 @@ stored_file_path = storage.upload_file(
115
121
 
116
122
  Raises an exception if both primary and fallback providers fail.
117
123
 
124
+ #### Async Upload
125
+
126
+ For async environments, use `upload_file_async()`:
127
+
128
+ ```python
129
+ import asyncio
130
+ from fallbacks3 import Storage
131
+
132
+ storage = Storage()
133
+
134
+ async def upload():
135
+ stored_file_uri = await storage.upload_file_async(
136
+ remote_file_uri="ps3://palver-whatsapp/audio.mp3",
137
+ local_file_path="/local/path/audio.mp3"
138
+ )
139
+ print(stored_file_uri) # "ps3://palver-whatsapp/audio.mp3"
140
+
141
+ asyncio.run(upload())
142
+ ```
143
+
144
+ The async method also supports automatic fallback, just like the synchronous version.
145
+
118
146
  ### Download and Signed URLs
119
147
 
120
148
  Download and signed URL generation use the provider specified in the remote file URI.
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fallbacks3"
7
- version = "0.1.0"
7
+ version = "0.2.0"
8
8
  description = "S3-compatible storage library with automatic fallback support"
9
9
  readme = "README.md"
10
- requires-python = ">=3.8"
10
+ requires-python = ">=3.9"
11
11
  authors = [
12
12
  {name = "Mila de Oliveira", email = "mila.oliveira@palver.com.br"}
13
13
  ]
@@ -45,8 +45,8 @@ python_functions = ["test_*"]
45
45
 
46
46
  [tool.black]
47
47
  line-length = 88
48
- target-version = ["py38"]
48
+ target-version = ["py39"]
49
49
 
50
50
  [tool.ruff]
51
51
  line-length = 88
52
- target-version = "py38"
52
+ target-version = "py39"
File without changes