Hello community, here is the log from the commit of package python-beren for openSUSE:Factory checked in at 2020-09-01 20:09:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-beren (Old) and /work/SRC/openSUSE:Factory/.python-beren.new.3399 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-beren" Tue Sep 1 20:09:58 2020 rev:2 rq:830941 version:0.7.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-beren/python-beren.changes 2019-12-04 14:19:40.030402078 +0100 +++ /work/SRC/openSUSE:Factory/.python-beren.new.3399/python-beren.changes 2020-09-01 20:10:15.640673576 +0200 @@ -1,0 +2,7 @@ +Tue Sep 1 05:08:46 UTC 2020 - Steve Kowalik <[email protected]> + +- Update to 0.7.0: + * No upstream changelog +- Update {Build,}Requires for apiron. + +------------------------------------------------------------------- Old: ---- beren-0.6.2.tar.gz New: ---- beren-0.7.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-beren.spec ++++++ --- /var/tmp/diff_new_pack.hfz7Pr/_old 2020-09-01 20:10:16.720674081 +0200 +++ /var/tmp/diff_new_pack.hfz7Pr/_new 2020-09-01 20:10:16.724674083 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-beren # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # Copyright (c) 2019 Dr. Axel Braun <[email protected]> # # All modifications and additions to the file contributed by third parties @@ -16,24 +16,24 @@ # Please submit bugfixes or comments via https://bugs.opensuse.org/ # + %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 %define modname beren Name: python-%{modname} -Version: 0.6.2 +Version: 0.7.0 Release: 0 Summary: Provides a REST client targeted at Orthanc REST API endpoints License: GPL-3.0-or-later -Group: Development/Languages/Python URL: https://github.com/teffalump/beren Source: https://files.pythonhosted.org/packages/source/b/%{modname}/%{modname}-%{version}.tar.gz +BuildRequires: %{python_module apiron >= 5.1.0 } BuildRequires: %{python_module setuptools} -BuildRequires: %{python_module apiron >= 2.5.0 } BuildRequires: fdupes -Requires: python-apiron >= 2.5.0 +Requires: python-apiron >= 5.1.0 %python_subpackages ++++++ beren-0.6.2.tar.gz -> beren-0.7.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beren-0.6.2/PKG-INFO new/beren-0.7.0/PKG-INFO --- old/beren-0.6.2/PKG-INFO 2019-10-28 19:11:21.000000000 +0100 +++ new/beren-0.7.0/PKG-INFO 2020-07-26 22:57:20.797431000 +0200 @@ -1,30 +1,32 @@ Metadata-Version: 2.1 Name: beren -Version: 0.6.2 +Version: 0.7.0 Summary: REST client for Orthanc DICOM servers Home-page: https://github.com/teffalump/beren Author: teffalump Author-email: [email protected] License: UNKNOWN -Description: # Beren +Description: # beren - [](https://travis-ci.com/teffalump/beren) + [](https://travis-ci.com/teffalump/beren) [](https://badge.fury.io/py/beren) - Provides a REST client targeted at [Orthanc](https://www.orthanc-server.com) REST API endpoints. + `beren` provides a REST client for [Orthanc](https://www.orthanc-server.com), an open-source DICOM server. - Based on the excellent [apiron](https://github.com/ithaka/apiron) library. + Built using the excellent [apiron](https://github.com/ithaka/apiron) library. ### Install + Use pip: + pip install beren ### How to use - Import the pre-defined client and pass the server details + Import the client and provide the server details from beren import Orthanc - orthanc = Orthanc('http://localhost:8042') + orthanc = Orthanc('https://example-orthanc-server.com') # Patient endpoints orthanc.get_patients() @@ -60,42 +62,80 @@ ### Authentication - Pass valid auth object: + Many servers require authentication to utilize their API. Simply provide a valid authentication object when defining the client: from requests.auth import HTTPBasicAuth auth = HTTPBasicAuth('orthanc', 'orthanc') orthanc = Orthanc('https://test.server.com', auth=auth) - Then call functions normally (the auth object is passed automatically). + To override the default authentication, provide a new authentication object when calling the endpoint: - ### Advanced examples + new_auth = HTTPBasicAuth('new_user', 'new_password') + orthanc.get_patients(auth=auth) - For example, to save an instance file to local directory: + ### Advanced Configuration - with open('test_file.dcm', 'wb') as dcm: - for chunk in orthanc.get_instance_file(instance_id): - dcm.write(chunk) + #### Timeouts - To get a zip of DCM files from a series: + Some servers are slow (and some methods can be slow). For example, asking for all instances from a server can cause a timeout before the server responds. To + modify the timeout settings, use `apiron`'s `Timeout` class: - with open('test.zip', 'wb') as z: - for chunk in orthanc.get_series_archive(<id>): - z.write(chunk) + from apiron import Timeout + t = Timeout(read_timeout=6, connection_timeout=1) # Modify the timeout + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + orthanc.get_instances(timeout_spec=t) # Use new timeout - ### Security warning on non-HTTPS endpoints + Increase the read timeout if the endpoint is slow. Increase the connection timeout for slow servers. - The rest client will warn when using HTTP endpoints. Strongly consider using HTTPS given the data sensitivity. + #### Disable Certificate Checks - You can disable the warning using the `warn_insecure` keyword argument: + To disable TLS certificate checking, use sessions: + import requests + session = requests.sessions.Session() # New session + session.verify = False # Disable certificate checking + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + orthanc.get_patients(session=session) # Use session + + #### Non-HTTPS endpoints + + The client will warn when using HTTP endpoints. Medical data is particularly sensitive, consequently, strongly consider using HTTPS. + + You can disable the warning using the `warn_insecure` argument: + + from beren import Orthanc orthanc = Orthanc('http://insecure.endpoint.com', warn_insecure=False) + ### Examples + + To save an instance file to the local directory: + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + + with open('test_file.dcm', 'wb') as dcm: + for chunk in orthanc.get_instance_file(<instance_id>): + dcm.write(chunk) + + To get an archive of a series (DCM files in a zip file): + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + + with open('test.zip', 'wb') as z: + for chunk in orthanc.get_series_archive(<instance_id>): + z.write(chunk) + ### Further help - [apiron](https://github.com/ithaka/apiron) - [Orthanc documentation](https://book.orthanc-server.com) - [Orthanc OpenAPI](https://api.orthanc-server.com) - - [Orthanc REST API spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vSBEymDKGZgskFEFF6yzge5JovGHPK_FIbEnW5a6SWUbPkX06tkoObUHh6T1XQhgj-HqFd0AWSnVFOv/pubhtml?gid=654036639&single=true) + - [Orthanc REST API spreadsheet](https://docs.google.com/spreadsheets/d/1muKHMIb9Br-59wfaQbDeLzAfKYsoWfDSXSmyt6P4EM8/pubhtml#) Platform: UNKNOWN Classifier: Development Status :: 4 - Beta diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beren-0.6.2/README.md new/beren-0.7.0/README.md --- old/beren-0.6.2/README.md 2019-10-24 18:18:31.000000000 +0200 +++ new/beren-0.7.0/README.md 2020-07-26 22:44:48.000000000 +0200 @@ -1,22 +1,24 @@ -# Beren +# beren -[](https://travis-ci.com/teffalump/beren) +[](https://travis-ci.com/teffalump/beren) [](https://badge.fury.io/py/beren) -Provides a REST client targeted at [Orthanc](https://www.orthanc-server.com) REST API endpoints. +`beren` provides a REST client for [Orthanc](https://www.orthanc-server.com), an open-source DICOM server. -Based on the excellent [apiron](https://github.com/ithaka/apiron) library. +Built using the excellent [apiron](https://github.com/ithaka/apiron) library. ### Install +Use pip: + pip install beren ### How to use -Import the pre-defined client and pass the server details +Import the client and provide the server details from beren import Orthanc - orthanc = Orthanc('http://localhost:8042') + orthanc = Orthanc('https://example-orthanc-server.com') # Patient endpoints orthanc.get_patients() @@ -52,39 +54,77 @@ ### Authentication -Pass valid auth object: +Many servers require authentication to utilize their API. Simply provide a valid authentication object when defining the client: from requests.auth import HTTPBasicAuth auth = HTTPBasicAuth('orthanc', 'orthanc') orthanc = Orthanc('https://test.server.com', auth=auth) -Then call functions normally (the auth object is passed automatically). +To override the default authentication, provide a new authentication object when calling the endpoint: -### Advanced examples + new_auth = HTTPBasicAuth('new_user', 'new_password') + orthanc.get_patients(auth=auth) -For example, to save an instance file to local directory: +### Advanced Configuration - with open('test_file.dcm', 'wb') as dcm: - for chunk in orthanc.get_instance_file(instance_id): - dcm.write(chunk) +#### Timeouts -To get a zip of DCM files from a series: +Some servers are slow (and some methods can be slow). For example, asking for all instances from a server can cause a timeout before the server responds. To +modify the timeout settings, use `apiron`'s `Timeout` class: - with open('test.zip', 'wb') as z: - for chunk in orthanc.get_series_archive(<id>): - z.write(chunk) + from apiron import Timeout + t = Timeout(read_timeout=6, connection_timeout=1) # Modify the timeout + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + orthanc.get_instances(timeout_spec=t) # Use new timeout -### Security warning on non-HTTPS endpoints +Increase the read timeout if the endpoint is slow. Increase the connection timeout for slow servers. -The rest client will warn when using HTTP endpoints. Strongly consider using HTTPS given the data sensitivity. +#### Disable Certificate Checks -You can disable the warning using the `warn_insecure` keyword argument: +To disable TLS certificate checking, use sessions: + import requests + session = requests.sessions.Session() # New session + session.verify = False # Disable certificate checking + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + orthanc.get_patients(session=session) # Use session + +#### Non-HTTPS endpoints + +The client will warn when using HTTP endpoints. Medical data is particularly sensitive, consequently, strongly consider using HTTPS. + +You can disable the warning using the `warn_insecure` argument: + + from beren import Orthanc orthanc = Orthanc('http://insecure.endpoint.com', warn_insecure=False) +### Examples + +To save an instance file to the local directory: + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + + with open('test_file.dcm', 'wb') as dcm: + for chunk in orthanc.get_instance_file(<instance_id>): + dcm.write(chunk) + +To get an archive of a series (DCM files in a zip file): + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + + with open('test.zip', 'wb') as z: + for chunk in orthanc.get_series_archive(<instance_id>): + z.write(chunk) + ### Further help - [apiron](https://github.com/ithaka/apiron) - [Orthanc documentation](https://book.orthanc-server.com) - [Orthanc OpenAPI](https://api.orthanc-server.com) -- [Orthanc REST API spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vSBEymDKGZgskFEFF6yzge5JovGHPK_FIbEnW5a6SWUbPkX06tkoObUHh6T1XQhgj-HqFd0AWSnVFOv/pubhtml?gid=654036639&single=true) +- [Orthanc REST API spreadsheet](https://docs.google.com/spreadsheets/d/1muKHMIb9Br-59wfaQbDeLzAfKYsoWfDSXSmyt6P4EM8/pubhtml#) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beren-0.6.2/beren/VERSION new/beren-0.7.0/beren/VERSION --- old/beren-0.6.2/beren/VERSION 2019-10-28 19:04:03.000000000 +0100 +++ new/beren-0.7.0/beren/VERSION 2020-07-26 22:45:00.000000000 +0200 @@ -1 +1 @@ -0.6.2 +0.7.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beren-0.6.2/beren/orthanc.py new/beren-0.7.0/beren/orthanc.py --- old/beren-0.6.2/beren/orthanc.py 2019-10-28 19:03:43.000000000 +0100 +++ new/beren-0.7.0/beren/orthanc.py 2020-07-26 22:09:27.000000000 +0200 @@ -11,7 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. -from .endpoints import ( +from beren.endpoints import ( OrthancInstances, OrthancModalities, OrthancPatients, @@ -61,7 +61,7 @@ ) ) - # Set target for each apiron service + # Set target and auth for each apiron service for x in [ self.instances, self.modalities, @@ -72,10 +72,28 @@ self.studies, ]: setattr(x, "domain", self._target) + setattr(x, "auth", self._auth) def __repr__(self): return "<Orthanc REST client({})>".format(self._target) + @classmethod + def get_api_methods(cls): + """List callable endpoints""" + return [ + func + for func in dir(cls) + if callable(getattr(cls, func)) + and not func.startswith("__") + and func + not in [ + "clean", + "convert_to_json", + "build_root_parameters", + "get_api_methods", + ] + ] + @staticmethod def convert_to_json(data, **kwargs): """Wrapper for ``json.dumps``""" @@ -83,47 +101,75 @@ @staticmethod def clean(d): - """Clean the parameter dict for endpoint semantics""" + """Clean the parameter dict for endpoint semantics + + Accordingly, + Boolean True is converted to 1, False is dropped + Values evaluating to None are dropped + Keep the other entries + + :param dict d + Dictinary to clean + :return + Cleaned dictionary + :rtype: + dict + """ + n = {} for k, v in d.items(): - if v == None or v == False: + if isinstance(v, (bool)): + if v == True: + n[k] = 1 + elif v == None: continue - elif v == True: - n[k] = "" else: n[k] = v return n + @classmethod + def build_root_parameters(cls, expand, since, limit, params): + """Helper function for root endpoints' (/study, /patient, /instance, /series) parameter logic""" + if params is None: + passed_params = {} + if expand == True: + passed_params["expand"] = True + if limit is not None or since is not None: + try: + passed_params["since"] = int(since) + passed_params["limit"] = int(limit) + except: + passed_params.pop("since", None) + passed_params.pop("limit", None) + warn("Must provide valid integers to since AND limit. Ignoring.") + return cls.clean(passed_params) + else: + return params + #### INSTANCES - def get_instances(self, expand=False, since=0, limit=None, **kwargs): + def get_instances( + self, expand=False, since=None, limit=None, params=None, **kwargs + ): """Return instance record(s). No raw file data. Use ``expand`` keyword argument to retrieve extensive information. - Use ``since`` and ``limit`` keyword arguments to specify group of records. + Use ``since`` and ``limit`` keyword arguments to specify a group of records. :param bool expand: Return verbose information about instances. Default ``False``. By default, returns UUIDs. :param int since: - Return since nth instance record. Default ``0``. + Return since nth instance record. Optional. Must use with ``limit``. :param int limit: - Limit to given number of records. Optional. + Limit to given number of records. Optional. Must use with ``since``. + :param dict params: + Provide overriding parameter dictionary :return: A list of records: either UUIDs or dictionary of information :rtype: list """ - params = {} - if expand == True: - params["expand"] = True - if limit: - try: - params["since"] = int(since) - params["limit"] = int(limit) - except: - raise TypeError("Must provide valid ints as since and limit") - kwargs["params"] = params - kwargs["auth"] = kwargs.get("auth", self._auth) + kwargs["params"] = self.build_root_parameters(expand, since, limit, params) return self.instances.instances(**kwargs) def add_instance(self, dicom, **kwargs): @@ -136,7 +182,6 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.add_instance(data=dicom, **kwargs) def get_instance(self, id_, **kwargs): @@ -151,7 +196,6 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.instance(id_=id_, **kwargs) def delete_instance(self, id_, **kwargs): @@ -164,7 +208,6 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.del_instance(id_=id_, **kwargs) def anonymize_instance( @@ -192,17 +235,17 @@ :return: Anonymized DICOM file :rtype: - DICOM file + generator """ - data = { - "DicomVersion": version, - "KeepPrivateTags": keep_private, - "Keep": keep_tags, - "Replace": replace_tags, - } - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.instances.anonymize(id_=id_, data=j, **kwargs) + data = self.clean( + { + "DicomVersion": version, + "KeepPrivateTags": keep_private, + "Keep": keep_tags, + "Replace": replace_tags, + } + ) + return self.instances.anonymize(id_=id_, json=data, **kwargs) def get_instance_content(self, id_, **kwargs): """List first-level DICOM tags. @@ -214,7 +257,6 @@ :rtype: list """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.content(id_=id_, **kwargs) def get_instance_content_raw_tag(self, id_, group, element, **kwargs): @@ -231,13 +273,20 @@ :rtype: str """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.content_raw_tag( id_=id_, group=group, element=element, **kwargs ) def export_instance(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) + """Write the DICOM file to the filesystem where Orthanc is running + + :param str id_: + The instance UUID + :return: + Empty list + :rtype: + list + """ return self.instances.export(id_=id_, data={}, **kwargs) def get_instance_file(self, id_, **kwargs): @@ -255,7 +304,6 @@ :rtype: generator """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.file_(id_=id_, **kwargs) def get_instance_frame(self, id_, frame, format_, **kwargs): @@ -272,7 +320,6 @@ :return: generator """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.frame(id_=id_, frame=frame, format_=format_, **kwargs) def get_instance_frames(self, id_, **kwargs): @@ -285,7 +332,6 @@ :rtype: list (int) """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.frames(id_=id_, **kwargs) def get_instance_frame_preview(self, id_, frame, **kwargs): @@ -300,7 +346,6 @@ :rtype: generator """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.frame_preview(id_=id_, number=frame, **kwargs) def get_instance_header(self, id_, simplify=False, short=False, **kwargs): @@ -318,7 +363,6 @@ dict """ kwargs["params"] = self.clean({"simplify": simplify, "short": short}) - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.header(id_=id_, **kwargs) def get_instance_image(self, id_, format_, **kwargs): @@ -333,16 +377,45 @@ :rtype: generator """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.image(id_=id_, format_=format_, **kwargs) - def modify_instance(self, id_, data, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.instances.modify(id_=id_, data=j, **kwargs) + def modify_instance( + self, + id_, + replace={}, + remove=[], + remove_private_tags=False, + force=False, + **kwargs + ): + """Modify a set of specified tags in a single DICOM instance and download the resulting modified DICOM file + + :param str id_: + Instance UUID + :param dict replace: + The dictionary which specifies the substitions to be applied (cf. anonymization). Default empty. + :param list remove: + List of tags to remove. Default empty. + :param bool remove_private_tags: + If set to true, the private tags (i.e. manufacturer-specific tags) are removed. Default False. + :param bool force: + The force option must be set to True in order to allow the modification of the PatientID, as such a modification of the DICOM identifiers might lead to breaking the DICOM model of the real-world. In general, any explicit modification to one of the PatientID, StudyInstanceUID, SeriesInstanceUID, and SOPInstanceUID requires Force to be set to True, in order to prevent any unwanted side effect. Default False. + :return: + DICOM file + :rtype: + generator + """ + data = self.clean( + { + "Replace": replace, + "Remove": remove, + "RemovePrivateTags": remove_private_tags, + "Force": force, + } + ) + return self.instances.modify(id_=id_, json=data, **kwargs) def get_instance_module(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.module(id_=id_, **kwargs) def get_instance_patient(self, id_, **kwargs): @@ -355,11 +428,11 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.patient(id_=id_, **kwargs) def get_instance_pdf(self, id_, **kwargs): """Download embedded PDF of DICOM instance + :param str id_: The instance UUID :return: @@ -367,15 +440,33 @@ :rtype: generator """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.pdf(id_=id_, **kwargs) - def get_instance_preview(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.instances.preview(id_=id_, **kwargs) + def get_instance_preview(self, id_, png=True, **kwargs): + """Download a preview image of the DICOM instance. Default "image/png". Other option "image/jpeg" + + :param str id_: + Instance UUID + :param bool png: + Image format. Default png. False is jpeg. + :return: + DICOM preview + :rtype: + generator + """ + image_type = "image/png" if png == True else "image/jpeg" + return self.instances.preview(id_=id_, headers={"Accept": image_type}, **kwargs) def reconstruct_instance(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) + """Force reconstruction of the main DICOM tags, JSON summary and metadata + + :param str id_: + Instance UUID + :return: + Empty list on success + :rtype: + List + """ return self.instances.reconstruct(id_=id_, data={}, **kwargs) def get_instance_series(self, id_, **kwargs): @@ -388,7 +479,6 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.series(id_=id_, **kwargs) def get_instance_simplified_tags(self, id_, **kwargs): @@ -401,11 +491,18 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.simplified_tags(id_=id_, **kwargs) def get_instance_statistics(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) + """Get instance statistics + + :param str id_: + Instance UUID + :return: + Instance statistics + :rtype: + dict + """ return self.instances.statistics(id_=id_, **kwargs) def get_instance_study(self, id_, **kwargs): @@ -418,7 +515,6 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.study(id_=id_, **kwargs) def get_instance_tag(self, id_, tag, **kwargs): @@ -433,7 +529,6 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.tags(id_=id_, tag=tag, **kwargs) def get_instance_tags(self, id_, simplify=False, short=False, **kwargs): @@ -451,11 +546,10 @@ dict """ kwargs["params"] = self.clean({"simplify": simplify, "short": short}) - kwargs["auth"] = kwargs.get("auth", self._auth) return self.instances.tags(id_=id_, **kwargs) #### PATIENTS - def get_patients(self, expand=False, since=0, limit=None, params=None, **kwargs): + def get_patients(self, expand=False, since=None, limit=None, params=None, **kwargs): """Return patient record(s) Use ``expand`` keyword argument to retrieve expanded information. @@ -465,9 +559,9 @@ Return verbose information about patients. Default ``False``. By default, returns UUIDs. :param int since: - Return since nth patient record. Default ``0``. + Return since nth patient record. Optional. Must use with ``limit``. :param int limit: - Limit to given number of records. Optional. + Limit to given number of records. Optional. Must use with ``since``. :param dict params: Provide paramaters dict to override other values :return: @@ -475,20 +569,7 @@ :rtype: list """ - if params is None: - params = {} - if expand == True: - params["expand"] = True - if limit: - try: - params["since"] = int(since) - params["limit"] = int(limit) - except: - raise TypeError("Must provide valid ints as since and limit") - kwargs["params"] = self.clean(params) - else: - kwargs["params"] = params - kwargs["auth"] = kwargs.get("auth", self._auth) + kwargs["params"] = self.build_root_parameters(expand, since, limit, params) return self.patients.patients(**kwargs) def get_patient(self, id_, **kwargs): @@ -501,20 +582,15 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.patient(id_=id_, **kwargs) def delete_patient(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.del_patient(id_=id_, **kwargs) def anonymize_patient(self, id_, data={}, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.patients.anonymize(id_=id_, data=j, **kwargs) + return self.patients.anonymize(id_=id_, json=data, **kwargs) def archive_patient(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.archive(id_=id_, **kwargs) def get_patient_instances(self, id_, **kwargs): @@ -527,36 +603,27 @@ :rtype: list (dict) """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.instances(id_=id_, **kwargs) def get_patient_instance_tags(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.instances_tags(id_=id_, **kwargs) def modify_patient(self, id_, data, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.patients.modify(id_=id_, data=j, **kwargs) + return self.patients.modify(id_=id_, json=data, **kwargs) def get_patient_module(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.module(id_=id_, **kwargs) def get_patient_media(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.media(id_=id_, **kwargs) def get_patient_protected(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.protected(id_=id_, **kwargs) def put_patient_protected(self, id_, data={}, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.put_protected(id_=id_, data=data, **kwargs) def reconstruct_patient(self, id_, data={}, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.protected(id_=id_, data=data, **kwargs) def get_patient_series(self, id_, **kwargs): @@ -569,15 +636,12 @@ :rtype: list (dict) """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.series(id_=id_, **kwargs) def get_patient_shared_tags(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.shared_tags(id_=id_, **kwargs) def get_patient_statistics(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.statistics(id_=id_, **kwargs) def get_patient_studies(self, id_, **kwargs): @@ -590,7 +654,6 @@ :rtype: list (dict) """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.patients.studies(id_=id_, **kwargs) def get_patient_id_from_uuid(self, id_, **kwargs): @@ -605,7 +668,6 @@ :rtype: str """ - kwargs["auth"] = kwargs.get("auth", self._auth) return ( self.patients.patient(id_=id_, **kwargs) .get("MainDicomTags") @@ -614,7 +676,6 @@ def get_patient_studies_from_id(self, id_, **kwargs): try: - kwargs["auth"] = kwargs.get("auth", self._auth) return [ self.get_patient_studies(patient) for patient in self.find( @@ -627,62 +688,67 @@ #### QUERIES def get_queries(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.queries(**kwargs) def get_query(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.query(id_=id_, **kwargs) def delete_query(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.del_query(id_=id_, **kwargs) def get_query_answers(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.query(id_=id_, **kwargs) def get_query_answers_content(self, id_, index, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.answers_content(id_=id_, index=index, **kwargs) def post_query_answers_retrieve(self, id_, index, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.answers_retrieve(id_=id_, index=index, **kwargs) def get_query_level(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.level(id_=id_, **kwargs) def get_query_modality(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.modality(id_=id_, **kwargs) def get_query_query(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.query_query(id_=id_, **kwargs) def post_query_retrieve(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.queries.retrieve(id_=id_, **kwargs) #### SERIES - def get_series(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) + def get_series(self, expand=False, since=None, limit=None, params=None, **kwargs): + """Return series record(s). + + Use ``expand`` keyword argument to retrieve extensive information. + Use ``since`` and ``limit`` keyword arguments to specify a group of records. + + :param bool expand: + Return verbose information about series. Default ``False``. + By default, returns UUIDs. + :param int since: + Return since nth series record. Optional. Must use with ``limit``. + :param int limit: + Limit to given number of records. Optional. Must use with ``since``. + :param dict params: + Provide overriding parameter dictionary + :return: + A list of records: either UUIDs or dictionary of information + :rtype: + list + """ + kwargs["params"] = self.build_root_parameters(expand, since, limit, params) return self.series.series(**kwargs) def get_one_series(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.part(id_=id_, **kwargs) def delete_series(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.del_part(id_=id_, **kwargs) def anonymize_series(self, id_, data={}, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.series.anonymize(id_=id_, data=j, **kwargs) + return self.series.anonymize(id_=id_, json=data, **kwargs) def get_series_archive(self, id_, **kwargs): """Create a ZIP archive for media storage with DICOMDIR @@ -694,7 +760,6 @@ :rtype: generator """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.archive(id_=id_, **kwargs) def get_series_instances(self, id_, **kwargs): @@ -707,52 +772,40 @@ :rtype: list (dict) """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.instances(id_=id_, **kwargs) def get_series_instances_tags(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.instances_tags(id_=id_, **kwargs) def get_series_media(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.media(id_=id_, **kwargs) def modify_series(self, id_, data, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.series.modify(id_=id_, data=j, **kwargs) + return self.series.modify(id_=id_, json=data, **kwargs) def get_series_module(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.module(id_=id_, **kwargs) def get_series_ordered_slices(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.ordered_slices(id_=id_, **kwargs) def get_series_patient(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.patient(id_=id_, **kwargs) def reconstruct_series(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.reconstruct(id_=id_, **kwargs) def get_series_shared_tags(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.shared_tags(id_=id_, **kwargs) def get_series_statistics(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.statistics(id_=id_, **kwargs) def get_series_study(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.series.study(id_=id_, **kwargs) #### STUDIES - def get_studies(self, expand=False, since=0, limit=None, params=None, **kwargs): + def get_studies(self, expand=False, since=None, limit=None, params=None, **kwargs): """Return study record(s) Use ``expand`` keyword argument to retrieve expanded information. @@ -762,9 +815,9 @@ Return verbose information about studies. Default ``False``. By default, returns UUIDs. :param int since: - Return since nth study record. Default ``0``. + Return since nth study record. Optional. Must use with ``limit``. :param int limit: - Limit to given number of records. Optional. + Limit to given number of records. Optional. Must use with ``since``. :param dict params: Provide paramaters dict to override other values :return: @@ -772,120 +825,78 @@ :rtype: list """ - if params is None: - params = {} - if expand == True: - params["expand"] = True - if limit: - try: - params["since"] = int(since) - params["limit"] = int(limit) - except: - raise TypeError("Must provide valid ints as since and limit") - kwargs["params"] = self.clean(params) - else: - kwargs["params"] = params - kwargs["auth"] = kwargs.get("auth", self._auth) + kwargs["params"] = self.build_root_parameters(expand, since, limit, params) return self.studies.studies(**kwargs) def get_study(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.study(id_=id_, **kwargs) def delete_study(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.del_study(id_=id_, **kwargs) def anonymize_study(self, id_, data={}, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.studies.anonymize(id_=id_, data=j, **kwargs) + return self.studies.anonymize(id_=id_, json=data, **kwargs) def get_study_archive(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.archive(id_=id_, **kwargs) def get_study_instances(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.instances(id_=id_, **kwargs) def get_study_instances_tags(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.instances_tags(id_=id_, **kwargs) def get_study_media(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.media(id_=id_, **kwargs) def modify_study(self, id_, data, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.studies.modify(id_=id_, data=j, **kwargs) + return self.studies.modify(id_=id_, json=data, **kwargs) def get_study_module(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.module(id_=id_, **kwargs) def get_study_module_patient(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.module_patient(id_=id_, **kwargs) def get_study_patient(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.patient(id_=id_, **kwargs) def reconstruct_study(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.reconstruct(id_=id_, **kwargs) def get_study_series(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.series(id_=id_, **kwargs) def get_study_shared_tags(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.shared_tags(id_=id_, **kwargs) def get_study_statistics(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.studies.statistics(id_=id_, **kwargs) #### MODALITIES ### def get_modalities(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.modalities.modalities(**kwargs) def get_modality(self, dicom, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.modalities.modality(dicom=dicom, **kwargs) def delete_modality(self, dicom, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.modalities.del_modality(dicom=dicom, **kwargs) def update_modality(self, dicom, data, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.modalities.put_modality(dicom=dicom, data=j, **kwargs) + return self.modalities.put_modality(dicom=dicom, json=data, **kwargs) def echo_modality(self, dicom, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.modalities.echo(dicom=dicom, data={}, **kwargs) def move_modality(self, dicom, data, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.modalities.move(dicom=dicom, data=j, **kwargs) + return self.modalities.move(dicom=dicom, json=data, **kwargs) def query_modality(self, dicom, data, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.modalities.query(dicom=dicom, data=j, **kwargs) + return self.modalities.query(dicom=dicom, json=data, **kwargs) def store_modality(self, dicom, data, **kwargs): - j = self.convert_to_json(data) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.modalities.store(dicom=dicom, data=j, **kwargs) + return self.modalities.store(dicom=dicom, json=data, **kwargs) #### SERVER-RELATED def get_changes(self, since=0, limit=100, last=False, **kwargs): @@ -912,79 +923,60 @@ kwargs["params"] = {"last": ""} # overrule else: kwargs["params"] = {"since": since, "limit": limit} # overrule - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.changes(**kwargs) def clear_changes(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.del_changes(**kwargs) def get_exports(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.exports(**kwargs) def clear_exports(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.del_exports(**kwargs) def get_jobs(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.jobs(**kwargs) def get_job(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.job(id_=id_, **kwargs) def cancel_job(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.cancel_job(id_=id_, data={}, **kwargs) def pause_job(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.pause_job(id_=id_, data={}, **kwargs) def resubmit_job(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.resubmit_job(id_=id_, data={}, **kwargs) def resume_job(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.resume_job(id_=id_, data={}, **kwargs) def get_peers(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.peers(**kwargs) def get_peer(self, peer, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.peer(peer=peer, **kwargs) def delete_peer(self, peer, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.del_peer(peer=peer, **kwargs) def put_peer(self, peer, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.put_peer(peer=peer, **kwargs) def store_peer(self, peer, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.store_peer(peer=peer, **kwargs) def get_plugins(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.plugins(**kwargs) def get_plugin(self, id_, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.plugin(id_=id_, **kwargs) def get_plugins_js(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.plugins_js(**kwargs) def get_statistics(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.statistics(**kwargs) def get_system(self, **kwargs): @@ -995,31 +987,24 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.system(**kwargs) def create_archive(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_create_archive(**kwargs) def create_dicom(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_create_dicom(**kwargs) def create_media(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_create_media(**kwargs) def create_media_extended(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_create_media_extended(**kwargs) def get_default_encoding(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_default_encoding(**kwargs) def change_default_encoding(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_post_default_encoding(**kwargs) def get_dicom_conformance(self, **kwargs): @@ -1030,13 +1015,10 @@ :rtype: str """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_dicom_conformance(**kwargs) def execute_script(self, script, **kwargs): - j = self.convert_to_json(script) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.server.tools_execute_script(data=j, **kwargs) + return self.server.tools_execute_script(json=data, **kwargs) def find(self, query, level, expand=False, limit=None, **kwargs): """Search for matching items @@ -1061,9 +1043,7 @@ list """ body = {"Query": query, "Level": level, "Expand": expand, "Limit": limit} - j = self.convert_to_json(body) - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.server.tools_find(data=j, **kwargs) + return self.server.tools_find(json=body, **kwargs) def generate_uid(self, level, **kwargs): """Generate DICOM UID @@ -1078,25 +1058,22 @@ if level not in ["patient", "instance", "series", "study"]: raise ValueError("Must be patient, instance, series, or study") params = {"level": level} - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_generate_uid(params=params, **kwargs) def invalidate_tags(self, **kwargs): - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_invalidate_tags(**kwargs) def lookup(self, lookup, **kwargs): """Map DICOM UIDs to Orthanc identifiers - :param lookup: + :param list lookup: UID(s) to map :return: Orthanc identifiers :rtype: list """ - kwargs["auth"] = kwargs.get("auth", self._auth) - return self.server.tools_lookup(data=self.convert_to_json(lookup), **kwargs) + return self.server.tools_lookup(json=lookup, **kwargs) def get_now(self, **kwargs): """Get the current universal datetime (UTC) in the ISO 8601 format @@ -1106,7 +1083,6 @@ :rtype: str (ISO 8601) """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_now(**kwargs) def get_now_local(self, **kwargs): @@ -1117,7 +1093,6 @@ :rtype: str (ISO 8601) """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_now_local(**kwargs) def reconstruct(self, **kwargs): @@ -1128,7 +1103,6 @@ :rtype: str """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_reconstruct(data={}, **kwargs) def reset(self, **kwargs): @@ -1139,7 +1113,6 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_reset(data={}, **kwargs) def shutdown(self, **kwargs): @@ -1150,5 +1123,4 @@ :rtype: dict """ - kwargs["auth"] = kwargs.get("auth", self._auth) return self.server.tools_shutdown(data={}, **kwargs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beren-0.6.2/beren.egg-info/PKG-INFO new/beren-0.7.0/beren.egg-info/PKG-INFO --- old/beren-0.6.2/beren.egg-info/PKG-INFO 2019-10-28 19:11:21.000000000 +0100 +++ new/beren-0.7.0/beren.egg-info/PKG-INFO 2020-07-26 22:57:20.000000000 +0200 @@ -1,30 +1,32 @@ Metadata-Version: 2.1 Name: beren -Version: 0.6.2 +Version: 0.7.0 Summary: REST client for Orthanc DICOM servers Home-page: https://github.com/teffalump/beren Author: teffalump Author-email: [email protected] License: UNKNOWN -Description: # Beren +Description: # beren - [](https://travis-ci.com/teffalump/beren) + [](https://travis-ci.com/teffalump/beren) [](https://badge.fury.io/py/beren) - Provides a REST client targeted at [Orthanc](https://www.orthanc-server.com) REST API endpoints. + `beren` provides a REST client for [Orthanc](https://www.orthanc-server.com), an open-source DICOM server. - Based on the excellent [apiron](https://github.com/ithaka/apiron) library. + Built using the excellent [apiron](https://github.com/ithaka/apiron) library. ### Install + Use pip: + pip install beren ### How to use - Import the pre-defined client and pass the server details + Import the client and provide the server details from beren import Orthanc - orthanc = Orthanc('http://localhost:8042') + orthanc = Orthanc('https://example-orthanc-server.com') # Patient endpoints orthanc.get_patients() @@ -60,42 +62,80 @@ ### Authentication - Pass valid auth object: + Many servers require authentication to utilize their API. Simply provide a valid authentication object when defining the client: from requests.auth import HTTPBasicAuth auth = HTTPBasicAuth('orthanc', 'orthanc') orthanc = Orthanc('https://test.server.com', auth=auth) - Then call functions normally (the auth object is passed automatically). + To override the default authentication, provide a new authentication object when calling the endpoint: - ### Advanced examples + new_auth = HTTPBasicAuth('new_user', 'new_password') + orthanc.get_patients(auth=auth) - For example, to save an instance file to local directory: + ### Advanced Configuration - with open('test_file.dcm', 'wb') as dcm: - for chunk in orthanc.get_instance_file(instance_id): - dcm.write(chunk) + #### Timeouts - To get a zip of DCM files from a series: + Some servers are slow (and some methods can be slow). For example, asking for all instances from a server can cause a timeout before the server responds. To + modify the timeout settings, use `apiron`'s `Timeout` class: - with open('test.zip', 'wb') as z: - for chunk in orthanc.get_series_archive(<id>): - z.write(chunk) + from apiron import Timeout + t = Timeout(read_timeout=6, connection_timeout=1) # Modify the timeout + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + orthanc.get_instances(timeout_spec=t) # Use new timeout - ### Security warning on non-HTTPS endpoints + Increase the read timeout if the endpoint is slow. Increase the connection timeout for slow servers. - The rest client will warn when using HTTP endpoints. Strongly consider using HTTPS given the data sensitivity. + #### Disable Certificate Checks - You can disable the warning using the `warn_insecure` keyword argument: + To disable TLS certificate checking, use sessions: + import requests + session = requests.sessions.Session() # New session + session.verify = False # Disable certificate checking + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + orthanc.get_patients(session=session) # Use session + + #### Non-HTTPS endpoints + + The client will warn when using HTTP endpoints. Medical data is particularly sensitive, consequently, strongly consider using HTTPS. + + You can disable the warning using the `warn_insecure` argument: + + from beren import Orthanc orthanc = Orthanc('http://insecure.endpoint.com', warn_insecure=False) + ### Examples + + To save an instance file to the local directory: + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + + with open('test_file.dcm', 'wb') as dcm: + for chunk in orthanc.get_instance_file(<instance_id>): + dcm.write(chunk) + + To get an archive of a series (DCM files in a zip file): + + from beren import Orthanc + orthanc = Orthanc('https://example-orthanc-server.com') + + with open('test.zip', 'wb') as z: + for chunk in orthanc.get_series_archive(<instance_id>): + z.write(chunk) + ### Further help - [apiron](https://github.com/ithaka/apiron) - [Orthanc documentation](https://book.orthanc-server.com) - [Orthanc OpenAPI](https://api.orthanc-server.com) - - [Orthanc REST API spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vSBEymDKGZgskFEFF6yzge5JovGHPK_FIbEnW5a6SWUbPkX06tkoObUHh6T1XQhgj-HqFd0AWSnVFOv/pubhtml?gid=654036639&single=true) + - [Orthanc REST API spreadsheet](https://docs.google.com/spreadsheets/d/1muKHMIb9Br-59wfaQbDeLzAfKYsoWfDSXSmyt6P4EM8/pubhtml#) Platform: UNKNOWN Classifier: Development Status :: 4 - Beta diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beren-0.6.2/beren.egg-info/requires.txt new/beren-0.7.0/beren.egg-info/requires.txt --- old/beren-0.6.2/beren.egg-info/requires.txt 2019-10-28 19:11:21.000000000 +0100 +++ new/beren-0.7.0/beren.egg-info/requires.txt 2020-07-26 22:57:20.000000000 +0200 @@ -1 +1 @@ -apiron>=2.5.0 +apiron==5.1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beren-0.6.2/dev-requirements.txt new/beren-0.7.0/dev-requirements.txt --- old/beren-0.6.2/dev-requirements.txt 2019-10-24 18:18:31.000000000 +0200 +++ new/beren-0.7.0/dev-requirements.txt 2020-04-18 03:03:53.000000000 +0200 @@ -1,4 +1,3 @@ -r requirements.txt -pytest==4.2.0 -twine==1.11.0 +pytest==5.4.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beren-0.6.2/requirements.txt new/beren-0.7.0/requirements.txt --- old/beren-0.6.2/requirements.txt 2019-10-24 18:18:31.000000000 +0200 +++ new/beren-0.7.0/requirements.txt 2020-07-26 21:48:08.000000000 +0200 @@ -1 +1 @@ -apiron>=2.5.0 +apiron==5.1.0
