qmenta-client 1.1.dev1326__py3-none-any.whl → 1.1.dev1349__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.
- qmenta/client/Project.py +328 -77
- {qmenta_client-1.1.dev1326.dist-info → qmenta_client-1.1.dev1349.dist-info}/METADATA +1 -1
- {qmenta_client-1.1.dev1326.dist-info → qmenta_client-1.1.dev1349.dist-info}/RECORD +4 -4
- {qmenta_client-1.1.dev1326.dist-info → qmenta_client-1.1.dev1349.dist-info}/WHEEL +0 -0
qmenta/client/Project.py
CHANGED
|
@@ -200,14 +200,45 @@ def wrap_search_criteria(search_criteria={}):
|
|
|
200
200
|
return modality, tags, file_metadata
|
|
201
201
|
|
|
202
202
|
|
|
203
|
+
def convert_qc_value_to_qcstatus(value):
|
|
204
|
+
"""
|
|
205
|
+
Convert input string to QCStatus class.
|
|
206
|
+
|
|
207
|
+
Parameters
|
|
208
|
+
----------
|
|
209
|
+
value : str
|
|
210
|
+
Value to convert.
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
QCStatus or Bool
|
|
215
|
+
QCStatus.PASS, QCStatus.FAIL or QCStatus.UNDETERMINED
|
|
216
|
+
False if the Value cannot be convered.
|
|
217
|
+
"""
|
|
218
|
+
logger = logging.getLogger(logger_name)
|
|
219
|
+
if value == "pass":
|
|
220
|
+
return QCStatus.PASS
|
|
221
|
+
elif value == "fail":
|
|
222
|
+
return QCStatus.FAIL
|
|
223
|
+
elif value == "":
|
|
224
|
+
return QCStatus.UNDERTERMINED
|
|
225
|
+
else:
|
|
226
|
+
logger.error(f"The input value '{value}' cannot be converted "
|
|
227
|
+
f"to class QCStatus.")
|
|
228
|
+
return False
|
|
229
|
+
|
|
230
|
+
|
|
203
231
|
class QCStatus(Enum):
|
|
204
232
|
"""
|
|
205
233
|
Enum with the following options:
|
|
206
|
-
FAIL, PASS
|
|
234
|
+
FAIL, PASS, UNDERTERMINED
|
|
235
|
+
that are the possible options for the QA/QC status of both
|
|
236
|
+
analysis and session.
|
|
207
237
|
"""
|
|
208
238
|
|
|
209
239
|
PASS = "pass"
|
|
210
240
|
FAIL = "fail"
|
|
241
|
+
UNDERTERMINED = ""
|
|
211
242
|
|
|
212
243
|
|
|
213
244
|
class Project:
|
|
@@ -644,10 +675,27 @@ class Project:
|
|
|
644
675
|
return data["fields"]
|
|
645
676
|
|
|
646
677
|
def get_analysis(self, analysis_name_or_id):
|
|
678
|
+
"""
|
|
679
|
+
Returns the analysis corresponding with the analysis id or analysis name
|
|
680
|
+
|
|
681
|
+
Parameters
|
|
682
|
+
----------
|
|
683
|
+
analysis_name_or_id : int, str
|
|
684
|
+
analysis_id or analysis name to search for
|
|
685
|
+
|
|
686
|
+
Returns
|
|
687
|
+
-------
|
|
688
|
+
analysis: dict
|
|
689
|
+
A dictionary containing the analysis information
|
|
690
|
+
"""
|
|
647
691
|
if isinstance(analysis_name_or_id, int):
|
|
648
692
|
search_tag = "id"
|
|
649
693
|
elif isinstance(analysis_name_or_id, str):
|
|
650
|
-
|
|
694
|
+
if analysis_name_or_id.isdigit():
|
|
695
|
+
search_tag = "id"
|
|
696
|
+
analysis_name_or_id = int(analysis_name_or_id)
|
|
697
|
+
else:
|
|
698
|
+
search_tag = "p_n"
|
|
651
699
|
else:
|
|
652
700
|
raise Exception("The analysis identifier must be its name or an " "integer")
|
|
653
701
|
|
|
@@ -667,32 +715,37 @@ class Project:
|
|
|
667
715
|
|
|
668
716
|
def list_analysis(self, search_condition={}, items=(0, 9999)):
|
|
669
717
|
"""
|
|
670
|
-
List the analysis available to the user
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
718
|
+
List the analysis available to the user.\n
|
|
719
|
+
|
|
720
|
+
Examples
|
|
721
|
+
--------
|
|
722
|
+
|
|
723
|
+
>>> search_condition = {
|
|
724
|
+
"secret_name":"014_S_6920",
|
|
725
|
+
"from_d": "06.02.2025",
|
|
726
|
+
"with_child_analysis": 1,
|
|
727
|
+
"state": "completed"
|
|
677
728
|
}
|
|
729
|
+
list_analysis(search_condition=search_condition)
|
|
678
730
|
|
|
679
731
|
Parameters
|
|
680
732
|
----------
|
|
681
733
|
search_condition : dict
|
|
682
|
-
p_n: str
|
|
683
|
-
type: str
|
|
684
|
-
from_d: str
|
|
685
|
-
to_d: str
|
|
686
|
-
qa_status: str
|
|
687
|
-
secret_name: str
|
|
688
|
-
tags: str
|
|
689
|
-
with_child_analysis: 1
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
734
|
+
- p_n: str Analysis name
|
|
735
|
+
- type: str Type
|
|
736
|
+
- from_d: str dd.mm.yyyy Date from
|
|
737
|
+
- to_d: str dd.mm.yyyy Date to
|
|
738
|
+
- qa_status: str pass/fail/nd QC status
|
|
739
|
+
- secret_name: str Subject ID
|
|
740
|
+
- tags: str
|
|
741
|
+
- with_child_analysis: 1 if 1, child analysis of workflows will appear
|
|
742
|
+
- id: str ID
|
|
743
|
+
- state: running, completed, pending, exception
|
|
744
|
+
- username: str
|
|
745
|
+
|
|
746
|
+
items : List[int]
|
|
747
|
+
list containing two elements [min, max] that correspond to the
|
|
748
|
+
mininum and maximum range of analysis listed
|
|
696
749
|
|
|
697
750
|
Returns
|
|
698
751
|
-------
|
|
@@ -811,23 +864,48 @@ class Project:
|
|
|
811
864
|
]
|
|
812
865
|
return containers
|
|
813
866
|
|
|
814
|
-
def list_result_containers(self,
|
|
867
|
+
def list_result_containers(self, search_condition={}, items=(0, 9999)):
|
|
815
868
|
"""
|
|
816
869
|
List the result containers available to the user.
|
|
870
|
+
Examples
|
|
871
|
+
--------
|
|
872
|
+
|
|
873
|
+
>>> search_condition = {
|
|
874
|
+
"secret_name":"014_S_6920",
|
|
875
|
+
"from_d": "06.02.2025",
|
|
876
|
+
"with_child_analysis": 1,
|
|
877
|
+
"state": "completed"
|
|
878
|
+
}
|
|
879
|
+
list_result_containers(search_condition=search_condition)
|
|
817
880
|
|
|
818
881
|
Parameters
|
|
819
882
|
----------
|
|
820
|
-
|
|
821
|
-
|
|
883
|
+
search_condition : dict
|
|
884
|
+
- p_n: str Analysis name
|
|
885
|
+
- type: str Type
|
|
886
|
+
- from_d: str dd.mm.yyyy Date from
|
|
887
|
+
- to_d: str dd.mm.yyyy Date to
|
|
888
|
+
- qa_status: str pass/fail/nd QC status
|
|
889
|
+
- secret_name: str Subject ID
|
|
890
|
+
- tags: str
|
|
891
|
+
- with_child_analysis: 1 if 1, child analysis of workflows will appear
|
|
892
|
+
- id: str ID
|
|
893
|
+
- state: running, completed, pending, exception
|
|
894
|
+
- username: str
|
|
895
|
+
items : List[int]
|
|
896
|
+
list containing two elements [min, max] that correspond to the
|
|
897
|
+
mininum and maximum range of analysis listed
|
|
822
898
|
|
|
823
899
|
Returns
|
|
824
900
|
-------
|
|
825
901
|
dict
|
|
826
902
|
List of containers, each a dictionary
|
|
827
903
|
{"name": "container-name", "id": "container_id"}
|
|
904
|
+
if "id": None, that analysis did not had an output container,
|
|
905
|
+
probably it is a workflow
|
|
828
906
|
"""
|
|
829
|
-
|
|
830
|
-
return [{"name":
|
|
907
|
+
analyses = self.list_analysis(search_condition, items)
|
|
908
|
+
return [{"name": analysis["name"], "id": (analysis.get("out_container_id") or None)} for analysis in analyses]
|
|
831
909
|
|
|
832
910
|
def list_container_files(
|
|
833
911
|
self,
|
|
@@ -1841,7 +1919,8 @@ class Project:
|
|
|
1841
1919
|
modalities.append(modality)
|
|
1842
1920
|
return modalities
|
|
1843
1921
|
|
|
1844
|
-
def
|
|
1922
|
+
def set_qc_status_analysis(self, analysis_id,
|
|
1923
|
+
status=QCStatus.UNDERTERMINED, comments=""):
|
|
1845
1924
|
"""
|
|
1846
1925
|
Changes the analysis QC status.
|
|
1847
1926
|
|
|
@@ -1850,85 +1929,257 @@ class Project:
|
|
|
1850
1929
|
analysis_id : int
|
|
1851
1930
|
Analysis ID number
|
|
1852
1931
|
status : QCStatus
|
|
1853
|
-
QCStatus.PASS or QCStatus.
|
|
1932
|
+
QCStatus.PASS, QCStatus.FAIL or QCStatus.UNDETERMINED
|
|
1854
1933
|
comments : str, optional
|
|
1855
|
-
Additional comments explaining why the
|
|
1856
|
-
|
|
1934
|
+
Additional comments explaining why the reasoning of setting the
|
|
1935
|
+
QC status to such state.
|
|
1936
|
+
|
|
1937
|
+
Returns
|
|
1938
|
+
-------
|
|
1939
|
+
bool
|
|
1940
|
+
True if the QC status was correctly changed, False otherwise.
|
|
1857
1941
|
"""
|
|
1942
|
+
|
|
1858
1943
|
logger = logging.getLogger(__name__)
|
|
1859
1944
|
logger.info(f"Setting QC status to {status}: {comments}")
|
|
1860
1945
|
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1946
|
+
if not isinstance(status, QCStatus):
|
|
1947
|
+
raise ValueError("Status should be type 'QCStatus'.")
|
|
1948
|
+
|
|
1949
|
+
try:
|
|
1950
|
+
analysis_id = str(int(analysis_id))
|
|
1951
|
+
except ValueError:
|
|
1952
|
+
raise ValueError(f"analysis_id: '{analysis_id}' not valid. " f"Must be convertible to int.")
|
|
1953
|
+
|
|
1954
|
+
try:
|
|
1955
|
+
platform.parse_response(
|
|
1956
|
+
platform.post(
|
|
1957
|
+
auth=self._account.auth,
|
|
1958
|
+
endpoint="projectset_manager/set_qa_status",
|
|
1959
|
+
data={"item_ids": analysis_id, "status": status.value,
|
|
1960
|
+
"comments": str(comments), "entity": "analysis"},
|
|
1961
|
+
)
|
|
1866
1962
|
)
|
|
1867
|
-
|
|
1963
|
+
except Exception:
|
|
1964
|
+
logger.error(f"It was not possible to change the QC status of"
|
|
1965
|
+
f"Analysis ID: {analysis_id}")
|
|
1966
|
+
return False
|
|
1967
|
+
return True
|
|
1968
|
+
|
|
1969
|
+
def set_qc_status_subject(self, patient_id,
|
|
1970
|
+
status=QCStatus.UNDERTERMINED, comments=""):
|
|
1971
|
+
"""
|
|
1972
|
+
Changes the QC status of a Patient ID (equivalent to a
|
|
1973
|
+
Subject ID/Session ID).
|
|
1974
|
+
|
|
1975
|
+
Parameters
|
|
1976
|
+
----------
|
|
1977
|
+
patient_id : int
|
|
1978
|
+
Patient ID number of the session.
|
|
1979
|
+
status : QCStatus
|
|
1980
|
+
QCStatus.PASS, QCStatus.FAIL or QCStatus.UNDETERMINED
|
|
1981
|
+
comments : str, optional
|
|
1982
|
+
Additional comments explaining why the reasoning of setting the
|
|
1983
|
+
QC status to such state.
|
|
1984
|
+
|
|
1985
|
+
Returns
|
|
1986
|
+
-------
|
|
1987
|
+
bool
|
|
1988
|
+
True if the QC status was correctly changed, False otherwise.
|
|
1989
|
+
"""
|
|
1990
|
+
logger = logging.getLogger(__name__)
|
|
1991
|
+
logger.info(f"Setting QC status to {status}: {comments}")
|
|
1868
1992
|
|
|
1869
|
-
|
|
1993
|
+
if not isinstance(status, QCStatus):
|
|
1994
|
+
raise ValueError("Status should be type 'QCStatus'.")
|
|
1995
|
+
|
|
1996
|
+
try:
|
|
1997
|
+
patient_id = str(int(patient_id))
|
|
1998
|
+
except ValueError:
|
|
1999
|
+
raise ValueError(f"'patient_id': '{patient_id}' not valid. " f"Must be convertible to int.")
|
|
2000
|
+
|
|
2001
|
+
try:
|
|
2002
|
+
platform.parse_response(
|
|
2003
|
+
platform.post(
|
|
2004
|
+
auth=self._account.auth,
|
|
2005
|
+
endpoint="projectset_manager/set_qa_status",
|
|
2006
|
+
data={"item_ids": patient_id, "status": status.value,
|
|
2007
|
+
"comments": str(comments), "entity": "patients"},
|
|
2008
|
+
)
|
|
2009
|
+
)
|
|
2010
|
+
except Exception:
|
|
2011
|
+
logger.error(f"It was not possible to change the QC status of"
|
|
2012
|
+
f"Patient ID: {patient_id}")
|
|
2013
|
+
return False
|
|
2014
|
+
return True
|
|
2015
|
+
|
|
2016
|
+
def get_qc_status_analysis(self, analysis_id):
|
|
1870
2017
|
"""
|
|
1871
|
-
Gets the
|
|
1872
|
-
specified, it returns the QC of the
|
|
1873
|
-
analysis instead.
|
|
2018
|
+
Gets the QC status of an anlaysis provided its Analysis ID.
|
|
1874
2019
|
|
|
2020
|
+
Parameters
|
|
2021
|
+
----------
|
|
2022
|
+
analysis_id : int
|
|
2023
|
+
Analysis ID number
|
|
2024
|
+
|
|
2025
|
+
Returns
|
|
2026
|
+
-------
|
|
2027
|
+
status : QCStatus or False
|
|
2028
|
+
QCStatus.PASS, QCStatus.FAIL or QCStatus.UNDETERMINED
|
|
2029
|
+
False if the status cannot be extracted.
|
|
2030
|
+
comments : str or False
|
|
2031
|
+
Comments defined in the QC Status.
|
|
2032
|
+
False if the comments cannot be extracted.
|
|
1875
2033
|
"""
|
|
1876
|
-
|
|
2034
|
+
try:
|
|
2035
|
+
search_criteria = {"id": analysis_id}
|
|
2036
|
+
to_return = self.list_analysis(search_criteria)
|
|
2037
|
+
return convert_qc_value_to_qcstatus(to_return[0]["qa_status"]), to_return[0]["qa_comments"]
|
|
2038
|
+
except IndexError:
|
|
2039
|
+
# Handle the case where no matching analysis is found
|
|
2040
|
+
logging.error(f"No analysis was found with such Analysis ID: '{analysis_id}'.")
|
|
2041
|
+
return False, False
|
|
2042
|
+
except Exception:
|
|
2043
|
+
# Handle other potential exceptions
|
|
2044
|
+
logging.error(f"It was not possible to extract the QC status"
|
|
2045
|
+
f"from Analysis ID: {analysis_id}")
|
|
2046
|
+
return False, False
|
|
2047
|
+
|
|
2048
|
+
def get_qc_status_subject(self, patient_id=None, subject_name=None,
|
|
2049
|
+
ssid=None):
|
|
2050
|
+
"""
|
|
2051
|
+
Gets the session QC status via the patient ID or the Subject ID
|
|
2052
|
+
and the Session ID.
|
|
2053
|
+
|
|
2054
|
+
Parameters
|
|
2055
|
+
----------
|
|
2056
|
+
patient_id : int
|
|
2057
|
+
Patient ID number of the session
|
|
2058
|
+
subject_name : string
|
|
2059
|
+
Subject ID of the session
|
|
2060
|
+
ssid : string
|
|
2061
|
+
Session ID
|
|
2062
|
+
|
|
2063
|
+
Returns
|
|
2064
|
+
-------
|
|
2065
|
+
status : QCStatus or False
|
|
2066
|
+
QCStatus.PASS, QCStatus.FAIL or QCStatus.UNDETERMINED
|
|
2067
|
+
False if the status cannot be extracted.
|
|
2068
|
+
comments : str or False
|
|
2069
|
+
Comments defined in the QC Status.
|
|
2070
|
+
False if the comments cannot be extracted.
|
|
2071
|
+
"""
|
|
2072
|
+
|
|
2073
|
+
if patient_id:
|
|
2074
|
+
try:
|
|
2075
|
+
patient_id = int(patient_id)
|
|
2076
|
+
except ValueError:
|
|
2077
|
+
raise ValueError(f"patient_id '{patient_id}' should be an "
|
|
2078
|
+
f"integer.")
|
|
2079
|
+
sessions = self.get_subjects_metadata(search_criteria={})
|
|
2080
|
+
session = [session for session in sessions if int(session["_id"]) == patient_id]
|
|
2081
|
+
if len(session) < 1:
|
|
2082
|
+
logging.error(f"No session was found with Patient ID: "
|
|
2083
|
+
f"'{patient_id}'.")
|
|
2084
|
+
return False, False
|
|
2085
|
+
return convert_qc_value_to_qcstatus(session[0]["qa_status"]), session[0]["qa_comments"]
|
|
2086
|
+
elif subject_name and ssid:
|
|
1877
2087
|
session = self.get_subjects_metadata(
|
|
1878
2088
|
search_criteria={
|
|
1879
|
-
"pars_patient_secret_name": f"string;
|
|
2089
|
+
"pars_patient_secret_name": f"string;{subject_name}",
|
|
1880
2090
|
"pars_ssid": f"integer;eq|{ssid}",
|
|
1881
2091
|
}
|
|
1882
2092
|
)
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
][0]
|
|
1889
|
-
to_return = to_return["qa_status"], to_return["qa_comments"]
|
|
1890
|
-
except IndexError:
|
|
1891
|
-
# Handle the case where no matching analysis is found
|
|
1892
|
-
to_return = None
|
|
1893
|
-
except Exception as e:
|
|
1894
|
-
# Handle other potential exceptions
|
|
1895
|
-
print(f"An error occurred: {e}")
|
|
1896
|
-
to_return = None
|
|
2093
|
+
if len(session) < 1:
|
|
2094
|
+
logging.error(f"No session was found with Subject ID: "
|
|
2095
|
+
f"'{subject_name}' and Session ID: '{ssid}'.")
|
|
2096
|
+
return False, False
|
|
2097
|
+
return convert_qc_value_to_qcstatus(session[0]["qa_status"]), session[0]["qa_comments"]
|
|
1897
2098
|
else:
|
|
1898
|
-
raise
|
|
1899
|
-
|
|
2099
|
+
raise ValueError("Either 'patient_id' or 'subject_name' and 'ssid'"
|
|
2100
|
+
" must not be empty.")
|
|
1900
2101
|
|
|
1901
|
-
def
|
|
2102
|
+
def set_project_pa_rules(self, rules_file_path, guidance_text=""):
|
|
1902
2103
|
"""
|
|
1903
|
-
|
|
1904
|
-
|
|
2104
|
+
Updates the active project's protocol adherence rules using the
|
|
2105
|
+
provided rules file.
|
|
1905
2106
|
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
2107
|
+
Parameters
|
|
2108
|
+
----------
|
|
2109
|
+
rules_file_path : str
|
|
2110
|
+
The file path to the JSON file containing the protocol
|
|
2111
|
+
adherence rules.
|
|
2112
|
+
guidance_text : str
|
|
2113
|
+
Description of the protocol adherence rules.
|
|
1909
2114
|
|
|
1910
|
-
Returns
|
|
1911
|
-
|
|
2115
|
+
Returns
|
|
2116
|
+
-------
|
|
2117
|
+
bool: True if the protocol adherence rules were set successfully,
|
|
2118
|
+
False otherwise.
|
|
1912
2119
|
"""
|
|
2120
|
+
logger = logging.getLogger(logger_name)
|
|
1913
2121
|
# Read the rules from the JSON file
|
|
1914
2122
|
try:
|
|
1915
2123
|
with open(rules_file_path, "r") as fr:
|
|
1916
2124
|
rules = json.load(fr)
|
|
1917
2125
|
except FileNotFoundError:
|
|
1918
|
-
|
|
2126
|
+
logger.error(f"Pprotocol adherence rule file '{rules_file_path}' "
|
|
2127
|
+
f"not found.")
|
|
1919
2128
|
return False
|
|
1920
2129
|
|
|
1921
2130
|
# Update the project's QA rules
|
|
1922
|
-
res = platform.post(
|
|
2131
|
+
res = platform.parse_response(platform.post(
|
|
1923
2132
|
auth=self._account.auth,
|
|
1924
2133
|
endpoint="projectset_manager/set_session_qa_requirements",
|
|
1925
2134
|
data={"project_id": self._project_id, "rules": json.dumps(rules), "guidance_text": guidance_text},
|
|
1926
|
-
)
|
|
2135
|
+
))
|
|
1927
2136
|
|
|
1928
|
-
if res.
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
2137
|
+
if not res.get("success") == 1:
|
|
2138
|
+
logger.error("There was an error setting up the protocol "
|
|
2139
|
+
"adherence rules.")
|
|
2140
|
+
logger.error(platform.parse_response(res))
|
|
2141
|
+
return False
|
|
2142
|
+
|
|
2143
|
+
return True
|
|
2144
|
+
|
|
2145
|
+
def get_project_pa_rules(self, rules_file_path):
|
|
2146
|
+
"""
|
|
2147
|
+
Retrive the active project's protocol adherence rules
|
|
2148
|
+
|
|
2149
|
+
Parameters
|
|
2150
|
+
----------
|
|
2151
|
+
rules_file_path : str
|
|
2152
|
+
The file path to the JSON file to store the protocol adherence
|
|
2153
|
+
rules.
|
|
2154
|
+
|
|
2155
|
+
Returns
|
|
2156
|
+
-------
|
|
2157
|
+
guidance_text : str
|
|
2158
|
+
Description of the protocol adherence rules,
|
|
2159
|
+
False if extraction of the protocol adhernece rules is not
|
|
2160
|
+
possible.
|
|
2161
|
+
"""
|
|
2162
|
+
logger = logging.getLogger(logger_name)
|
|
2163
|
+
|
|
2164
|
+
# Update the project's QA rules
|
|
2165
|
+
res = platform.parse_response(platform.post(
|
|
2166
|
+
auth=self._account.auth,
|
|
2167
|
+
endpoint="projectset_manager/get_session_qa_requirements",
|
|
2168
|
+
data={"project_id": self._project_id},
|
|
2169
|
+
))
|
|
2170
|
+
|
|
2171
|
+
if "rules" not in res:
|
|
2172
|
+
logger.error(f"There was an error extracting the protocol "
|
|
2173
|
+
f"adherence rules from {self._project_name}.")
|
|
2174
|
+
logger.error(platform.parse_response(res))
|
|
1934
2175
|
return False
|
|
2176
|
+
|
|
2177
|
+
try:
|
|
2178
|
+
with open(rules_file_path, "w") as fr:
|
|
2179
|
+
json.dump(res["rules"], fr, indent=4)
|
|
2180
|
+
except FileNotFoundError:
|
|
2181
|
+
logger.error(f"Protocol adherence rules could not be exported"
|
|
2182
|
+
f"to file: '{rules_file_path}'.")
|
|
2183
|
+
return False
|
|
2184
|
+
|
|
2185
|
+
return res["guidance_text"]
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
qmenta/__init__.py,sha256=jv2YF__bseklT3OWEzlqJ5qE24c4aWd5F4r0TTjOrWQ,65
|
|
2
2
|
qmenta/client/Account.py,sha256=MEljEy9cmg2uP2FG1d3TZAgfj66EE2_3PQAZ9rvpCXY,9647
|
|
3
3
|
qmenta/client/File.py,sha256=ZgvSqejIosUt4uoX7opUnPnp5XGEaJNMRwFC0mQVB8k,5344
|
|
4
|
-
qmenta/client/Project.py,sha256=
|
|
4
|
+
qmenta/client/Project.py,sha256=xk-C4kf2i7RLsIp3fiwHQzlEOZpb1sL-KqxGqDex8Mc,76953
|
|
5
5
|
qmenta/client/Subject.py,sha256=lhxxVdQ6d-GNoQC8mrJwa4L1f44nJc4PcJtDspmKN7I,8756
|
|
6
6
|
qmenta/client/__init__.py,sha256=AjTojBhZeW5nl0i605KS8S1Gl5tPNc1hdzD47BGNfoI,147
|
|
7
7
|
qmenta/client/utils.py,sha256=5DK2T_HQprrCwLS0Ycm2CjseaYmAUKaJkJvYoW-Rqzc,2479
|
|
8
|
-
qmenta_client-1.1.
|
|
9
|
-
qmenta_client-1.1.
|
|
10
|
-
qmenta_client-1.1.
|
|
8
|
+
qmenta_client-1.1.dev1349.dist-info/METADATA,sha256=RBQVZKHts7FiBDWvv9C5Nf6lCj8I5YH6N_shy1JRBsc,672
|
|
9
|
+
qmenta_client-1.1.dev1349.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
10
|
+
qmenta_client-1.1.dev1349.dist-info/RECORD,,
|
|
File without changes
|