qmenta-client 2.1.dev1508__tar.gz → 2.1.dev1510__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,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: qmenta-client
3
- Version: 2.1.dev1508
3
+ Version: 2.1.dev1510
4
4
  Summary: Python client lib to interact with the QMENTA platform.
5
5
  Author: QMENTA
6
6
  Author-email: dev@qmenta.com
@@ -13,5 +13,6 @@ Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
15
  Requires-Dist: future (>=0.18.2,<0.19.0)
16
+ Requires-Dist: pytest-cov (>=6.1.1,<7.0.0)
16
17
  Requires-Dist: qmenta-core (>=4.0.1,<5.0.0)
17
18
  Project-URL: Homepage, https://www.qmenta.com/
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "qmenta-client"
3
- version = "2.1.dev1508"
3
+ version = "2.1.dev1510"
4
4
  description = "Python client lib to interact with the QMENTA platform."
5
5
  authors = ["QMENTA <dev@qmenta.com>"]
6
6
  homepage = "https://www.qmenta.com/"
@@ -16,6 +16,7 @@ packages = [
16
16
  python = "^3.10"
17
17
  future = "^0.18.2"
18
18
  qmenta-core = "^4.0.1"
19
+ pytest-cov = "^6.1.1"
19
20
 
20
21
  [tool.poetry.group.dev.dependencies]
21
22
  pytest = "^7.1.2"
@@ -25,6 +26,7 @@ dom-toml = "^0.6.0"
25
26
  scriv = {version = "^0.15.2", extras = ["toml"]}
26
27
  coverage = "^7.2.5"
27
28
  flake8 = "^7.1.2"
29
+ responses = "^0.25.7"
28
30
 
29
31
 
30
32
  [build-system]
@@ -1,10 +1,9 @@
1
1
  from __future__ import print_function
2
2
 
3
3
  import logging
4
- from urllib3.exceptions import HTTPError
5
-
6
- from qmenta.core import platform
7
4
  from qmenta.core import errors
5
+ from qmenta.core import platform
6
+ from urllib3.exceptions import HTTPError
8
7
 
9
8
  from .Project import Project
10
9
  from .utils import load_json
@@ -35,7 +34,13 @@ class Account:
35
34
  The Auth object used for communication with the platform
36
35
  """
37
36
 
38
- def __init__(self, username, password, base_url="https://platform.qmenta.com", verify_certificates=True):
37
+ def __init__(
38
+ self,
39
+ username,
40
+ password,
41
+ base_url="https://platform.qmenta.com",
42
+ verify_certificates=True,
43
+ ):
39
44
 
40
45
  self._cookie = None
41
46
  self.username = username
@@ -62,7 +67,12 @@ class Account:
62
67
  """
63
68
  logger = logging.getLogger(logger_name)
64
69
  try:
65
- auth = platform.Auth.login(self.username, self.password, base_url=self.baseurl, ask_for_2fa_input=True)
70
+ auth = platform.Auth.login(
71
+ self.username,
72
+ self.password,
73
+ base_url=self.baseurl,
74
+ ask_for_2fa_input=True,
75
+ )
66
76
  except errors.PlatformError as e:
67
77
  logger.error("Failed to log in: {}".format(e))
68
78
  self.auth = None
@@ -109,10 +119,16 @@ class Account:
109
119
  return Project(self, int(project_id))
110
120
  elif type(project_id) is str:
111
121
  projects = self.projects
112
- projects_match = [proj for proj in projects if proj["name"] == project_id]
122
+ projects_match = [
123
+ proj for proj in projects if proj["name"] == project_id
124
+ ]
113
125
  if not projects_match:
114
- raise Exception(f"Project {project_id} does not exist or is not available for this user.")
126
+ raise Exception(
127
+ f"Project {project_id} does not exist or is not available "
128
+ f"for this user."
129
+ )
115
130
  return Project(self, int(projects_match[0]["id"]))
131
+ return None
116
132
 
117
133
  @property
118
134
  def projects(self):
@@ -127,7 +143,11 @@ class Account:
127
143
  logger = logging.getLogger(logger_name)
128
144
 
129
145
  try:
130
- data = platform.parse_response(platform.post(self.auth, "projectset_manager/get_projectset_list"))
146
+ data = platform.parse_response(
147
+ platform.post(
148
+ self.auth, "projectset_manager/get_projectset_list"
149
+ )
150
+ )
131
151
  except errors.PlatformError as e:
132
152
  logger.error("Failed to get project list: {}".format(e))
133
153
  raise
@@ -137,7 +157,15 @@ class Account:
137
157
  titles.append({"name": project["name"], "id": project["_id"]})
138
158
  return titles
139
159
 
140
- def add_project(self, project_abbreviation, project_name, description="", users=None, from_date="", to_date=""):
160
+ def add_project(
161
+ self,
162
+ project_abbreviation,
163
+ project_name,
164
+ description="",
165
+ users=None,
166
+ from_date="",
167
+ to_date="",
168
+ ):
141
169
  """
142
170
  Add a new project to the user account.
143
171
 
@@ -256,7 +284,9 @@ class Account:
256
284
  preload_content=not stream,
257
285
  )
258
286
  if response.status >= 400:
259
- raise HTTPError("STATUS {}: {}".format(response.status, response.reason))
287
+ raise HTTPError(
288
+ "STATUS {}: {}".format(response.status, response.reason)
289
+ )
260
290
  except Exception as e:
261
291
  error = "Could not send request. ERROR: {0}".format(e)
262
292
  logger.error(error)
@@ -278,7 +308,9 @@ class Account:
278
308
  try:
279
309
  parsed_content = load_json(response.data)
280
310
  except Exception:
281
- error = "Could not parse the response as JSON data: {}".format(response.data)
311
+ error = "Could not parse the response as JSON data: {}".format(
312
+ response.data
313
+ )
282
314
  logger.error(error)
283
315
  raise
284
316
 
@@ -32,12 +32,21 @@ class File:
32
32
  `ff_container = File(project, "MRB", "1", "gre_field_mapping_3.zip")`
33
33
  """
34
34
 
35
- def __init__(self, project: qmenta.client.Project, subject_name: str, ssid: str, file_name: str):
35
+ def __init__(
36
+ self,
37
+ project: qmenta.client.Project,
38
+ subject_name: str,
39
+ ssid: str,
40
+ file_name: str,
41
+ ):
36
42
  self.file_name = file_name
37
43
  self.project = project
38
44
  self._container_id = None
39
45
  for cont in self.project.list_input_containers():
40
- if cont["patient_secret_name"] == subject_name and cont["ssid"] == ssid:
46
+ if (
47
+ cont["patient_secret_name"] == subject_name
48
+ and cont["ssid"] == ssid
49
+ ):
41
50
  self._container_id = cont["container_id"]
42
51
  break
43
52
  if self.file_name.endswith(".zip"):
@@ -50,7 +59,9 @@ class File:
50
59
  def __str__(self):
51
60
  return self.file_name
52
61
 
53
- def pull_scan_sequence_info(self, specify_dicom_tags=None, output_format: str = "csv"):
62
+ def pull_scan_sequence_info(
63
+ self, specify_dicom_tags=None, output_format: str = "csv"
64
+ ):
54
65
  """
55
66
  Pulling scan sequence information (e.g. series number, series type,
56
67
  series description, number of files, file formats available)
@@ -74,11 +85,18 @@ class File:
74
85
  if specify_dicom_tags is None:
75
86
  specify_dicom_tags = list()
76
87
  valid_output_formats = ["csv", "tsv", "json", "dict"]
77
- assert output_format in valid_output_formats, f"Output format not valid. Choose one of {valid_output_formats}"
88
+ assert (
89
+ output_format in valid_output_formats
90
+ ), f"Output format not valid. Choose one of {valid_output_formats}"
78
91
 
79
92
  with TemporaryDirectory() as temp_dir:
80
93
  local_file_name = mkstemp(dir=temp_dir) + ".zip"
81
- self.project.download_file(self._container_id, self.file_name, local_file_name, overwrite=False)
94
+ self.project.download_file(
95
+ self._container_id,
96
+ self.file_name,
97
+ local_file_name,
98
+ overwrite=False,
99
+ )
82
100
  if self._file_type == "DICOM":
83
101
  unzip_dicoms(local_file_name, temp_dir, exclude_members=None)
84
102
  dicoms = glob.glob(os.path.join(temp_dir, "*"))
@@ -92,11 +110,21 @@ class File:
92
110
  # only needed for one file, all have the same data.
93
111
  for attribute in specify_dicom_tags:
94
112
  # error handling of attributes send by the user
95
- assert len(attribute) == 2, "Invalid length of DICOM Attribute"
96
- assert isinstance(attribute[0], int), "Invalid type of DICOM Attribute"
97
- output_data["dicom tag"].append(open_file[attribute].tag)
98
- output_data["attribute"].append(open_file[attribute].name)
99
- output_data["value"].append(open_file[attribute].value)
113
+ assert (
114
+ len(attribute) == 2
115
+ ), "Invalid length of DICOM Attribute"
116
+ assert isinstance(
117
+ attribute[0], int
118
+ ), "Invalid type of DICOM Attribute"
119
+ output_data["dicom tag"].append(
120
+ open_file[attribute].tag
121
+ )
122
+ output_data["attribute"].append(
123
+ open_file[attribute].name
124
+ )
125
+ output_data["value"].append(
126
+ open_file[attribute].value
127
+ )
100
128
  except Exception as e:
101
129
  print(str(e))
102
130
  pass
@@ -106,10 +134,14 @@ class File:
106
134
  output_data["value"].append(number_files)
107
135
 
108
136
  if output_format == "csv":
109
- pd.DataFrame(output_data).to_csv(f"scan_sequence_info.{output_format}", index=False)
137
+ pd.DataFrame(output_data).to_csv(
138
+ f"scan_sequence_info.{output_format}", index=False
139
+ )
110
140
 
111
141
  elif output_format == "tsv":
112
- pd.DataFrame(output_data).to_csv(f"scan_sequence_info.{output_format}", sep="\t", index=False)
142
+ pd.DataFrame(output_data).to_csv(
143
+ f"scan_sequence_info.{output_format}", sep="\t", index=False
144
+ )
113
145
 
114
146
  elif output_format == "json":
115
147
  with open(f"scan_sequence_info.{output_format}", "w") as fp: