fallbacks3 0.3.1__tar.gz → 0.5.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.3.1
3
+ Version: 0.5.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.9
9
+ Requires-Python: >=3.10
10
10
  Description-Content-Type: text/markdown
11
11
  Requires-Dist: boto3>=1.26.0
12
12
  Requires-Dist: pydantic-settings>=2.0.0
@@ -49,6 +49,15 @@ PROVIDERS="ps3://access_key:secret_key@ps3.palver.com,r2://access_key:secret_key
49
49
  FALLBACK_PROVIDER="r2"
50
50
  ```
51
51
 
52
+ `FALLBACK_PROVIDER` may also be set as a `<scheme>://<bucket>` URI to redirect fallback
53
+ uploads to a specific bucket instead of reusing the original request's bucket. The scheme
54
+ must still be one of the providers in `PROVIDERS`.
55
+
56
+ ```bash
57
+ # On fallback, upload to bucket "bucket-v2" on the r2 provider
58
+ FALLBACK_PROVIDER="r2://bucket-v2"
59
+ ```
60
+
52
61
 
53
62
  ### Provider URI Format
54
63
 
@@ -108,7 +117,7 @@ print(signed_url) # "https://ps3.palver.com/palver-whatsapp/audio.mp3?signature
108
117
 
109
118
  ### Upload with Automatic Fallback
110
119
 
111
- If the primary provider fails for the upload method, the library automatically retries with the fallback provider (using the same bucket and file path), as to ensure files are not lost.
120
+ If the primary provider fails for the upload method, the library automatically retries with the fallback provider (using the same bucket and file path, unless `FALLBACK_PROVIDER` specifies a bucket), as to ensure files are not lost.
112
121
 
113
122
  ```python
114
123
  # If ps3 fails, automatically falls back to r2
@@ -28,6 +28,15 @@ PROVIDERS="ps3://access_key:secret_key@ps3.palver.com,r2://access_key:secret_key
28
28
  FALLBACK_PROVIDER="r2"
29
29
  ```
30
30
 
31
+ `FALLBACK_PROVIDER` may also be set as a `<scheme>://<bucket>` URI to redirect fallback
32
+ uploads to a specific bucket instead of reusing the original request's bucket. The scheme
33
+ must still be one of the providers in `PROVIDERS`.
34
+
35
+ ```bash
36
+ # On fallback, upload to bucket "bucket-v2" on the r2 provider
37
+ FALLBACK_PROVIDER="r2://bucket-v2"
38
+ ```
39
+
31
40
 
32
41
  ### Provider URI Format
33
42
 
@@ -87,7 +96,7 @@ print(signed_url) # "https://ps3.palver.com/palver-whatsapp/audio.mp3?signature
87
96
 
88
97
  ### Upload with Automatic Fallback
89
98
 
90
- If the primary provider fails for the upload method, the library automatically retries with the fallback provider (using the same bucket and file path), as to ensure files are not lost.
99
+ If the primary provider fails for the upload method, the library automatically retries with the fallback provider (using the same bucket and file path, unless `FALLBACK_PROVIDER` specifies a bucket), as to ensure files are not lost.
91
100
 
92
101
  ```python
93
102
  # If ps3 fails, automatically falls back to r2
@@ -1,9 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING
4
-
5
3
  from boto3 import client
4
+ from boto3.s3.transfer import TransferConfig
6
5
  from botocore.client import Config as BotoConfig
6
+ from typing import TYPE_CHECKING
7
7
 
8
8
  if TYPE_CHECKING:
9
9
  from mypy_boto3_s3.client import S3Client
@@ -18,6 +18,7 @@ class S3Provider:
18
18
  endpoint: str,
19
19
  access_key_id: str,
20
20
  secret_access_key: str,
21
+ transfer_config: TransferConfig | None = None,
21
22
  ):
22
23
  """Initialize S3 provider with credentials.
23
24
 
@@ -26,9 +27,12 @@ class S3Provider:
26
27
  endpoint: S3 endpoint URL with scheme (e.g., 'https://ps3.palver.com')
27
28
  access_key_id: Access key ID
28
29
  secret_access_key: Secret access key
30
+ transfer_config: Optional boto3 TransferConfig for upload behaviour.
31
+ Defaults to boto3's built-in defaults when None.
29
32
  """
30
33
  self.provider_scheme: str = provider_scheme
31
34
  self.endpoint: str = endpoint
35
+ self.transfer_config: TransferConfig | None = transfer_config
32
36
  self.client: S3Client = client(
33
37
  "s3",
34
38
  config=BotoConfig(signature_version="s3v4"),
@@ -49,7 +53,11 @@ class S3Provider:
49
53
  Full URI of the uploaded file in format:
50
54
  <provider_scheme>://<bucket>/<file_name>
51
55
  """
52
- self.client.upload_file(file_path, bucket, file_name)
56
+ self.client.upload_file(
57
+ file_path, bucket, file_name, Config=self.transfer_config
58
+ ) if self.transfer_config else self.client.upload_file(
59
+ file_path, bucket, file_name
60
+ )
53
61
  return f"{self.provider_scheme}://{bucket}/{file_name}"
54
62
 
55
63
  def download_file(self, file_name: str, local_path: str, bucket: str) -> str:
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+
2
3
  from fallbacks3.config import config
3
4
  from fallbacks3.provider import S3Provider
4
5
  from fallbacks3.utils.uri import build_provider_credentials, parse_uri
@@ -12,6 +13,7 @@ class Storage:
12
13
  self,
13
14
  providers: str = config.providers,
14
15
  fallback_provider: str = config.fallback_provider,
16
+ provider_configs: dict[str, dict] | None = None,
15
17
  ):
16
18
  """Initialize storage with multiple providers.
17
19
 
@@ -20,9 +22,15 @@ class Storage:
20
22
  <provider>://<access_key>:<secret_key>@<endpoint>
21
23
  Example: "ps3://key:secret@ps3.palver.com,s4://a:b@s4.mega.com"
22
24
  Defaults to PROVIDERS environment variable.
23
- fallback_provider: Provider scheme to use for fallback (e.g., "r2").
24
- Must be one of the providers in the providers string.
25
+ fallback_provider: Fallback provider to use on upload failure. Either
26
+ a bare scheme (e.g. "r2"), which reuses the original bucket, or a
27
+ "<scheme>://<bucket>" URI (e.g. "r2://bucket-v2"), which redirects
28
+ fallback uploads to <bucket>. The scheme must be one of the
29
+ providers in the providers string.
25
30
  Defaults to FALLBACK_PROVIDER environment variable.
31
+ provider_configs: Optional per-provider kwargs keyed by provider scheme,
32
+ merged into the S3Provider constructor for the matching provider.
33
+ Example: {"mega": {"transfer_config": TransferConfig(...)}}
26
34
 
27
35
  Raises:
28
36
  ValueError: If fallback_provider not found in providers
@@ -39,13 +47,16 @@ class Storage:
39
47
  endpoint=creds.endpoint,
40
48
  access_key_id=creds.access_key,
41
49
  secret_access_key=creds.secret_key,
50
+ **(provider_configs or {}).get(creds.provider_scheme, {}),
42
51
  )
43
52
 
44
- self.fallback_provider: str = fallback_provider
53
+ scheme, _, bucket = fallback_provider.partition("://")
54
+ self.fallback_provider: str = scheme
55
+ self.fallback_bucket: str | None = bucket or None
45
56
 
46
- if fallback_provider not in self.providers:
57
+ if self.fallback_provider not in self.providers:
47
58
  raise ValueError(
48
- f"Fallback provider '{fallback_provider}' not found in providers"
59
+ f"Fallback provider '{self.fallback_provider}' not found in providers"
49
60
  )
50
61
 
51
62
  def upload_file(self, remote_file_uri: str, local_file_path: str) -> str:
@@ -76,11 +87,11 @@ class Storage:
76
87
  if self.fallback_provider != parsed_uri.scheme:
77
88
  try:
78
89
  fallback: S3Provider = self.providers[self.fallback_provider]
79
- # Use same bucket and key with fallback provider
90
+ # Use configured fallback bucket if set, else the same bucket
80
91
  return fallback.upload_file(
81
92
  file_name=parsed_uri.path.lstrip("/"),
82
93
  file_path=local_file_path,
83
- bucket=parsed_uri.netloc,
94
+ bucket=self.fallback_bucket or parsed_uri.netloc,
84
95
  )
85
96
  except Exception as fallback_error:
86
97
  raise Exception(
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fallbacks3
3
- Version: 0.3.1
3
+ Version: 0.5.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.9
9
+ Requires-Python: >=3.10
10
10
  Description-Content-Type: text/markdown
11
11
  Requires-Dist: boto3>=1.26.0
12
12
  Requires-Dist: pydantic-settings>=2.0.0
@@ -49,6 +49,15 @@ PROVIDERS="ps3://access_key:secret_key@ps3.palver.com,r2://access_key:secret_key
49
49
  FALLBACK_PROVIDER="r2"
50
50
  ```
51
51
 
52
+ `FALLBACK_PROVIDER` may also be set as a `<scheme>://<bucket>` URI to redirect fallback
53
+ uploads to a specific bucket instead of reusing the original request's bucket. The scheme
54
+ must still be one of the providers in `PROVIDERS`.
55
+
56
+ ```bash
57
+ # On fallback, upload to bucket "bucket-v2" on the r2 provider
58
+ FALLBACK_PROVIDER="r2://bucket-v2"
59
+ ```
60
+
52
61
 
53
62
  ### Provider URI Format
54
63
 
@@ -108,7 +117,7 @@ print(signed_url) # "https://ps3.palver.com/palver-whatsapp/audio.mp3?signature
108
117
 
109
118
  ### Upload with Automatic Fallback
110
119
 
111
- If the primary provider fails for the upload method, the library automatically retries with the fallback provider (using the same bucket and file path), as to ensure files are not lost.
120
+ If the primary provider fails for the upload method, the library automatically retries with the fallback provider (using the same bucket and file path, unless `FALLBACK_PROVIDER` specifies a bucket), as to ensure files are not lost.
112
121
 
113
122
  ```python
114
123
  # If ps3 fails, automatically falls back to r2
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fallbacks3"
7
- version = "0.3.1"
7
+ version = "0.5.0"
8
8
  description = "S3-compatible storage library with automatic fallback support"
9
9
  readme = "README.md"
10
- requires-python = ">=3.9"
10
+ requires-python = ">=3.10"
11
11
  authors = [
12
12
  {name = "Mila de Oliveira", email = "mila.oliveira@palver.com.br"}
13
13
  ]
File without changes