Hello community, here is the log from the commit of package python-girder-client for openSUSE:Factory checked in at 2019-11-20 10:28:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-girder-client (Old) and /work/SRC/openSUSE:Factory/.python-girder-client.new.26869 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-girder-client" Wed Nov 20 10:28:58 2019 rev:2 rq:749767 version:3.0.5 Changes: -------- --- /work/SRC/openSUSE:Factory/python-girder-client/python-girder-client.changes 2019-02-01 11:48:47.328346485 +0100 +++ /work/SRC/openSUSE:Factory/.python-girder-client.new.26869/python-girder-client.changes 2019-11-20 10:29:24.278588198 +0100 @@ -1,0 +2,17 @@ +Tue Nov 19 21:05:23 UTC 2019 - Todd R <toddrme2...@gmail.com> + +- Update to 3.0.5 + * Update Google OAuth provider to use new OpenID Connect API +- Update to 3.0.4 + * Remove python-dateutil requirement. +- Update to 3.0.3 + * Add indices to audit logs +- Update to 3.0.2 + * Harden the logic when a passwordless user needs to login with OAuth +- Update to 3.0.1 + * Remove some hardcoded version numbers +- Update to 3.0.0 + * Explicitly forbid multipart upload + * Remove the access.cookie decorator. + +------------------------------------------------------------------- Old: ---- girder-client-2.4.0.tar.gz New: ---- girder-client-3.0.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-girder-client.spec ++++++ --- /var/tmp/diff_new_pack.ohAJiu/_old 2019-11-20 10:29:25.142588370 +0100 +++ /var/tmp/diff_new_pack.ohAJiu/_new 2019-11-20 10:29:25.142588370 +0100 @@ -18,14 +18,13 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-girder-client -Version: 2.4.0 +Version: 3.0.5 Release: 0 Summary: Python Girder client License: Apache-2.0 -Group: Development/Languages/Python -URL: http://girder.readthedocs.org/en/latest/python-client.html +URL: https://girder.readthedocs.org/en/latest/python-client.html Source: https://files.pythonhosted.org/packages/source/g/girder-client/girder-client-%{version}.tar.gz -BuildRequires: %{python_module devel} +BuildRequires: %{python_module setuptools_scm} BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros ++++++ girder-client-2.4.0.tar.gz -> girder-client-3.0.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/girder-client-2.4.0/PKG-INFO new/girder-client-3.0.5/PKG-INFO --- old/girder-client-2.4.0/PKG-INFO 2018-06-04 15:32:38.000000000 +0200 +++ new/girder-client-3.0.5/PKG-INFO 2019-11-15 01:09:18.000000000 +0100 @@ -1,12 +1,11 @@ Metadata-Version: 1.1 Name: girder-client -Version: 2.4.0 +Version: 3.0.5 Summary: Python client for interacting with Girder servers Home-page: http://girder.readthedocs.org/en/latest/python-client.html Author: Kitware, Inc. Author-email: kitw...@kitware.com License: Apache 2.0 -Description-Content-Type: UNKNOWN Description: Girder Python Client ==================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/girder-client-2.4.0/girder_client/__init__.py new/girder-client-3.0.5/girder_client/__init__.py --- old/girder-client-2.4.0/girder_client/__init__.py 2018-06-04 15:20:00.000000000 +0200 +++ new/girder-client-3.0.5/girder_client/__init__.py 2019-11-15 01:08:34.000000000 +0100 @@ -1,21 +1,13 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- +from pkg_resources import DistributionNotFound, get_distribution -############################################################################### -# Copyright Kitware Inc. -# -# Licensed under the Apache License, Version 2.0 ( the "License" ); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -############################################################################### +try: + __version__ = get_distribution(__name__).version +except DistributionNotFound: + # package is not installed + __version__ = None + +__license__ = 'Apache 2.0' import diskcache import errno @@ -32,10 +24,6 @@ import tempfile from contextlib import contextmanager -from requests_toolbelt import MultipartEncoder - -__version__ = '2.4.0' -__license__ = 'Apache 2.0' DEFAULT_PAGE_LIMIT = 50 # Number of results to fetch per request REQ_BUFFER_SIZE = 65536 # Chunk size when iterating a download body @@ -45,16 +33,6 @@ _logger = logging.getLogger('girder_client.lib') -def _compareDicts(x, y): - """ - Compare two dictionaries with metadata. - - :param x: First metadata item. - :param y: Second metadata item. - """ - return len(x) == len(y) == len(set(x.items()) & set(y.items())) - - def _safeMakedirs(path): """ Wraps os.makedirs in such a way that it will not raise exceptions if the @@ -86,6 +64,7 @@ exception should instead raise requests.HTTPError manually or through another mechanism such as requests.Response.raise_for_status. """ + def __init__(self, status, text, url, method, response=None): super(HttpError, self).__init__('HTTP error %s: %s %s' % (status, method, url), response=response) @@ -98,6 +77,13 @@ return super(HttpError, self).__str__() + '\nResponse text: ' + self.responseText +class IncompleteResponseError(requests.RequestException): + def __init__(self, message, expected, received, response=None): + super(IncompleteResponseError, self).__init__('%s (%d of %d bytes received)' % ( + message, received, expected + ), response=response) + + class _NoopProgressReporter(object): reportProgress = False @@ -115,7 +101,6 @@ pass -# Used for fast non-multipart upload class _ProgressBytesIO(six.BytesIO): def __init__(self, *args, **kwargs): self.reporter = kwargs.pop('reporter') @@ -127,18 +112,6 @@ return _chunk -# Used for deprecated multipart upload -class _ProgressMultiPartEncoder(MultipartEncoder): - def __init__(self, *args, **kwargs): - self.reporter = kwargs.pop('reporter') - MultipartEncoder.__init__(self, *args, **kwargs) - - def read(self, _size=-1): - _chunk = MultipartEncoder.read(self, _size) - self.reporter.update(len(_chunk)) - return _chunk - - class GirderClient(object): """ A class for interacting with the Girder RESTful API. @@ -177,9 +150,9 @@ returns `GirderClient.DEFAULT_LOCALHOST_PORT` if `hostname` is `localhost`, and finally returns `GirderClient.DEFAULT_HTTP_PORT`. """ - if scheme == "https": + if scheme == 'https': return GirderClient.DEFAULT_HTTPS_PORT - if hostname == "localhost": + if hostname == 'localhost': return GirderClient.DEFAULT_LOCALHOST_PORT return GirderClient.DEFAULT_HTTP_PORT @@ -188,10 +161,10 @@ """Get default scheme based on the hostname. Returns `http` if `hostname` is `localhost` otherwise returns `https`. """ - if hostname == "localhost": - return "http" + if hostname == 'localhost': + return 'http' else: - return "https" + return 'https' def __init__(self, host=None, port=None, apiRoot=None, scheme=None, apiUrl=None, cacheSettings=None, progressReporterCls=None): @@ -248,6 +221,7 @@ self.token = '' self._folderUploadCallbacks = [] self._itemUploadCallbacks = [] + self._serverVersion = [] self._serverApiDescription = {} self.incomingMetadata = {} self.localMetadata = {} @@ -350,6 +324,8 @@ self.setToken(resp['authToken']['token']) + return resp['user'] + def setToken(self, token): """ Set a token on the GirderClient instance. This is useful in the case @@ -370,9 +346,17 @@ :type useCached: bool :return: The API version as a list (e.g. ``['1', '0', '0']``) """ - description = self.getServerAPIDescription(useCached) - version = description.get('info', {}).get('version') - return version.split('.') if version else None + if not self._serverVersion or not useCached: + response = self.get('system/version') + if 'release' in response: + release = response['release'] # girder >= 3 + else: + release = response['apiVersion'] # girder < 3 + + # Do not include any more than 3 version components in the patch version + self._serverVersion = release.split('.', 2) + + return self._serverVersion def getServerAPIDescription(self, useCached=True): """ @@ -550,17 +534,15 @@ return self.get(route) - def resourceLookup(self, path, test=False): + def resourceLookup(self, path): """ Look up and retrieve resource in the data hierarchy by path. :param path: The path of the resource. The path must be an absolute Unix path starting with either "/user/[user name]" or "/collection/[collection name]". - :param test: Whether or not to return None, if the path does not - exist, rather than throwing an exception. """ - return self.get('resource/lookup', parameters={'path': path, 'test': test}) + return self.get('resource/lookup', parameters={'path': path}) def listResource(self, path, params=None, limit=None, offset=None): """ @@ -632,7 +614,6 @@ same name already exists. :param metadata: JSON metadata to set on item. """ - if metadata is not None and not isinstance(metadata, six.string_types): metadata = json.dumps(metadata) @@ -749,7 +730,6 @@ the same name exists. :param metadata: JSON metadata to set on the folder. """ - if metadata is not None and not isinstance(metadata, six.string_types): metadata = json.dumps(metadata) @@ -812,7 +792,6 @@ :param access: JSON document specifying access control. :param public: Boolean specificying the public value. """ - if access is not None and not isinstance(access, six.string_types): access = json.dumps(access) @@ -890,8 +869,7 @@ if '_id' not in obj: raise Exception( 'After creating an upload token for replacing file ' - 'contents, expected an object with an id. Got instead: ' + - json.dumps(obj)) + 'contents, expected an object with an id. Got instead: ' + json.dumps(obj)) else: if mimeType is None: # Attempt to guess MIME type if not passed explicitly @@ -1027,24 +1005,9 @@ if isinstance(chunk, six.text_type): chunk = chunk.encode('utf8') - if self.getServerVersion() >= ['2', '2']: - uploadObj = self.post( - 'file/chunk?offset=%d&uploadId=%s' % (offset, uploadId), - data=_ProgressBytesIO(chunk, reporter=reporter)) - else: - # Prior to version 2.2 the server only supported multipart uploads - parameters = { - 'offset': offset, - 'uploadId': uploadId - } - - m = _ProgressMultiPartEncoder( - reporter=reporter, - fields={'chunk': ('chunk', chunk, 'application/octet-stream')}, - ) - - uploadObj = self.post('file/chunk', parameters=parameters, - data=m, headers={'Content-Type': m.content_type}) + uploadObj = self.post( + 'file/chunk?offset=%d&uploadId=%s' % (offset, uploadId), + data=_ProgressBytesIO(chunk, reporter=reporter)) if '_id' not in uploadObj: raise Exception( @@ -1137,8 +1100,7 @@ if '_id' not in obj: raise Exception( 'After creating an upload token for replacing file ' - 'contents, expected an object with an id. Got instead: ' + - json.dumps(obj)) + 'contents, expected an object with an id. Got instead: ' + json.dumps(obj)) return self._uploadContents(obj, stream, size) @@ -1164,6 +1126,17 @@ obj = self.put(path, json=metadata) return obj + def addMetadataToCollection(self, collectionId, metadata): + """ + Takes a collection ID and a dictionary containing the metadata + + :param collectionId: ID of the collection to set metadata on. + :param metadata: dictionary of metadata to set on collection. + """ + path = 'collection/' + collectionId + '/metadata' + obj = self.put(path, json=metadata) + return obj + def transformFilename(self, name): """ Sanitize a resource name from Girder into a name that is safe to use @@ -1200,7 +1173,6 @@ :returns: The request """ - path = 'file/%s/download' % fileId return self.sendRestRequest('get', path, stream=True, jsonResp=False) @@ -1211,7 +1183,8 @@ :param fileId: The ID of the Girder file to download. :param path: The path to write the file to, or a file-like object. """ - created = created or self.getFile(fileId)['created'] + fileObj = self.getFile(fileId) + created = created or fileObj['created'] cacheKey = '\n'.join([self.urlBase, fileId, created]) # see if file is in local cache @@ -1236,6 +1209,11 @@ reporter.update(len(chunk)) tmp.write(chunk) + size = os.stat(tmp.name).st_size + if size != fileObj['size']: + os.remove(tmp.name) + raise IncompleteResponseError('File %s download' % fileId, fileObj['size'], size) + # save file in cache if self.cache is not None: with open(tmp.name, 'rb') as fp: @@ -1261,7 +1239,6 @@ :returns: The request content iterator. """ - req = self._streamingFileDownload(fileId) return req.iter_content(chunk_size=chunkSize) @@ -1357,8 +1334,7 @@ for item in items: _id = item['_id'] self.incomingMetadata[_id] = item - if (sync and _id in self.localMetadata and - _compareDicts(item, self.localMetadata[_id])): + if sync and _id in self.localMetadata and item == self.localMetadata[_id]: continue self.downloadItem(item['_id'], dest, name=item['name']) @@ -1422,7 +1398,6 @@ :param dest: The local download destination. """ - try: with open(os.path.join(dest, '.girder_metadata'), 'r') as fh: self.localMetadata = json.loads(fh.read()) @@ -1661,7 +1636,7 @@ # pass that as the parent_type self._uploadFolderRecursive( fullEntry, folder['_id'], 'folder', leafFoldersAsItems, reuseExisting, - dryRun=dryRun, reference=reference) + blacklist=blacklist, dryRun=dryRun, reference=reference) else: self._uploadAsItem( entry, folder['_id'], fullEntry, reuseExisting, dryRun=dryRun, @@ -1730,7 +1705,9 @@ def _checkResourcePath(self, objId): if isinstance(objId, six.string_types) and objId.startswith('/'): - obj = self.resourceLookup(objId, test=True) - if obj is not None: - return obj['_id'] + try: + return self.resourceLookup(objId)['_id'] + except requests.HTTPError: + return None + return objId diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/girder-client-2.4.0/girder_client/__main__.py new/girder-client-3.0.5/girder_client/__main__.py --- old/girder-client-2.4.0/girder_client/__main__.py 2018-05-18 21:09:17.000000000 +0200 +++ new/girder-client-3.0.5/girder_client/__main__.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -############################################################################### -# Copyright Kitware Inc. -# -# Licensed under the Apache License, Version 2.0 ( the "License" ); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -############################################################################### - -import click -from girder_client import cli - -if __name__ == '__main__': - click.echo('Deprecation notice: Use "girder-client" to run the CLI.', err=True) - cli.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/girder-client-2.4.0/girder_client/cli.py new/girder-client-3.0.5/girder_client/cli.py --- old/girder-client-2.4.0/girder_client/cli.py 2018-05-24 22:04:40.000000000 +0200 +++ new/girder-client-3.0.5/girder_client/cli.py 2019-11-15 01:08:34.000000000 +0100 @@ -1,21 +1,5 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - -############################################################################### -# Copyright Kitware Inc. -# -# Licensed under the Apache License, Version 2.0 ( the "License" ); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -############################################################################### import click import logging import requests @@ -52,7 +36,7 @@ """ def _progressBar(*args, **kwargs): bar = click.progressbar(*args, **kwargs) - bar.bar_template = "[%(bar)s] %(info)s %(label)s" + bar.bar_template = '[%(bar)s] %(info)s %(label)s' bar.show_percent = True bar.show_pos = True @@ -151,18 +135,18 @@ # Advanced options @click.option('--host', default=None, cls=_AdvancedOption, - help="[default: %s]" % GirderClient.DEFAULT_HOST) + help='[default: %s]' % GirderClient.DEFAULT_HOST) @click.option('--scheme', default=None, cls=_AdvancedOption, - help="[default: %s if %s else %s]" % ( + help='[default: %s if %s else %s]' % ( GirderClient.getDefaultScheme(GirderClient.DEFAULT_HOST), GirderClient.DEFAULT_HOST, - GirderClient.getDefaultScheme("girder.example.com"))) + GirderClient.getDefaultScheme('girder.example.com'))) @click.option('--port', default=None, cls=_AdvancedOption, - help="[default: %s if %s; %s if %s else %s]" % ( - GirderClient.DEFAULT_HTTPS_PORT, "https", - GirderClient.DEFAULT_LOCALHOST_PORT, "localhost", + help='[default: %s if %s; %s if %s else %s]' % ( + GirderClient.DEFAULT_HTTPS_PORT, 'https', + GirderClient.DEFAULT_LOCALHOST_PORT, 'localhost', GirderClient.DEFAULT_HTTP_PORT, )) @click.option('--api-root', default=None, @@ -175,8 +159,8 @@ show_default=True, cls=_AdvancedOption ) -@click.option('--certificate', default=None, - help='Specify path to SSL certificate', +@click.option('--ca-certificate', default=None, + help='Specify path to CA certificate to use to verify the server', show_default=True, cls=_AdvancedOption ) @@ -191,7 +175,7 @@ @click.pass_context def main(ctx, username, password, api_key, api_url, scheme, host, port, api_root, - no_ssl_verify, certificate, token, retries, verbose): + no_ssl_verify, ca_certificate, token, retries, verbose): """Perform common Girder CLI operations. The CLI is particularly suited to upload (or download) large, nested @@ -215,14 +199,14 @@ if has_api_url and has_url_part: raise click.BadArgumentUsage( 'Option "--api-url" and option "--%s" are mutually exclusive.' % - name.replace("_", "-")) - if certificate and no_ssl_verify: + name.replace('_', '-')) + if ca_certificate and no_ssl_verify: raise click.BadArgumentUsage( - 'Option "--no-ssl-verify" and option "--certificate" are mutually exclusive.') + 'Option "--no-ssl-verify" and option "--ca-certificate" are mutually exclusive.') ssl_verify = True - if certificate: - ssl_verify = certificate + if ca_certificate: + ssl_verify = ca_certificate if no_ssl_verify: ssl_verify = False @@ -231,10 +215,6 @@ scheme=scheme, apiUrl=api_url, apiKey=api_key, sslVerify=ssl_verify, token=token, retries=retries) - if certificate and ctx.obj.scheme != 'https': - raise click.BadArgumentUsage( - 'A URI scheme of "https" is required for option "--certificate"') - def _set_logging_level(verbosity): if not verbosity: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/girder-client-2.4.0/girder_client.egg-info/PKG-INFO new/girder-client-3.0.5/girder_client.egg-info/PKG-INFO --- old/girder-client-2.4.0/girder_client.egg-info/PKG-INFO 2018-06-04 15:32:38.000000000 +0200 +++ new/girder-client-3.0.5/girder_client.egg-info/PKG-INFO 2019-11-15 01:09:18.000000000 +0100 @@ -1,12 +1,11 @@ Metadata-Version: 1.1 Name: girder-client -Version: 2.4.0 +Version: 3.0.5 Summary: Python client for interacting with Girder servers Home-page: http://girder.readthedocs.org/en/latest/python-client.html Author: Kitware, Inc. Author-email: kitw...@kitware.com License: Apache 2.0 -Description-Content-Type: UNKNOWN Description: Girder Python Client ==================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/girder-client-2.4.0/girder_client.egg-info/SOURCES.txt new/girder-client-3.0.5/girder_client.egg-info/SOURCES.txt --- old/girder-client-2.4.0/girder_client.egg-info/SOURCES.txt 2018-06-04 15:32:38.000000000 +0200 +++ new/girder-client-3.0.5/girder_client.egg-info/SOURCES.txt 2019-11-15 01:09:18.000000000 +0100 @@ -1,7 +1,6 @@ README.rst setup.py girder_client/__init__.py -girder_client/__main__.py girder_client/cli.py girder_client.egg-info/PKG-INFO girder_client.egg-info/SOURCES.txt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/girder-client-2.4.0/setup.py new/girder-client-3.0.5/setup.py --- old/girder-client-2.4.0/setup.py 2018-05-18 21:09:17.000000000 +0200 +++ new/girder-client-3.0.5/setup.py 2019-11-15 01:08:34.000000000 +0100 @@ -1,26 +1,24 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- - -############################################################################### -# Copyright Kitware Inc. -# -# Licensed under the Apache License, Version 2.0 ( the "License" ); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -############################################################################### - import os -import re + from setuptools import setup, find_packages + +def prerelease_local_scheme(version): + """Return local scheme version unless building on master in CircleCI. + This function returns the local scheme version number + (e.g. 0.0.0.dev<N>+g<HASH>) unless building on CircleCI for a + pre-release in which case it ignores the hash and produces a + PEP440 compliant pre-release version number (e.g. 0.0.0.dev<N>). + """ + from setuptools_scm.version import get_local_node_and_date + + if os.getenv('CIRCLE_BRANCH') == 'master': + return '' + else: + return get_local_node_and_date(version) + + install_reqs = [ 'click>=6.7', 'diskcache', @@ -31,16 +29,11 @@ with open('README.rst') as f: readme = f.read() -init = os.path.join(os.path.dirname(__file__), 'girder_client', '__init__.py') -with open(init) as fd: - version = re.search( - r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', - fd.read(), re.MULTILINE).group(1) - # perform the install setup( name='girder-client', - version=version, + use_scm_version={'root': '../..', 'local_scheme': prerelease_local_scheme}, + setup_requires=['setuptools-scm'], description='Python client for interacting with Girder servers', long_description=readme, author='Kitware, Inc.',