willisapi-client 1.8__tar.gz → 1.9__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.
Files changed (45) hide show
  1. {willisapi_client-1.8 → willisapi_client-1.9}/PKG-INFO +1 -1
  2. willisapi_client-1.9/tests/test_diarize.py +64 -0
  3. willisapi_client-1.9/tests/test_diarize_call_remaining.py +42 -0
  4. willisapi_client-1.9/willisapi_client/__init__.py +18 -0
  5. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/__version__.py +2 -1
  6. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/api.py +4 -0
  7. willisapi_client-1.9/willisapi_client/services/diarize/__init__.py +7 -0
  8. willisapi_client-1.9/willisapi_client/services/diarize/diarize_utils.py +99 -0
  9. willisapi_client-1.9/willisapi_client/services/diarize/willisdiarize.py +52 -0
  10. willisapi_client-1.9/willisapi_client/services/diarize/willisdiarize_call_remaining.py +28 -0
  11. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/download/download_utils.py +5 -5
  12. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/upload/csv_validation.py +3 -1
  13. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/upload/upload_utils.py +3 -2
  14. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/willisapi_client.py +6 -3
  15. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client.egg-info/PKG-INFO +1 -1
  16. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client.egg-info/SOURCES.txt +6 -0
  17. willisapi_client-1.8/willisapi_client/__init__.py +0 -10
  18. {willisapi_client-1.8 → willisapi_client-1.9}/LICENSE +0 -0
  19. {willisapi_client-1.8 → willisapi_client-1.9}/MANIFEST.in +0 -0
  20. {willisapi_client-1.8 → willisapi_client-1.9}/README.md +0 -0
  21. {willisapi_client-1.8 → willisapi_client-1.9}/RELEASE.md +0 -0
  22. {willisapi_client-1.8 → willisapi_client-1.9}/requirements.txt +0 -0
  23. {willisapi_client-1.8 → willisapi_client-1.9}/setup.cfg +0 -0
  24. {willisapi_client-1.8 → willisapi_client-1.9}/setup.py +0 -0
  25. {willisapi_client-1.8 → willisapi_client-1.9}/tests/test_auth.py +0 -0
  26. {willisapi_client-1.8 → willisapi_client-1.9}/tests/test_csv_validation.py +0 -0
  27. {willisapi_client-1.8 → willisapi_client-1.9}/tests/test_download.py +0 -0
  28. {willisapi_client-1.8 → willisapi_client-1.9}/tests/test_upload.py +0 -0
  29. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/logging_setup.py +0 -0
  30. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/__init__.py +0 -0
  31. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/auth/__init__.py +0 -0
  32. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/auth/auth_utils.py +0 -0
  33. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/auth/login_manager.py +0 -0
  34. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/download/__init__.py +0 -0
  35. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/download/download_handler.py +0 -0
  36. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/exceptions.py +0 -0
  37. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/upload/__init__.py +0 -0
  38. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/upload/language_choices.py +0 -0
  39. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/upload/multipart_upload_handler.py +0 -0
  40. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/services/upload/utils.py +0 -0
  41. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client/timer.py +0 -0
  42. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client.egg-info/dependency_links.txt +0 -0
  43. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client.egg-info/not-zip-safe +0 -0
  44. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client.egg-info/requires.txt +0 -0
  45. {willisapi_client-1.8 → willisapi_client-1.9}/willisapi_client.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: willisapi_client
3
- Version: 1.8
3
+ Version: 1.9
4
4
  Summary: A Python client for willisapi
5
5
  Home-page: https://github.com/bklynhlth/willsiapi_client
6
6
  Author: bklynhlth
@@ -0,0 +1,64 @@
1
+ from unittest.mock import patch
2
+
3
+ from willisapi_client.services.diarize.willisdiarize import (
4
+ willis_diarize,
5
+ )
6
+ from willisapi_client.logging_setup import logger as logger
7
+ import logging
8
+
9
+
10
+ class TestDiarizeFunction:
11
+ def setup(self):
12
+ self.key = "dummy"
13
+ self.file_path = "file.json"
14
+
15
+ @patch(
16
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.decode_response"
17
+ )
18
+ @patch(
19
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_diarize"
20
+ )
21
+ @patch(
22
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.read_json_file"
23
+ )
24
+ @patch(
25
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.is_valid_file_path"
26
+ )
27
+ def test_willis_diarize_function_success(
28
+ self, mock_file_path, mock_json, mock_api_res, mock_decoded_res, caplog
29
+ ):
30
+ mock_file_path.return_value = True
31
+ mock_json.return_value = {"Correct Transcription"}
32
+ mock_api_res.return_value = {
33
+ "status_code": 200,
34
+ "data": "Encoded Response",
35
+ }
36
+ mock_decoded_res.return_value = {"Correct Transcription"}
37
+ with caplog.at_level(logging.INFO):
38
+ res = willis_diarize(self.key, self.file_path)
39
+
40
+ assert res == {"Correct Transcription"}
41
+
42
+ @patch(
43
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_diarize"
44
+ )
45
+ @patch(
46
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.read_json_file"
47
+ )
48
+ @patch(
49
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.is_valid_file_path"
50
+ )
51
+ def test_willis_diarize_function_invalid_json(
52
+ self, mock_file_path, mock_json, mock_api_res, caplog
53
+ ):
54
+ mock_file_path.return_value = False
55
+ mock_json.return_value = {}
56
+ mock_api_res.return_value = {
57
+ "status_code": 200,
58
+ "data": "Encoded Response",
59
+ }
60
+
61
+ with caplog.at_level(logging.INFO):
62
+ res = willis_diarize(self.key, self.file_path)
63
+
64
+ assert "Input file type is incorrect. We only accept JSON files" in caplog.text
@@ -0,0 +1,42 @@
1
+ from unittest.mock import patch
2
+
3
+ from willisapi_client.services.diarize.willisdiarize_call_remaining import (
4
+ willis_diarize_call_remaining,
5
+ )
6
+ from willisapi_client.logging_setup import logger as logger
7
+ import logging
8
+
9
+
10
+ class TestDiarizeCallsFunction:
11
+ def setup(self):
12
+ self.key = "dummy"
13
+
14
+ @patch(
15
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_call_remaining"
16
+ )
17
+ def test_willisdiarize_remaining_calls_failed(self, mocked_data, caplog):
18
+ mocked_data.return_value = {}
19
+ with caplog.at_level(logging.INFO):
20
+ willis_diarize_call_remaining(self.key)
21
+ assert "" in caplog.text
22
+
23
+ @patch(
24
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_call_remaining"
25
+ )
26
+ def test_willisdiarize_remaining_calls_missing_auth(self, mocked_data, caplog):
27
+ mocked_data.return_value = {"status_code": 401, "message": "message"}
28
+ with caplog.at_level(logging.INFO):
29
+ willis_diarize_call_remaining(self.key)
30
+ assert "message" in caplog.text
31
+
32
+ @patch(
33
+ "willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_call_remaining"
34
+ )
35
+ def test_willisdiarize_remaining_calls_success(self, mocked_data, caplog):
36
+ mocked_data.return_value = {
37
+ "status_code": 401,
38
+ "message": "Your account has 10 WillisDiarize API calls remaining.",
39
+ }
40
+ with caplog.at_level(logging.INFO):
41
+ willis_diarize_call_remaining(self.key)
42
+ assert "Your account has 10 WillisDiarize API calls remaining." in caplog.text
@@ -0,0 +1,18 @@
1
+ # website: https://www.brooklyn.health
2
+
3
+ # import the required packages
4
+ from willisapi_client.services.api import (
5
+ login,
6
+ upload,
7
+ download,
8
+ willis_diarize_call_remaining,
9
+ willis_diarize,
10
+ )
11
+
12
+ __all__ = [
13
+ "login",
14
+ "upload",
15
+ "download",
16
+ "willis_diarize_call_remaining",
17
+ "willis_diarize",
18
+ ]
@@ -1,7 +1,8 @@
1
1
  """Version details for willisapi_client
2
2
  """
3
+
3
4
  __client__ = "willisapi_client"
4
- __latestVersion__ = "1.8"
5
+ __latestVersion__ = "1.9"
5
6
  __url__ = "https://github.com/bklynhlth/willsiapi_client"
6
7
  __short_description__ = "A Python client for willisapi"
7
8
  __content_type__ = "text/markdown"
@@ -4,3 +4,7 @@
4
4
  from willisapi_client.services.auth import login
5
5
  from willisapi_client.services.upload import upload
6
6
  from willisapi_client.services.download import download
7
+ from willisapi_client.services.diarize import (
8
+ willis_diarize_call_remaining,
9
+ willis_diarize,
10
+ )
@@ -0,0 +1,7 @@
1
+ # website: https://www.brooklyn.health
2
+ from willisapi_client.services.diarize.willisdiarize_call_remaining import (
3
+ willis_diarize_call_remaining,
4
+ )
5
+ from willisapi_client.services.diarize.willisdiarize import willis_diarize
6
+
7
+ __all__ = ["willis_diarize_call_remaining", "willis_diarize"]
@@ -0,0 +1,99 @@
1
+ import requests
2
+ import json
3
+ import time
4
+ import random
5
+ import os
6
+ import gzip
7
+ import base64
8
+ from willisapi_client.logging_setup import logger as logger
9
+
10
+
11
+ class DiarizeUtils:
12
+ def is_valid_file_path(file_path: str):
13
+ return file_path.endswith(".json") and os.path.exists(file_path)
14
+
15
+ def read_json_file(file_path: str):
16
+ data = None
17
+ try:
18
+ with open(file_path) as f:
19
+ json_data = json.load(f)
20
+ data = dict(json_data=json_data)
21
+ except json.decoder.JSONDecodeError:
22
+ logger.info("No data found in the file or JSON is invalid.")
23
+ logger.info("Failed!")
24
+ return data
25
+
26
+ def decode_response(encoded_response):
27
+ return json.loads(gzip.decompress(base64.b64decode(encoded_response)))
28
+
29
+ def request_diarize(url, data, headers, try_number):
30
+ """
31
+ ------------------------------------------------------------------------------------------------------
32
+ Class: DiarizeUtils
33
+
34
+ Function: request_diarize
35
+
36
+ Description: This is an internal diarize function which makes a GET API call to brooklyn.health API server
37
+
38
+ Parameters:
39
+ ----------
40
+ url: The URL of the API endpoint.
41
+ headers: The headers to be sent in the request.
42
+ try_number: The number of times the function has been tried.
43
+
44
+ Returns:
45
+ ----------
46
+ json: The JSON response from the API server.
47
+ ------------------------------------------------------------------------------------------------------
48
+ """
49
+ try:
50
+ response = requests.post(url, json=data, headers=headers)
51
+ res_json = response.json()
52
+ except (
53
+ requests.exceptions.ConnectionError,
54
+ json.decoder.JSONDecodeError,
55
+ ) as ex:
56
+ if try_number == 3:
57
+ raise
58
+ time.sleep(random.random() * 2)
59
+ return DiarizeUtils.request_diarize(
60
+ url, data, headers, try_number=try_number + 1
61
+ )
62
+ else:
63
+ return res_json
64
+
65
+ def request_call_remaining(url, headers, try_number):
66
+ """
67
+ ------------------------------------------------------------------------------------------------------
68
+ Class: DiarizeUtils
69
+
70
+ Function: request_call_remaining
71
+
72
+ Description: This is an internal diarize function which makes a GET API call to brooklyn.health API server
73
+
74
+ Parameters:
75
+ ----------
76
+ url: The URL of the API endpoint.
77
+ headers: The headers to be sent in the request.
78
+ try_number: The number of times the function has been tried.
79
+
80
+ Returns:
81
+ ----------
82
+ json: The JSON response from the API server.
83
+ ------------------------------------------------------------------------------------------------------
84
+ """
85
+ try:
86
+ response = requests.get(url, headers=headers)
87
+ res_json = response.json()
88
+ except (
89
+ requests.exceptions.ConnectionError,
90
+ json.decoder.JSONDecodeError,
91
+ ) as ex:
92
+ if try_number == 3:
93
+ raise
94
+ time.sleep(random.random() * 2)
95
+ return DiarizeUtils.request_call_remaining(
96
+ url, headers, try_number=try_number + 1
97
+ )
98
+ else:
99
+ return res_json
@@ -0,0 +1,52 @@
1
+ from http import HTTPStatus
2
+
3
+ from willisapi_client.willisapi_client import WillisapiClient
4
+ from willisapi_client.logging_setup import logger as logger
5
+ from willisapi_client.services.diarize.diarize_utils import DiarizeUtils
6
+
7
+
8
+ def willis_diarize(key: str, file_path: str, **kwargs):
9
+ """
10
+ ---------------------------------------------------------------------------------------------------
11
+ Function: willis_diarize
12
+
13
+ Description: This function makes call to WillisDiarize Model
14
+
15
+ Parameters:
16
+ ----------
17
+ key: AWS access id token (str)
18
+ file_path: String
19
+
20
+ Returns:
21
+ ----------
22
+ json: JSON
23
+ ---------------------------------------------------------------------------------------------------
24
+ """
25
+
26
+ logger.info("Passing through WillisDiarize...")
27
+ wc = WillisapiClient(env=kwargs.get("env"))
28
+ url = wc.get_diarize()
29
+ headers = wc.get_headers()
30
+ headers["Authorization"] = key
31
+ corrected_transcript = None
32
+
33
+ if not DiarizeUtils.is_valid_file_path(file_path):
34
+ logger.info("Input file type is incorrect. We only accept JSON files.")
35
+ logger.info("Failed!")
36
+ return corrected_transcript
37
+
38
+ data = DiarizeUtils.read_json_file(file_path)
39
+
40
+ if not data:
41
+ return corrected_transcript
42
+
43
+ response = DiarizeUtils.request_diarize(url, data, headers, try_number=1)
44
+ if response["status_code"] != HTTPStatus.OK:
45
+ logger.info(response["message"])
46
+ logger.info("Failed!")
47
+ else:
48
+ logger.info("Returning processed JSON...")
49
+ encoded_response = response["data"]
50
+ corrected_transcript = DiarizeUtils.decode_response(encoded_response)
51
+ logger.info("Done!")
52
+ return corrected_transcript
@@ -0,0 +1,28 @@
1
+ from http import HTTPStatus
2
+
3
+ from willisapi_client.willisapi_client import WillisapiClient
4
+ from willisapi_client.logging_setup import logger as logger
5
+ from willisapi_client.services.diarize.diarize_utils import DiarizeUtils
6
+
7
+
8
+ def willis_diarize_call_remaining(key: str, **kwargs):
9
+ """
10
+ ---------------------------------------------------------------------------------------------------
11
+ Function: willis_diarize_call_remaining
12
+
13
+ Description: This function returns the number of remaining calls for willisdiarize
14
+
15
+ Parameters:
16
+ ----------
17
+ key: AWS access id token (str)
18
+ ---------------------------------------------------------------------------------------------------
19
+ """
20
+
21
+ wc = WillisapiClient(env=kwargs.get("env"))
22
+ url = wc.get_diarize_remaining_calls_url()
23
+ headers = wc.get_headers()
24
+ headers["Authorization"] = key
25
+
26
+ response = DiarizeUtils.request_call_remaining(url, headers, try_number=1)
27
+ if response:
28
+ logger.info(response["message"])
@@ -7,7 +7,7 @@ from typing import Tuple
7
7
  from http import HTTPStatus
8
8
 
9
9
 
10
- vocal_acoustic_summary = "vocal_acoustics_summary"
10
+ vocal_acoustics_simple_summary = "vocal_acoustics_simple_summary"
11
11
  speech_characteristics_summary = "speech_characteristics_summary"
12
12
  rater_qa_summary = "rater_qa_summary"
13
13
 
@@ -164,7 +164,7 @@ class DownloadUtils:
164
164
  and measures_dict[workflow_tag]
165
165
  and workflow_tag
166
166
  in [
167
- vocal_acoustic_summary,
167
+ vocal_acoustics_simple_summary,
168
168
  speech_characteristics_summary,
169
169
  rater_qa_summary,
170
170
  ]
@@ -239,9 +239,9 @@ class DownloadUtils:
239
239
  columns=DownloadUtils._get_defined_columns(),
240
240
  )
241
241
 
242
- vocal_acoustics_summary_df = (
242
+ vocal_acoustics_simple_summary_df = (
243
243
  DownloadUtils._get_summary_df_from_json(
244
- data, pt, rec, vocal_acoustic_summary
244
+ data, pt, rec, vocal_acoustics_simple_summary
245
245
  )
246
246
  )
247
247
  speech_characteristics_summary_df = (
@@ -255,7 +255,7 @@ class DownloadUtils:
255
255
  df = pd.concat(
256
256
  [
257
257
  main_df,
258
- vocal_acoustics_summary_df,
258
+ vocal_acoustics_simple_summary_df,
259
259
  speech_characteristics_summary_df,
260
260
  rater_qa_summary_df,
261
261
  ],
@@ -53,7 +53,7 @@ class CSVValidation:
53
53
  }
54
54
  self.gender_field = ["M", "F"]
55
55
  self.workflow_tags = [
56
- "vocal_acoustics",
56
+ "vocal_acoustics_simple",
57
57
  "speech_characteristics",
58
58
  "speech_transcription_aws",
59
59
  "voice_and_speech",
@@ -71,6 +71,8 @@ class CSVValidation:
71
71
  "scale_",
72
72
  "speech_characteristics_",
73
73
  "rater_qa_",
74
+ "scale_wd_",
75
+ "rater_qa_wd_",
74
76
  ]
75
77
  self.collect_time_format = r"^\d{4}-\d{2}-\d{2}$"
76
78
  self.df = None
@@ -305,6 +305,7 @@ class UploadUtils:
305
305
  (upload_id, record_id, error) = UploadUtils.initiate_multi_part_upload(
306
306
  index, row, url, headers, force_upload
307
307
  )
308
+ filename = os.path.basename(row.file_path)
308
309
  uploaded = False
309
310
  if upload_id and record_id:
310
311
  presigned_urls, number_of_parts = UploadUtils.fetch_pre_signed_part_urls(
@@ -314,7 +315,7 @@ class UploadUtils:
314
315
  if len(presigned_urls) != number_of_parts:
315
316
  parts = json.dumps([])
316
317
  res = requests.post(
317
- f"{url}?type=complete&record_id={record_id}&upload_id={upload_id}&number_of_parts={number_of_parts}",
318
+ f"{url}?type=complete&record_id={record_id}&upload_id={upload_id}&number_of_parts={number_of_parts}&filename={filename}",
318
319
  json=parts,
319
320
  headers=headers,
320
321
  )
@@ -324,7 +325,7 @@ class UploadUtils:
324
325
  UploadUtils.close_file(file)
325
326
  parts = json.dumps(parts)
326
327
  res = requests.post(
327
- f"{url}?type=complete&record_id={record_id}&upload_id={upload_id}&number_of_parts={number_of_parts}",
328
+ f"{url}?type=complete&record_id={record_id}&upload_id={upload_id}&number_of_parts={number_of_parts}&filename={filename}",
328
329
  json=parts,
329
330
  headers=headers,
330
331
  )
@@ -25,14 +25,17 @@ class WillisapiClient:
25
25
  def get_login_url(self):
26
26
  return self.get_base_url() + "login"
27
27
 
28
- def get_signup_url(self):
29
- return self.get_base_url() + "signup"
30
-
31
28
  def get_upload_url(self):
32
29
  return self.get_base_url() + "upload"
33
30
 
34
31
  def get_download_url(self):
35
32
  return self.get_base_url() + "download"
36
33
 
34
+ def get_diarize_remaining_calls_url(self):
35
+ return self.get_base_url() + "willis-diarize-call-remaining"
36
+
37
+ def get_diarize(self):
38
+ return self.get_base_url() + "diarize"
39
+
37
40
  def get_headers(self):
38
41
  return {"Content-Type": "application/json", "Accept": "application/json"}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: willisapi-client
3
- Version: 1.8
3
+ Version: 1.9
4
4
  Summary: A Python client for willisapi
5
5
  Home-page: https://github.com/bklynhlth/willsiapi_client
6
6
  Author: bklynhlth
@@ -7,6 +7,8 @@ setup.cfg
7
7
  setup.py
8
8
  tests/test_auth.py
9
9
  tests/test_csv_validation.py
10
+ tests/test_diarize.py
11
+ tests/test_diarize_call_remaining.py
10
12
  tests/test_download.py
11
13
  tests/test_upload.py
12
14
  willisapi_client/__init__.py
@@ -26,6 +28,10 @@ willisapi_client/services/exceptions.py
26
28
  willisapi_client/services/auth/__init__.py
27
29
  willisapi_client/services/auth/auth_utils.py
28
30
  willisapi_client/services/auth/login_manager.py
31
+ willisapi_client/services/diarize/__init__.py
32
+ willisapi_client/services/diarize/diarize_utils.py
33
+ willisapi_client/services/diarize/willisdiarize.py
34
+ willisapi_client/services/diarize/willisdiarize_call_remaining.py
29
35
  willisapi_client/services/download/__init__.py
30
36
  willisapi_client/services/download/download_handler.py
31
37
  willisapi_client/services/download/download_utils.py
@@ -1,10 +0,0 @@
1
- # website: https://www.brooklyn.health
2
-
3
- # import the required packages
4
- from willisapi_client.services.api import (
5
- login,
6
- upload,
7
- download,
8
- )
9
-
10
- __all__ = ["login", "upload", "download"]
File without changes
File without changes
File without changes
File without changes