synapse-sdk 1.0.0a83__py3-none-any.whl → 1.0.0a84__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 synapse-sdk might be problematic. Click here for more details.

@@ -2,11 +2,52 @@ from urllib.parse import parse_qs, urlparse
2
2
 
3
3
 
4
4
  class BaseStorage:
5
+ """Base storage provider class for all storage implementations.
6
+
7
+ This is an abstract base class that defines the interface for storage providers.
8
+ All storage providers (S3, GCP, SFTP, HTTP, FileSystem) must inherit from this
9
+ class and implement all the abstract methods.
10
+
11
+ Args:
12
+ connection_params (str | dict): The connection parameters. Can be either:
13
+ - A URL string (e.g., 's3://bucket/path?access_key=key&secret_key=secret')
14
+ - A dict with 'provider' and 'configuration' keys
15
+
16
+ Attributes:
17
+ url: Parsed URL object if connection_params was a string
18
+ base_path: Base path for storage operations (provider-specific)
19
+ options: Storage-specific options
20
+ query_params: Parsed query parameters from URL or configuration dict
21
+ OPTION_CASTS: Dictionary mapping option names to type casting functions
22
+
23
+ Example:
24
+ >>> # URL-based initialization
25
+ >>> storage = SomeStorage('s3://bucket/path?access_key=key&secret_key=secret')
26
+ >>>
27
+ >>> # Dict-based initialization
28
+ >>> config = {
29
+ ... 'provider': 's3',
30
+ ... 'configuration': {
31
+ ... 'bucket_name': 'my-bucket',
32
+ ... 'access_key': 'key',
33
+ ... 'secret_key': 'secret'
34
+ ... }
35
+ ... }
36
+ >>> storage = SomeStorage(config)
37
+ """
38
+
5
39
  url = None
6
40
  options = None
7
41
  OPTION_CASTS = {}
8
42
 
9
43
  def __init__(self, connection_params: str | dict):
44
+ """Initialize the storage provider with connection parameters.
45
+
46
+ Args:
47
+ connection_params (str | dict): Connection parameters for the storage provider.
48
+ If string, should be a valid URL with scheme and query parameters.
49
+ If dict, should contain 'provider' and 'configuration' keys.
50
+ """
10
51
  self.url = None
11
52
 
12
53
  if isinstance(connection_params, dict):
@@ -16,6 +57,15 @@ class BaseStorage:
16
57
  self.query_params = self.url_querystring_to_dict()
17
58
 
18
59
  def url_querystring_to_dict(self):
60
+ """Parse URL query string into a dictionary with proper type casting.
61
+
62
+ Converts query parameters from the URL into a dictionary, applying
63
+ type casting based on OPTION_CASTS mapping. Single-value lists are
64
+ flattened to scalar values.
65
+
66
+ Returns:
67
+ dict: Parsed and type-cast query parameters.
68
+ """
19
69
  query_string = self.url.query
20
70
 
21
71
  query_dict = parse_qs(query_string)
@@ -30,43 +80,104 @@ class BaseStorage:
30
80
  }
31
81
 
32
82
  def upload(self, source, target):
83
+ """Upload a file from source to target location.
84
+
85
+ Args:
86
+ source (str): Path to the source file on local filesystem.
87
+ target (str): Target path in the storage provider.
88
+
89
+ Returns:
90
+ str: URL or identifier of the uploaded file.
91
+
92
+ Raises:
93
+ NotImplementedError: This method must be implemented by subclasses.
94
+ """
33
95
  raise NotImplementedError
34
96
 
35
97
  def exists(self, target):
98
+ """Check if a file exists at the target location.
99
+
100
+ Args:
101
+ target (str): Target path in the storage provider.
102
+
103
+ Returns:
104
+ bool: True if the file exists, False otherwise.
105
+
106
+ Raises:
107
+ NotImplementedError: This method must be implemented by subclasses.
108
+ """
36
109
  raise NotImplementedError
37
110
 
38
111
  def get_url(self, target):
112
+ """Get the URL for accessing a file at the target location.
113
+
114
+ Args:
115
+ target (str): Target path in the storage provider.
116
+
117
+ Returns:
118
+ str: URL that can be used to access the file.
119
+
120
+ Raises:
121
+ NotImplementedError: This method must be implemented by subclasses.
122
+ """
39
123
  raise NotImplementedError
40
124
 
41
125
  def get_pathlib(self, path):
42
- """Get the path as a pathlib object.
126
+ """Get the path as a pathlib-compatible object.
43
127
 
44
128
  Args:
45
- path (str): The path to convert.
129
+ path (str): The path to convert, relative to the storage root.
46
130
 
47
131
  Returns:
48
- pathlib.Path: The converted path.
132
+ pathlib.Path or UPath: A pathlib-compatible object representing the path.
133
+ The exact type depends on the storage provider implementation.
134
+
135
+ Raises:
136
+ NotImplementedError: This method must be implemented by subclasses.
137
+
138
+ Note:
139
+ Different storage providers may return different path object types:
140
+ - FileSystemStorage returns pathlib.Path objects
141
+ - Cloud storage providers typically return UPath objects
49
142
  """
50
143
  raise NotImplementedError
51
144
 
52
145
  def get_path_file_count(self, pathlib_obj):
53
- """Get the file count in the path.
146
+ """Get the total number of files in the given path.
54
147
 
55
148
  Args:
56
- pathlib_obj (UPath): The path to get file count.
149
+ pathlib_obj (Path | UPath): The path object to count files in.
150
+ Should be obtained from get_pathlib().
57
151
 
58
152
  Returns:
59
- int: The file count in the path.
153
+ int: The total number of files found recursively in the path.
154
+ Returns 1 for individual files, 0 for non-existent paths.
155
+
156
+ Raises:
157
+ NotImplementedError: This method must be implemented by subclasses.
158
+
159
+ Note:
160
+ This method counts files recursively, including files in subdirectories.
161
+ Directories themselves are not counted, only regular files.
60
162
  """
61
163
  raise NotImplementedError
62
164
 
63
165
  def get_path_total_size(self, pathlib_obj):
64
- """Get the total size of the path.
166
+ """Get the total size of all files in the given path.
65
167
 
66
168
  Args:
67
- pathlib_obj (UPath): The path to get total size.
169
+ pathlib_obj (Path | UPath): The path object to calculate size for.
170
+ Should be obtained from get_pathlib().
68
171
 
69
172
  Returns:
70
- int: The total size of the path.
173
+ int: The total size in bytes of all files found recursively in the path.
174
+ Returns the file size for individual files, 0 for non-existent paths.
175
+
176
+ Raises:
177
+ NotImplementedError: This method must be implemented by subclasses.
178
+
179
+ Note:
180
+ This method calculates the total size recursively, including files
181
+ in subdirectories. Only regular files contribute to the total size.
71
182
  """
72
183
  raise NotImplementedError
@@ -0,0 +1,126 @@
1
+ import shutil
2
+ from pathlib import Path
3
+
4
+ from synapse_sdk.utils.storage.providers import BaseStorage
5
+
6
+
7
+ class FileSystemStorage(BaseStorage):
8
+ """Storage provider for file system.
9
+
10
+ * This storage do not support url based initialization.
11
+
12
+ Args:
13
+ url (str): The URL of the storage provider.
14
+
15
+ Examples:
16
+ >>> # Dict-based initialization
17
+ >>> config = {
18
+ ... 'provider': 'filesystem',
19
+ ... 'configuration': {
20
+ ... 'location': '/data'
21
+ ... }
22
+ ... }
23
+ >>> storage = FileSystemStorage(config)
24
+ """
25
+
26
+ def __init__(self, url):
27
+ super().__init__(url)
28
+ self.base_path = Path(self.query_params['location'])
29
+
30
+ def upload(self, source, target):
31
+ """Upload a file from source to target location.
32
+
33
+ Args:
34
+ source (str): Path to source file
35
+ target (str): Target path relative to base path
36
+
37
+ Returns:
38
+ str: URL of uploaded file
39
+ """
40
+ source_path = Path(source)
41
+ target_path = self.base_path / target
42
+
43
+ # Create parent directories if they don't exist
44
+ target_path.parent.mkdir(parents=True, exist_ok=True)
45
+
46
+ # Copy the file
47
+ shutil.copy2(source_path, target_path)
48
+
49
+ return self.get_url(target)
50
+
51
+ def exists(self, target):
52
+ """Check if target file exists.
53
+
54
+ Args:
55
+ target (str): Target path relative to base path
56
+
57
+ Returns:
58
+ bool: True if file exists, False otherwise
59
+ """
60
+ target_path = self.base_path / target
61
+ return target_path.exists()
62
+
63
+ def get_url(self, target):
64
+ """Get URL for target file.
65
+
66
+ Args:
67
+ target (str): Target path relative to base path
68
+
69
+ Returns:
70
+ str: File URL
71
+ """
72
+ target_path = self.base_path / target
73
+ return f'file://{target_path.absolute()}'
74
+
75
+ def get_pathlib(self, path):
76
+ """Get the path as a pathlib object.
77
+
78
+ Args:
79
+ path (str): The path to convert.
80
+
81
+ Returns:
82
+ pathlib.Path: The converted path.
83
+ """
84
+ return self.base_path / path
85
+
86
+ def get_path_file_count(self, pathlib_obj):
87
+ """Get the file count in the path.
88
+
89
+ Args:
90
+ pathlib_obj (Path): The path to get file count.
91
+
92
+ Returns:
93
+ int: The file count in the path.
94
+ """
95
+ if not pathlib_obj.exists():
96
+ return 0
97
+
98
+ if pathlib_obj.is_file():
99
+ return 1
100
+
101
+ count = 0
102
+ for item in pathlib_obj.rglob('*'):
103
+ if item.is_file():
104
+ count += 1
105
+ return count
106
+
107
+ def get_path_total_size(self, pathlib_obj):
108
+ """Get the total size of the path.
109
+
110
+ Args:
111
+ pathlib_obj (Path): The path to get total size.
112
+
113
+ Returns:
114
+ int: The total size of the path.
115
+ """
116
+ if not pathlib_obj.exists():
117
+ return 0
118
+
119
+ if pathlib_obj.is_file():
120
+ return pathlib_obj.stat().st_size
121
+
122
+ total_size = 0
123
+ for item in pathlib_obj.rglob('*'):
124
+ if item.is_file():
125
+ total_size += item.stat().st_size
126
+ return total_size
@@ -1,3 +1,4 @@
1
+ from synapse_sdk.utils.storage.providers.file_system import FileSystemStorage
1
2
  from synapse_sdk.utils.storage.providers.gcp import GCPStorage
2
3
  from synapse_sdk.utils.storage.providers.http import HTTPStorage
3
4
  from synapse_sdk.utils.storage.providers.s3 import S3Storage
@@ -12,4 +13,5 @@ STORAGE_PROVIDERS = {
12
13
  'sftp': SFTPStorage,
13
14
  'http': HTTPStorage,
14
15
  'https': HTTPStorage,
16
+ 'file_system': FileSystemStorage,
15
17
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synapse-sdk
3
- Version: 1.0.0a83
3
+ Version: 1.0.0a84
4
4
  Summary: synapse sdk
5
5
  Author-email: datamaker <developer@datamaker.io>
6
6
  License: MIT
@@ -214,15 +214,16 @@ synapse_sdk/utils/pydantic/config.py,sha256=1vYOcUI35GslfD1rrqhFkNXXJOXt4IDqOPSx
214
214
  synapse_sdk/utils/pydantic/errors.py,sha256=0v0T12eQBr1KrFiEOBu6KMaPK4aPEGEC6etPJGoR5b4,1061
215
215
  synapse_sdk/utils/pydantic/validators.py,sha256=G47P8ObPhsePmd_QZDK8EdPnik2CbaYzr_N4Z6En8dc,193
216
216
  synapse_sdk/utils/storage/__init__.py,sha256=HmZHqvoV-EogV2bE-Sw5XQRlrNuf3gfNL9irAJeRYsA,2195
217
- synapse_sdk/utils/storage/registry.py,sha256=MNhX2ohVfQsjhuHO2YMn0wiJIA0ELPp5NXH8LWoh2bQ,473
218
- synapse_sdk/utils/storage/providers/__init__.py,sha256=x7RGwZryT2FpVxS7fGWryRVpquHzAiIfTz-9uLgjleo,1860
217
+ synapse_sdk/utils/storage/registry.py,sha256=-VNIM7wERubomcyXMuAlPPRKyy87kVpkRAsdlBRp2ig,589
218
+ synapse_sdk/utils/storage/providers/__init__.py,sha256=crxrRzXXfBAmyR4nZS2RZvlLnr4IP1S-6eYeX_bSnLI,6412
219
+ synapse_sdk/utils/storage/providers/file_system.py,sha256=MBBXxWRgVSDtjP4T0L0sbaZkXEI4B8ANtLweaMWtaaQ,3217
219
220
  synapse_sdk/utils/storage/providers/gcp.py,sha256=i2BQCu1Kej1If9SuNr2_lEyTcr5M_ncGITZrL0u5wEA,363
220
221
  synapse_sdk/utils/storage/providers/http.py,sha256=2DhIulND47JOnS5ZY7MZUex7Su3peAPksGo1Wwg07L4,5828
221
222
  synapse_sdk/utils/storage/providers/s3.py,sha256=ZmqekAvIgcQBdRU-QVJYv1Rlp6VHfXwtbtjTSphua94,2573
222
223
  synapse_sdk/utils/storage/providers/sftp.py,sha256=_8s9hf0JXIO21gvm-JVS00FbLsbtvly4c-ETLRax68A,1426
223
- synapse_sdk-1.0.0a83.dist-info/licenses/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
224
- synapse_sdk-1.0.0a83.dist-info/METADATA,sha256=JFd43LG4HIkMQZECtk_O7CBHF3vBdNHd2LWH9W5VtjQ,3805
225
- synapse_sdk-1.0.0a83.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
226
- synapse_sdk-1.0.0a83.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
227
- synapse_sdk-1.0.0a83.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
228
- synapse_sdk-1.0.0a83.dist-info/RECORD,,
224
+ synapse_sdk-1.0.0a84.dist-info/licenses/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
225
+ synapse_sdk-1.0.0a84.dist-info/METADATA,sha256=TQr3AWnKuEIisWrMC0URwIn64lxJgnYVYimuUtoIp7E,3805
226
+ synapse_sdk-1.0.0a84.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
227
+ synapse_sdk-1.0.0a84.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
228
+ synapse_sdk-1.0.0a84.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
229
+ synapse_sdk-1.0.0a84.dist-info/RECORD,,