polly-python 1.6.0__tar.gz → 1.7.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.6.0/polly_python.egg-info → polly_python-1.7.0}/PKG-INFO +1 -1
- polly_python-1.7.0/polly/__init__.py +1 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/omixatlas.py +18 -0
- {polly_python-1.6.0 → polly_python-1.7.0/polly_python.egg-info}/PKG-INFO +1 -1
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/reporting/reporting.py +101 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/reporting/reporting_hlpr.py +52 -0
- polly_python-1.6.0/polly/__init__.py +0 -1
- {polly_python-1.6.0 → polly_python-1.7.0}/LICENSE.md +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/MANIFEST.in +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/README.md +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/analyze.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/application_error_info.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/auth.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/bridge_cohort.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/cohort.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/constants.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/core_cohort.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/curation.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/data_management.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/errors.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/help.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/helpers.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/http_response_codes.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/index_schema_level_conversion_const.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/jobs.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/omixatlas_hlpr.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/pipelines.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/s3_utils.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/session.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/threading_utils.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/tracking.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/validation.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/validation_hlpr.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly/workspaces.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_interfaces/IFiles.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_interfaces/IReporting.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_interfaces/ISchema.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_interfaces/__init__.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_python.egg-info/SOURCES.txt +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_python.egg-info/dependency_links.txt +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_python.egg-info/requires.txt +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_python.egg-info/top_level.txt +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/__init__.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/dataset.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/files/__init__.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/files/files.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/files/files_hlpr.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/polly_services_hlpr.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/reporting/__init__.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/schema/__init__.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/schema/schema.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/schema/schema_const.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/schema/schema_hlpr.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/polly_services/schema/validate_schema_hlpr.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/pyproject.toml +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/setup.cfg +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/setup.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_cohort.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_constants.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_curation.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_data_management.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_helpers.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_jobs.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_omixatlas.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_pipelines.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_s3_utils.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_schema_ux.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_threading_utils.py +0 -0
- {polly_python-1.6.0 → polly_python-1.7.0}/tests/test_workspaces.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.7.0"
|
|
@@ -1537,6 +1537,24 @@ class OmixAtlas:
|
|
|
1537
1537
|
except Exception as err:
|
|
1538
1538
|
raise err
|
|
1539
1539
|
|
|
1540
|
+
@Track.track_decorator
|
|
1541
|
+
def download_linked_reports(self, repo_key: str, dataset_id: str, folder_path: str):
|
|
1542
|
+
"""Downloads Linked Reports to the repo
|
|
1543
|
+
|
|
1544
|
+
Args:
|
|
1545
|
+
repo_key (str): repo_name/repo_id of the repository for which to fetch the report
|
|
1546
|
+
dataset_id (str): dataset_id of the dataset which to fetch the reports.
|
|
1547
|
+
folder_path (str): local folder path where the files need to be downloaded
|
|
1548
|
+
|
|
1549
|
+
Returns:
|
|
1550
|
+
Downloads the datasets in the passed folder path
|
|
1551
|
+
"""
|
|
1552
|
+
try:
|
|
1553
|
+
report_obj = Reporting()
|
|
1554
|
+
report_obj.download_linked_reports(self, repo_key, dataset_id, folder_path)
|
|
1555
|
+
except Exception as err:
|
|
1556
|
+
raise err
|
|
1557
|
+
|
|
1540
1558
|
@Track.track_decorator
|
|
1541
1559
|
def delete_linked_report(
|
|
1542
1560
|
self, repo_key: str, dataset_id: str, report_id: str
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from polly_interfaces.IReporting import IReporting
|
|
2
3
|
from polly.errors import error_handler, InvalidParameterException
|
|
3
4
|
import json
|
|
5
|
+
import urllib.parse
|
|
4
6
|
import pandas as pd
|
|
5
7
|
from polly import helpers
|
|
6
8
|
from datetime import datetime
|
|
7
9
|
from urllib.parse import urlparse
|
|
8
10
|
from polly_services import polly_services_hlpr
|
|
9
11
|
from polly_services.reporting import reporting_hlpr
|
|
12
|
+
from polly.errors import (
|
|
13
|
+
InvalidParameterException,
|
|
14
|
+
error_handler,
|
|
15
|
+
InvalidDirectoryPath,
|
|
16
|
+
)
|
|
10
17
|
|
|
11
18
|
|
|
12
19
|
class Reporting(IReporting):
|
|
@@ -268,6 +275,100 @@ class Reporting(IReporting):
|
|
|
268
275
|
pd.set_option("display.max_colwidth", None)
|
|
269
276
|
return df
|
|
270
277
|
|
|
278
|
+
def download_linked_reports(
|
|
279
|
+
self, polly_session, repo_key: str, dataset_id: str, local_folder_path: str
|
|
280
|
+
):
|
|
281
|
+
"""Download linked reports to the local path
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
polly_session : polly_session variable
|
|
285
|
+
repo_key (str): repo_key for the omixatlas
|
|
286
|
+
dataset_id (str): dataset_id for the repo
|
|
287
|
+
local_folder_path (str): _description_
|
|
288
|
+
"""
|
|
289
|
+
# sanity check of variables
|
|
290
|
+
if not (repo_key and isinstance(repo_key, str)):
|
|
291
|
+
raise InvalidParameterException("repo_key")
|
|
292
|
+
if not (dataset_id and isinstance(dataset_id, str)):
|
|
293
|
+
raise InvalidParameterException("dataset_id")
|
|
294
|
+
|
|
295
|
+
isExists = os.path.isdir(local_folder_path)
|
|
296
|
+
if not isExists:
|
|
297
|
+
raise InvalidDirectoryPath(local_folder_path)
|
|
298
|
+
|
|
299
|
+
# get the resultant dataframe from fetch_linked_reports function
|
|
300
|
+
df = self.fetch_linked_reports(polly_session, repo_key, dataset_id)
|
|
301
|
+
|
|
302
|
+
if df is None:
|
|
303
|
+
print("No reports to download")
|
|
304
|
+
return
|
|
305
|
+
|
|
306
|
+
urls_list = []
|
|
307
|
+
# iterate on the DF and get the report_ids
|
|
308
|
+
for index, row in df.iterrows():
|
|
309
|
+
# print(row)
|
|
310
|
+
urls_list.append(row["URL"])
|
|
311
|
+
|
|
312
|
+
files_signed_urls_list = []
|
|
313
|
+
|
|
314
|
+
file_id_list = []
|
|
315
|
+
|
|
316
|
+
for url in urls_list:
|
|
317
|
+
parsed_url = urllib.parse.urlparse(url)
|
|
318
|
+
|
|
319
|
+
# Extract the query string parameters
|
|
320
|
+
query_params = urllib.parse.parse_qs(parsed_url.query)
|
|
321
|
+
|
|
322
|
+
# Get the value of the 'id' parameter
|
|
323
|
+
# id will be list here
|
|
324
|
+
file_id = query_params.get("id")
|
|
325
|
+
|
|
326
|
+
# Print the extracted ID
|
|
327
|
+
if file_id:
|
|
328
|
+
# Assuming 'id' exists and has only one value
|
|
329
|
+
file_id_list.append(file_id[0])
|
|
330
|
+
else:
|
|
331
|
+
print(f"ID not found in the file URL: {url}")
|
|
332
|
+
|
|
333
|
+
# call the API on the report_id to get list of all signed urls
|
|
334
|
+
for file_id in file_id_list:
|
|
335
|
+
params = {"action": "file_download"}
|
|
336
|
+
url = f"{polly_session.base_url}/shared-files/{file_id}"
|
|
337
|
+
|
|
338
|
+
response = polly_session.session.get(url, params=params)
|
|
339
|
+
error_handler(response)
|
|
340
|
+
response_json = response.json()
|
|
341
|
+
|
|
342
|
+
# structure of response
|
|
343
|
+
"""
|
|
344
|
+
{
|
|
345
|
+
"data":{
|
|
346
|
+
"type":"file",
|
|
347
|
+
"id":"15374/renamed - another.xlsx",
|
|
348
|
+
"attributes":{
|
|
349
|
+
"s3_key":"15374/renamed - another.xlsx",
|
|
350
|
+
"last_modified":"2024-04-11 04:28:35.000000",
|
|
351
|
+
"size":"8.94 KB",
|
|
352
|
+
"file_name":""
|
|
353
|
+
},
|
|
354
|
+
"links":{
|
|
355
|
+
"self":"/projects/15374/files/renamed%20-%20another.xlsx",
|
|
356
|
+
"signed_url": "<signed_url>"
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
"""
|
|
361
|
+
signed_url_val = response_json.get("data").get("links").get("signed_url")
|
|
362
|
+
files_signed_urls_list.append(signed_url_val)
|
|
363
|
+
|
|
364
|
+
try:
|
|
365
|
+
# iterate over signed urls and download it in the provided local file path
|
|
366
|
+
reporting_hlpr.download_from_s3_signedUrls(
|
|
367
|
+
files_signed_urls_list, local_folder_path
|
|
368
|
+
)
|
|
369
|
+
except Exception as err:
|
|
370
|
+
raise err
|
|
371
|
+
|
|
271
372
|
def delete_linked_report(
|
|
272
373
|
self, polly_session, repo_key: str, dataset_id: str, report_id: str
|
|
273
374
|
):
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
import urllib
|
|
3
4
|
from polly import helpers
|
|
4
5
|
from cloudpathlib import S3Client
|
|
5
6
|
from polly.errors import error_handler
|
|
6
7
|
from urllib.parse import quote
|
|
7
8
|
from polly.errors import paramException, AccessDeniedError
|
|
9
|
+
from tqdm import tqdm
|
|
10
|
+
import requests
|
|
8
11
|
|
|
9
12
|
|
|
10
13
|
def verify_workspace_path(cloud_path: str, credentials: dict) -> tuple:
|
|
@@ -232,3 +235,52 @@ def split_workspace_path(absolute_path: str) -> tuple:
|
|
|
232
235
|
for item in range(2, len(contents)):
|
|
233
236
|
workspace_path = helpers.make_path(workspace_path, contents[item])
|
|
234
237
|
return workspace_id, workspace_path
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def download_from_s3_signedUrls(urls: str, local_folder: str):
|
|
241
|
+
"""
|
|
242
|
+
Downloads files from a list of AWS signed URLs to a local folder.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
urls: A list of strings containing the AWS signed URLs.
|
|
246
|
+
local_folder: The path to the local folder where files will be downloaded.
|
|
247
|
+
"""
|
|
248
|
+
# Create directory if it doesn't exist
|
|
249
|
+
os.makedirs(local_folder, exist_ok=True)
|
|
250
|
+
|
|
251
|
+
for url in urls:
|
|
252
|
+
parsed_url = urllib.parse.urlparse(url)
|
|
253
|
+
path = parsed_url.path
|
|
254
|
+
filename = os.path.basename(path)
|
|
255
|
+
# print(filename)
|
|
256
|
+
print(f"Starting report download {filename}")
|
|
257
|
+
local_path = os.path.join(local_folder, filename)
|
|
258
|
+
|
|
259
|
+
try:
|
|
260
|
+
response = requests.get(url, stream=True)
|
|
261
|
+
error_handler(response)
|
|
262
|
+
|
|
263
|
+
# tqdm implement
|
|
264
|
+
with open(local_path, "wb") as f:
|
|
265
|
+
chunk_size = 4096
|
|
266
|
+
total_size = int(response.headers.get('Content-Length', 0))
|
|
267
|
+
|
|
268
|
+
# Create a progress bar with total size (if available)
|
|
269
|
+
pbar = tqdm(
|
|
270
|
+
total=total_size,
|
|
271
|
+
unit='B',
|
|
272
|
+
unit_scale=True,
|
|
273
|
+
unit_divisor=4096
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
for chunk in response.iter_content(chunk_size=chunk_size):
|
|
277
|
+
if chunk: # Filter out keep-alive new chunks
|
|
278
|
+
f.write(chunk)
|
|
279
|
+
pbar.update(len(chunk)) # Update progress bar with downloaded chunk size
|
|
280
|
+
|
|
281
|
+
pbar.close() # Close the progress bar after download
|
|
282
|
+
print()
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
except requests.exceptions.RequestException as e:
|
|
286
|
+
print(f"Error downloading {filename} from s3: {e}")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.6.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|