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
         
-        [![Build 
Status](https://travis-ci.com/teffalump/beren.svg?branch=master)](https://travis-ci.com/teffalump/beren)
+        [![Build 
Status](https://travis-ci.com/teffalump/beren.svg?branch=main)](https://travis-ci.com/teffalump/beren)
         [![PyPI 
version](https://badge.fury.io/py/beren.svg)](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
 
-[![Build 
Status](https://travis-ci.com/teffalump/beren.svg?branch=master)](https://travis-ci.com/teffalump/beren)
+[![Build 
Status](https://travis-ci.com/teffalump/beren.svg?branch=main)](https://travis-ci.com/teffalump/beren)
 [![PyPI 
version](https://badge.fury.io/py/beren.svg)](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
         
-        [![Build 
Status](https://travis-ci.com/teffalump/beren.svg?branch=master)](https://travis-ci.com/teffalump/beren)
+        [![Build 
Status](https://travis-ci.com/teffalump/beren.svg?branch=main)](https://travis-ci.com/teffalump/beren)
         [![PyPI 
version](https://badge.fury.io/py/beren.svg)](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


Reply via email to