polly-python 1.4.0__tar.gz → 2.0.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.
- {polly_python-1.4.0/polly_python.egg-info → polly_python-2.0.0}/PKG-INFO +2 -1
- polly_python-2.0.0/polly/__init__.py +1 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/helpers.py +54 -7
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/pipelines.py +2 -1
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/workspaces.py +10 -2
- {polly_python-1.4.0 → polly_python-2.0.0/polly_python.egg-info}/PKG-INFO +2 -1
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_python.egg-info/requires.txt +1 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/setup.cfg +1 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_workspaces.py +25 -0
- polly_python-1.4.0/polly/__init__.py +0 -1
- {polly_python-1.4.0 → polly_python-2.0.0}/LICENSE.md +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/MANIFEST.in +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/README.md +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/analyze.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/application_error_info.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/auth.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/bridge_cohort.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/cohort.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/constants.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/core_cohort.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/curation.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/data_management.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/errors.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/help.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/http_response_codes.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/index_schema_level_conversion_const.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/jobs.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/omixatlas.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/omixatlas_hlpr.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/s3_utils.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/session.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/threading_utils.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/tracking.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/validation.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly/validation_hlpr.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_interfaces/IFiles.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_interfaces/IReporting.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_interfaces/ISchema.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_interfaces/__init__.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_python.egg-info/SOURCES.txt +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_python.egg-info/dependency_links.txt +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_python.egg-info/top_level.txt +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/__init__.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/dataset.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/files/__init__.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/files/files.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/files/files_hlpr.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/polly_services_hlpr.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/reporting/__init__.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/reporting/reporting.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/reporting/reporting_hlpr.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/schema/__init__.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/schema/schema.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/schema/schema_const.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/schema/schema_hlpr.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/polly_services/schema/validate_schema_hlpr.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/pyproject.toml +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/setup.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_cohort.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_constants.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_curation.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_data_management.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_helpers.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_jobs.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_omixatlas.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_pipelines.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_s3_utils.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_schema_ux.py +0 -0
- {polly_python-1.4.0 → polly_python-2.0.0}/tests/test_threading_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: polly_python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Polly SDK
|
|
5
5
|
Home-page: https://github.com/ElucidataInc/polly-python
|
|
6
6
|
Project-URL: Documentation, https://docs.elucidata.io
|
|
@@ -17,6 +17,7 @@ Requires-Dist: mixpanel==4.10.0
|
|
|
17
17
|
Requires-Dist: Deprecated>=1.2.12
|
|
18
18
|
Requires-Dist: pytest>=6.2.5
|
|
19
19
|
Requires-Dist: cryptography<=38.0.0,>=37.0.1
|
|
20
|
+
Requires-Dist: numpy==1.26.4
|
|
20
21
|
Requires-Dist: plotly<5.0.0,>=4.8.1; python_version > "3.6" and python_version < "3.7"
|
|
21
22
|
Requires-Dist: plotly>=5.0.0; python_version >= "3.7"
|
|
22
23
|
Requires-Dist: pandas<1.2.0,>=1.1.0; python_version > "3.6" and python_version < "3.7"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.0.0"
|
|
@@ -29,6 +29,7 @@ import pandas as pd
|
|
|
29
29
|
import polly.http_response_codes as http_codes
|
|
30
30
|
from polly.tracking import Track
|
|
31
31
|
import polly.constants as const
|
|
32
|
+
import string
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
def get_platform_value_from_env(
|
|
@@ -54,7 +55,9 @@ def make_path(prefix: any, postfix: any) -> str:
|
|
|
54
55
|
if not prefix:
|
|
55
56
|
raise InvalidParameterException("prefix")
|
|
56
57
|
if not postfix:
|
|
57
|
-
raise InvalidParameterException(
|
|
58
|
+
raise InvalidParameterException(
|
|
59
|
+
'path can\'t be empty. if u want to push to root then make path as "/"'
|
|
60
|
+
)
|
|
58
61
|
return os.path.normpath(f"{prefix}/{postfix}")
|
|
59
62
|
|
|
60
63
|
|
|
@@ -149,22 +152,60 @@ def display_df_from_list(val_list: list, column_name_in_df: str):
|
|
|
149
152
|
|
|
150
153
|
def upload_to_S3(cloud_path: str, local_path: str, credentials: dict) -> None:
|
|
151
154
|
"""
|
|
152
|
-
|
|
155
|
+
Uploads a file or folder to a specified S3 cloud path.
|
|
153
156
|
"""
|
|
154
157
|
access_key_id = credentials["AccessKeyId"]
|
|
155
158
|
secret_access_key = credentials["SecretAccessKey"]
|
|
156
159
|
session_token = credentials["SessionToken"]
|
|
160
|
+
|
|
161
|
+
# use these extras for all CloudPaths
|
|
157
162
|
client = S3Client(
|
|
158
163
|
aws_access_key_id=access_key_id,
|
|
159
164
|
aws_secret_access_key=secret_access_key,
|
|
160
165
|
aws_session_token=session_token,
|
|
161
166
|
extra_args={"ContentType": "text/html"},
|
|
162
167
|
)
|
|
163
|
-
|
|
168
|
+
|
|
169
|
+
# Behavior:
|
|
170
|
+
# 1. Validation of cloud_path:
|
|
171
|
+
# - If any part of the cloud_path contains directory names starting with special characters,
|
|
172
|
+
# the function will not consider them as valid unless they already exist in the S3 bucket.
|
|
173
|
+
# - The function will iterate through the cloud_path, checking each segment. If it encounters
|
|
174
|
+
# a segment starting with a special character that does not already exist in the S3 bucket,
|
|
175
|
+
# it will raise an error.
|
|
176
|
+
|
|
177
|
+
# Example:
|
|
178
|
+
# - Given a cloud_path of 'a/b/c/#/d/e':
|
|
179
|
+
# 1. if path not exists already, The function first checks if the path '{s3}/a/b/c/#/d' exists and that 'e'
|
|
180
|
+
# does not start with a special character.
|
|
181
|
+
# 2. If '{s3}/a/b/c/#/d' not exists, it checks '{s3}/a/b/c/#' and ensures 'd' does not start with a special character.
|
|
182
|
+
# 3. This process continues until a exist path is found or the directory start with special character.
|
|
183
|
+
# - If the cloud_path is invalid, the function raises an exception.
|
|
184
|
+
# - Once a valid path is determined, the file or folder is uploaded to this path in the S3 bucket.
|
|
164
185
|
client.set_as_default_client()
|
|
165
186
|
source_path = client.CloudPath(cloud_path)
|
|
187
|
+
splt_char = os.path.sep
|
|
188
|
+
punctuation_chars = set(string.punctuation)
|
|
166
189
|
if not source_path.exists():
|
|
190
|
+
# if path is S3://UserDataBucket/12345/path
|
|
191
|
+
# then path split will be [S3, , UserDataBucket, 12345, path]
|
|
192
|
+
path_split = cloud_path.split("/")
|
|
193
|
+
# s3 path have length = 4, so ignore that and checking path after that
|
|
194
|
+
while len(path_split) > 4:
|
|
195
|
+
cloud_path = splt_char.join(path_split[: len(path_split) - 1])
|
|
196
|
+
if (
|
|
197
|
+
path_split[len(path_split) - 1]
|
|
198
|
+
and path_split[len(path_split) - 1][0] in punctuation_chars
|
|
199
|
+
):
|
|
200
|
+
raise InvalidParameterException(
|
|
201
|
+
f"path can't start with {path_split[len(path_split)-1][0]}"
|
|
202
|
+
)
|
|
203
|
+
new_source_path = client.CloudPath(cloud_path)
|
|
204
|
+
if new_source_path.exists():
|
|
205
|
+
break
|
|
206
|
+
path_split = cloud_path.split("/")
|
|
167
207
|
source_path.mkdir()
|
|
208
|
+
|
|
168
209
|
try:
|
|
169
210
|
source_path.upload_from(local_path, force_overwrite_to_cloud=True)
|
|
170
211
|
except ClientError as e:
|
|
@@ -172,7 +213,11 @@ def upload_to_S3(cloud_path: str, local_path: str, credentials: dict) -> None:
|
|
|
172
213
|
|
|
173
214
|
|
|
174
215
|
def download_from_S3(
|
|
175
|
-
cloud_path: str,
|
|
216
|
+
cloud_path: str,
|
|
217
|
+
workspace_path: str,
|
|
218
|
+
credentials: dict,
|
|
219
|
+
destination_path: str,
|
|
220
|
+
copy_workspace_path: bool,
|
|
176
221
|
) -> None:
|
|
177
222
|
"""
|
|
178
223
|
Function to download file/folder from workspaces
|
|
@@ -195,13 +240,15 @@ def download_from_S3(
|
|
|
195
240
|
except ClientError as e:
|
|
196
241
|
raise OperationFailedException(e)
|
|
197
242
|
else:
|
|
198
|
-
if not cloud_path.endswith("/"):
|
|
199
|
-
cloud_path += "/"
|
|
200
243
|
source_path = client.CloudPath(cloud_path)
|
|
201
244
|
if not source_path.is_dir():
|
|
202
245
|
raise InvalidPathException
|
|
203
246
|
try:
|
|
204
|
-
|
|
247
|
+
# If copy_workspace_path is True, append workspace_path to destination_path to copy the directory structure.
|
|
248
|
+
# ex- make_path('/home/user/project/', 'folder1/folder2') = '/home/user/project/folder1/folder2'
|
|
249
|
+
if copy_workspace_path is True:
|
|
250
|
+
destination_path = f"{make_path(destination_path,workspace_path)}"
|
|
251
|
+
|
|
205
252
|
source_path.copytree(destination_path, force_overwrite_to_cloud=True)
|
|
206
253
|
except ClientError as e:
|
|
207
254
|
raise OperationFailedException(e)
|
|
@@ -195,8 +195,9 @@ class Pipelines:
|
|
|
195
195
|
"""
|
|
196
196
|
This function is used to create a Pipeline run.\n
|
|
197
197
|
A run is a collection of jobs, this functions creates an empty run in which the jobs can be added.
|
|
198
|
+
|
|
198
199
|
Args:
|
|
199
|
-
pipeline_id (str): pipeline_id for which the run is to be created
|
|
200
|
+
pipeline_id (str): pipeline_id for which the run is to be created
|
|
200
201
|
run_name (str): name of the run
|
|
201
202
|
priority (str): priority of the run, can be low | medium | high
|
|
202
203
|
tags (dict): a dict of key-value pair with tag_name -> tag_value mapping
|
|
@@ -270,6 +270,7 @@ initialize a object that can use all function and methods of Workspaces class.
|
|
|
270
270
|
if not isExists:
|
|
271
271
|
raise InvalidPathException
|
|
272
272
|
# check for access rights for the workspace_id
|
|
273
|
+
workspace_path = workspace_path.strip()
|
|
273
274
|
access_workspace = helpers.workspaces_permission_check(self, workspace_id)
|
|
274
275
|
if not access_workspace:
|
|
275
276
|
raise AccessDeniedError(
|
|
@@ -284,7 +285,11 @@ initialize a object that can use all function and methods of Workspaces class.
|
|
|
284
285
|
|
|
285
286
|
@Track.track_decorator
|
|
286
287
|
def download_from_workspaces(
|
|
287
|
-
self,
|
|
288
|
+
self,
|
|
289
|
+
workspace_id: int,
|
|
290
|
+
workspace_path: str,
|
|
291
|
+
local_path: str,
|
|
292
|
+
copy_workspace_path: bool = True,
|
|
288
293
|
) -> None:
|
|
289
294
|
"""
|
|
290
295
|
Function to download files/folders from workspaces.
|
|
@@ -292,6 +297,7 @@ initialize a object that can use all function and methods of Workspaces class.
|
|
|
292
297
|
Args:
|
|
293
298
|
workspace_id (int) : Id of the workspace where file needs to uploaded
|
|
294
299
|
workspace_path (str) : Downloaded file on workspace. The workspace path should be prefixed with "polly://"
|
|
300
|
+
copy_workspace_path (bool) : Flag indicating whether the workspace path needs to copied in the working directory
|
|
295
301
|
Returns:
|
|
296
302
|
None
|
|
297
303
|
Raises:
|
|
@@ -315,7 +321,9 @@ initialize a object that can use all function and methods of Workspaces class.
|
|
|
315
321
|
if workspace_path.startswith("polly://"):
|
|
316
322
|
workspace_path = workspace_path.split("polly://")[1]
|
|
317
323
|
s3_path, credentials = self._s3_util(workspace_id, workspace_path)
|
|
318
|
-
helpers.download_from_S3(
|
|
324
|
+
helpers.download_from_S3(
|
|
325
|
+
s3_path, workspace_path, credentials, local_path, copy_workspace_path
|
|
326
|
+
)
|
|
319
327
|
logging.basicConfig(level=logging.INFO)
|
|
320
328
|
logging.info(f"Download successful to path={local_path}")
|
|
321
329
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: polly_python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Polly SDK
|
|
5
5
|
Home-page: https://github.com/ElucidataInc/polly-python
|
|
6
6
|
Project-URL: Documentation, https://docs.elucidata.io
|
|
@@ -17,6 +17,7 @@ Requires-Dist: mixpanel==4.10.0
|
|
|
17
17
|
Requires-Dist: Deprecated>=1.2.12
|
|
18
18
|
Requires-Dist: pytest>=6.2.5
|
|
19
19
|
Requires-Dist: cryptography<=38.0.0,>=37.0.1
|
|
20
|
+
Requires-Dist: numpy==1.26.4
|
|
20
21
|
Requires-Dist: plotly<5.0.0,>=4.8.1; python_version > "3.6" and python_version < "3.7"
|
|
21
22
|
Requires-Dist: plotly>=5.0.0; python_version >= "3.7"
|
|
22
23
|
Requires-Dist: pandas<1.2.0,>=1.1.0; python_version > "3.6" and python_version < "3.7"
|
|
@@ -24,6 +24,7 @@ install_requires =
|
|
|
24
24
|
Deprecated >= 1.2.12
|
|
25
25
|
pytest >= 6.2.5
|
|
26
26
|
cryptography >= 37.0.1, <= 38.0.0
|
|
27
|
+
numpy == 1.26.4
|
|
27
28
|
plotly <5.0.0, >=4.8.1 ; python_version > '3.6' and python_version < '3.7'
|
|
28
29
|
plotly >= 5.0.0 ; python_version >= '3.7'
|
|
29
30
|
pandas >= 1.1.0, < 1.2.0 ; python_version > '3.6' and python_version < '3.7'
|
|
@@ -194,6 +194,31 @@ def test_download_from_workspaces(mocker, mock_workspaces_permission_check_fixtu
|
|
|
194
194
|
valid_workspace_id, invalid_workspace_path, local_path
|
|
195
195
|
)
|
|
196
196
|
|
|
197
|
+
exclude_path_result = obj.download_from_workspaces(
|
|
198
|
+
valid_workspace_id, valid_workspace_path, local_path, copy_workspace_path=False
|
|
199
|
+
)
|
|
200
|
+
assert exclude_path_result is None
|
|
201
|
+
with pytest.raises(
|
|
202
|
+
InvalidParameterException,
|
|
203
|
+
match=r".* Invalid Parameters .*",
|
|
204
|
+
):
|
|
205
|
+
obj.download_from_workspaces(
|
|
206
|
+
invalid_workspace_id,
|
|
207
|
+
valid_workspace_path,
|
|
208
|
+
local_path,
|
|
209
|
+
copy_workspace_path=False,
|
|
210
|
+
)
|
|
211
|
+
with pytest.raises(
|
|
212
|
+
InvalidParameterException,
|
|
213
|
+
match=r".* Invalid Parameters .*",
|
|
214
|
+
):
|
|
215
|
+
obj.download_from_workspaces(
|
|
216
|
+
valid_workspace_id,
|
|
217
|
+
invalid_workspace_path,
|
|
218
|
+
local_path,
|
|
219
|
+
copy_workspace_path=False,
|
|
220
|
+
)
|
|
221
|
+
|
|
197
222
|
|
|
198
223
|
def test_sync_data(mocker, mock_workspaces_permission_check_fixture):
|
|
199
224
|
obj = workspaces.Workspaces(token)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.4.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|