diff --git a/.gitignore b/.gitignore index fcc3e0be27b75860d4ed9a1054ba5799db774104..341bfea4f1381b6eb59e548f395859bad35520d7 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ __pycache__/ *.egg-info/ dist/ build/ +src/caosdb/version.py diff --git a/CHANGELOG.md b/CHANGELOG.md index b7f4dea462916b8bb6a792e75283da0cabc8614b..c7e92345efdf7e3c3c94928324c8e31bbee6797a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - An `auth_token` parameter for `caosdb.configure_connection(...)`. This parameter accepts a plain text auth token (which can only be issued by the CaosDB Server). Under the hood, auth tokens are stored plain, instead of urlencoded now. - New type of exception: `ConfigurationException` for misconfigurations. - Some unit tests, mainly for the `caosdb.connection.authentication` module +* Advanced setup.py for easy versioning and publication as pypi repository. ### Changed - [pytest](https://docs.pytest.org/en/latest/) is the new preferred unit test frame work. diff --git a/README.md b/README.md index 637a8ffcdb35b44289499ca85239b5ba85626df6..242081ba042969b4728ec330ac8d2f4d93626bc9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,3 @@ -<!--THIS FILE HAS BEEN GENERATED BY A SCRIPT. PLEASE DON'T CHANGE IT MANUALLY.--> -Project migrated to https://gitlab.com/caosdb - # Welcome This is the **CaosDB Python Client Library** repository and a part of the diff --git a/release.sh b/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..49ecd59be2ba720791035ffe1a57e7c21fd23b71 --- /dev/null +++ b/release.sh @@ -0,0 +1,3 @@ +#!/bin/bash +python setup.py bdist_wheel +python -m twine upload dist/* diff --git a/setup.py b/setup.py index 792ef41a663eaa289253c450389828e5c138cd15..b461efca3b870c3564dcdbb03d518e3b6cadd8da 100755 --- a/setup.py +++ b/setup.py @@ -1,43 +1,171 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- # -# ** header v3.0 -# This file is a part of the CaosDB Project. -# -# Copyright (C) 2018 Research Group Biomedical Physics, -# Max-Planck-Institute for Dynamics and Self-Organization Göttingen -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <https://www.gnu.org/licenses/>. -# -# ** end header -# -"""Install and (nose-)test caosdb.""" -from setuptools import setup, find_packages - -setup(name='PyCaosDB', - version='0.1.0', - description='Python Interface for CaosDB', - author='Timm Fitschen', - author_email='timm.fitschen@ds.mpg.de', - packages=find_packages('src'), - package_dir={'': 'src'}, - install_requires=['lxml>=3.6.4', - 'PyYaml>=3.12', 'future', 'PySocks>=1.6.7'], - extras_require={'keyring': ['keyring>=13.0.0']}, - setup_requires=["pytest-runner>=2.0,<3dev"], - tests_require=["pytest", "pytest-cov", "coverage>=4.4.2"], - package_data={ +# +"""caosdb""" +import os +import subprocess +import sys + +from setuptools import find_packages, setup + +######################################################################## +# The following code is largely based on code in numpy +######################################################################## +# +# Copyright (c) 2005-2019, NumPy Developers. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# * Neither the name of the NumPy Developers nor the names of any +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +######################################################################## + +MAJOR = 0 +MINOR = 2 +MICRO = 4 +ISRELEASED = False +VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO) + + +# Return the git revision as a string +def git_version(): + def _minimal_ext_cmd(cmd): + # construct minimal environment + env = {} + + for k in ['SYSTEMROOT', 'PATH', 'HOME']: + v = os.environ.get(k) + + if v is not None: + env[k] = v + # LANGUAGE is used on win32 + env['LANGUAGE'] = 'C' + env['LANG'] = 'C' + env['LC_ALL'] = 'C' + out = subprocess.check_output(cmd, stderr=subprocess.STDOUT, env=env) + + return out + + try: + out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD']) + GIT_REVISION = out.strip().decode('ascii') + except (subprocess.SubprocessError, OSError): + GIT_REVISION = "Unknown" + + return GIT_REVISION + + +def get_version_info(): + # Adding the git rev number needs to be done inside write_version_py(), + # otherwise the import of caosdb.version messes up the build under + # Python 3. + FULLVERSION = VERSION + + if os.path.exists('.git'): + GIT_REVISION = git_version() + elif os.path.exists('src/caosdb/version.py'): + # must be a source distribution, use existing version file + try: + from caosdb.version import git_revision as GIT_REVISION + except ImportError: + raise ImportError("Unable to import git_revision. Try removing " + "src/caosdb/version.py and the build directory " + "before building.") + else: + GIT_REVISION = "Unknown" + + if not ISRELEASED: + FULLVERSION += '.dev0+' + GIT_REVISION[:7] + + return FULLVERSION, GIT_REVISION + + +def write_version_py(filename='src/caosdb/version.py'): + cnt = """ +# THIS FILE IS GENERATED FROM caosdb SETUP.PY +# +short_version = '%(version)s' +version = '%(version)s' +full_version = '%(full_version)s' +git_revision = '%(git_revision)s' +release = %(isrelease)s + +if not release: + version = full_version +""" + FULLVERSION, GIT_REVISION = get_version_info() + + a = open(filename, 'w') + try: + a.write(cnt % {'version': VERSION, + 'full_version': FULLVERSION, + 'git_revision': GIT_REVISION, + 'isrelease': str(ISRELEASED)}) + finally: + a.close() + + +def setup_package(): + # load README + with open("README.md", "r") as fh: + long_description = fh.read() + + src_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "src") + sys.path.insert(0, src_path) + + # Rewrite the version file everytime + write_version_py() + + metadata = dict( + name='caosdb', + version=get_version_info()[0], + description='Python Interface for CaosDB', + long_description=long_description, + long_description_content_type="text/markdown", + author='Timm Fitschen', + author_email='t.fitschen@indiscale.com', + packages=find_packages('src'), + package_dir={'': 'src'}, + install_requires=['lxml>=3.6.4', + 'PyYaml>=3.12', 'future', 'PySocks>=1.6.7'], + extras_require={'keyring': ['keyring>=13.0.0']}, + setup_requires=["pytest-runner>=2.0,<3dev"], + tests_require=["pytest", "pytest-cov", "coverage>=4.4.2"], + package_data={ 'caosdb': ['cert/indiscale.ca.crt'], - } - ) + } + ) + try: + setup(**metadata) + finally: + del sys.path[0] + return + + +if __name__ == '__main__': + setup_package() diff --git a/src/caosdb/connection/authentication/keyring.py b/src/caosdb/connection/authentication/keyring.py index abdbf112e20279d9c7211d01bebd296869edea5d..1dc986174acbe23191305632afda91cda0c718d2 100644 --- a/src/caosdb/connection/authentication/keyring.py +++ b/src/caosdb/connection/authentication/keyring.py @@ -73,7 +73,7 @@ def _call_keyring(**config): "password in question.") url = config.get("url") username = config.get("username") - app = "PyCaosDB — {}".format(url) + app = "caosdb — {}".format(url) password = _call_keyring(app=app, username=username) external_keyring = _get_external_keyring() password = external_keyring.get_password(app, username) diff --git a/src/caosdb/connection/connection.py b/src/caosdb/connection/connection.py index 1a40f4eb48c71a8fc632e88b310d9f5ce50cf209..3e2ec2cdba5e4cddce6557969c661ba82c1c16d2 100644 --- a/src/caosdb/connection/connection.py +++ b/src/caosdb/connection/connection.py @@ -32,6 +32,7 @@ from builtins import str # pylint: disable=redefined-builtin from errno import EPIPE as BrokenPipe from socket import error as SocketError +from caosdb.version import version from caosdb.configuration import get_config from caosdb.exceptions import (AuthorizationException, CaosDBException, ClientErrorException, ConfigurationException, @@ -87,8 +88,7 @@ class _DefaultCaosDBServerConnection(CaosDBServerConnection): """ def __init__(self): - self._useragent = ("PyCaosDB - " - "DefaultCaosDBServerConnection") + self._useragent = ("caosdb-pylib/{version} - {implementation}".format(version=version, implementation=type(self).__name__)) self._http_con = None self._base_path = None @@ -120,6 +120,7 @@ class _DefaultCaosDBServerConnection(CaosDBServerConnection): if headers is None: headers = {} + headers["User-Agent"] = self._useragent try: self._http_con = StreamingHTTPSConnection( # TODO looks as if configure needs to be done first. diff --git a/tox.ini b/tox.ini index 0ad658afb4bf82d39a066437d5f0955915845ef6..97f7753720f8b8647476654518e0c65e1ec7906e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,10 @@ [tox] -envlist=py34, py35, py36, py37 +envlist=py34, py35, py36, py37, py38 skip_missing_interpreters = true + [testenv] -deps=nose +deps = . + nose pytest pytest-cov commands=py.test --cov=caosdb -vv {posargs}