From 11b478cad49b30b2181e6f567a5fddd5a03ddf61 Mon Sep 17 00:00:00 2001 From: Bryna Hazelton Date: Fri, 14 Dec 2018 12:46:38 -0800 Subject: [PATCH 1/8] Cleanup version and setup code, add changelog, increase version number --- CHANGELOG.md | 6 ++ hera_mc/VERSION | 1 + hera_mc/__init__.py | 4 +- hera_mc/tests/test_version.py | 132 ++++++++++++++++++++++++++ hera_mc/version.py | 173 +++++++++++++++++++--------------- setup.py | 59 +++++++----- 6 files changed, 274 insertions(+), 101 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 hera_mc/VERSION create mode 100644 hera_mc/tests/test_version.py diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..98b3bb108 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog +All notable changes to this project will be documented in this file. + +## [Unreleased] + +## [1.0.0] - 2018-12-04 diff --git a/hera_mc/VERSION b/hera_mc/VERSION new file mode 100644 index 000000000..3eefcb9dd --- /dev/null +++ b/hera_mc/VERSION @@ -0,0 +1 @@ +1.0.0 diff --git a/hera_mc/__init__.py b/hera_mc/__init__.py index 6426ec2b5..4378f7884 100644 --- a/hera_mc/__init__.py +++ b/hera_mc/__init__.py @@ -84,7 +84,9 @@ def NotNull(kind, **kwargs): return Column(kind, nullable=False, **kwargs) -from .version import __version__ # noqa +from . import version # noqa +__version__ = version.version + from . import autocorrelations # noqa from . import cm_transfer # noqa from . import part_connect # noqa diff --git a/hera_mc/tests/test_version.py b/hera_mc/tests/test_version.py new file mode 100644 index 000000000..7843112be --- /dev/null +++ b/hera_mc/tests/test_version.py @@ -0,0 +1,132 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright 2018 the HERA Collaboration +# Licensed under the 2-clause BSD license. + +"""Tests for version.py. + +""" +from __future__ import absolute_import, division, print_function + +import nose.tools as nt +import sys +import os +import six +import subprocess +import json + +import hera_mc +from hera_mc.data import DATA_PATH + + +def test_get_gitinfo_file(): + hera_mc_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + + git_file = os.path.join(hera_mc_dir, 'GIT_INFO') + if not os.path.exists(git_file): + # write a file to read in + temp_git_file = os.path.join(DATA_PATH, 'test_data/GIT_INFO') + version_info = hera_mc.version.construct_version_info() + data = [version_info['git_origin'], version_info['git_origin'], + version_info['git_origin'], version_info['git_origin']] + with open(temp_git_file, 'w') as outfile: + json.dump(data, outfile) + git_file = temp_git_file + + with open(git_file) as data_file: + data = [hera_mc.version._unicode_to_str(x) for x in json.loads(data_file.read().strip())] + git_origin = data[0] + git_hash = data[1] + git_description = data[2] + git_branch = data[3] + + test_file_info = {'git_origin': git_origin, 'git_hash': git_hash, + 'git_description': git_description, 'git_branch': git_branch} + + if 'temp_git_file' in locals(): + file_info = hera_mc.version._get_gitinfo_file(git_file=temp_git_file) + os.remove(temp_git_file) + else: + file_info = hera_mc.version._get_gitinfo_file() + + nt.assert_equal(file_info, test_file_info) + + +def test_construct_version_info(): + # this test is a bit silly because it uses the nearly the same code as the original, + # but it will detect accidental changes that could cause problems. + # It does test that the __version__ attribute is set on hera_mc. + + # this line is modified from the main implementation since we're in hera_mc/tests/ + hera_mc_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + + def get_git_output(args, capture_stderr=False): + """Get output from Git, ensuring that it is of the ``str`` type, + not bytes.""" + + argv = ['git', '-C', hera_mc_dir] + args + + if capture_stderr: + data = subprocess.check_output(argv, stderr=subprocess.STDOUT) + else: + data = subprocess.check_output(argv) + + data = data.strip() + + if six.PY2: + return data + return data.decode('utf8') + + def unicode_to_str(u): + if six.PY2: + return u.encode('utf8') + return u + + try: + git_origin = get_git_output(['config', '--get', 'remote.origin.url'], capture_stderr=True) + git_hash = get_git_output(['rev-parse', 'HEAD'], capture_stderr=True) + git_description = get_git_output(['describe', '--dirty', '--tag', '--always']) + git_branch = get_git_output(['rev-parse', '--abbrev-ref', 'HEAD'], capture_stderr=True) + except subprocess.CalledProcessError: + try: + # Check if a GIT_INFO file was created when installing package + git_file = os.path.join(hera_mc_dir, 'GIT_INFO') + with open(git_file) as data_file: + data = [unicode_to_str(x) for x in json.loads(data_file.read().strip())] + git_origin = data[0] + git_hash = data[1] + git_description = data[2] + git_branch = data[3] + except (IOError, OSError): + git_origin = '' + git_hash = '' + git_description = '' + git_branch = '' + + test_version_info = {'version': hera_mc.__version__, 'git_origin': git_origin, + 'git_hash': git_hash, 'git_description': git_description, + 'git_branch': git_branch} + + print(hera_mc.version.construct_version_info()) + print('\n') + print(test_version_info) + + nt.assert_equal(hera_mc.version.construct_version_info(), test_version_info) + + +def test_main(): + version_info = hera_mc.version.construct_version_info() + + saved_stdout = sys.stdout + try: + out = six.StringIO() + sys.stdout = out + hera_mc.version.main() + output = out.getvalue() + nt.assert_equal(output, 'Version = {v}\ngit origin = {o}\n' + 'git branch = {b}\ngit description = {d}\n' + .format(v=version_info['version'], + o=version_info['git_origin'], + b=version_info['git_branch'], + d=version_info['git_description'])) + finally: + sys.stdout = saved_stdout diff --git a/hera_mc/version.py b/hera_mc/version.py index 8fad92800..79d70760f 100644 --- a/hera_mc/version.py +++ b/hera_mc/version.py @@ -1,76 +1,101 @@ -"""Version definition for hera_mc.""" +#! /usr/bin/env python +# -*- mode: python; coding: utf-8 -*- +# Copyright 2018 the HERA Collaboration +# Licensed under the 2-clause BSD license. + from __future__ import absolute_import, division, print_function -from os.path import join as pjoin -import glob - -# Format expected by setup.py and doc/source/conf.py: string of form "X.Y.Z" -_version_major = 0 -_version_minor = 1 -_version_micro = '' # use '' for first of series, number for 1 and above -_version_extra = 'dev' -# _version_extra = '' # Uncomment this for full releases - -# Construct full version string from these. -_ver = [_version_major, _version_minor] -if _version_micro: - _ver.append(_version_micro) -if _version_extra: - _ver.append(_version_extra) - -__version__ = '.'.join(map(str, _ver)) - -CLASSIFIERS = ["Development Status :: 3 - Alpha", - "Environment :: Console", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Topic :: Scientific/Engineering"] - -# Description should be a one-liner: -description = "hera_mc: HERA monitor and control" -# Long description will go up on the pypi page -long_description = """ -hera_mc -======== -hera_mc -To get started using these components in your own software, please go to the -repository README_. -License -======= -``hera_mc`` is licensed under the terms of the BSD license. See the file -"LICENSE" for information on the history of this software, terms & conditions -for usage, and a DISCLAIMER OF ALL WARRANTIES. -All trademarks referenced herein are property of their respective holders. -Copyright (c) 2015--, HERA-Team. -""" - -NAME = "hera_mc" -MAINTAINER = "HERA Team" -MAINTAINER_EMAIL = "hera-sw@lists.berkeley.edu" -DESCRIPTION = description -LONG_DESCRIPTION = long_description -URL = "https://github.com/HERA-Team/hera_mc" -DOWNLOAD_URL = "" -LICENSE = "BSD" -AUTHOR = "HERA Team" -AUTHOR_EMAIL = "hera-sw@lists.berkeley.edu" -PLATFORMS = "OS Independent" -MAJOR = _version_major -MINOR = _version_minor -MICRO = _version_micro -VERSION = __version__ -PACKAGES = ['hera_mc', - 'hera_mc.tests'] -SCRIPTS = [p for p in glob.glob('scripts/*') if not p.endswith('~')] -PACKAGE_DATA = { - 'hera_mc': [ - pjoin('data', '*.csv'), - pjoin('data', '*.txt'), - pjoin('data', 'finals.all'), - pjoin('data', 'test_data', '*.tst'), - ] -} -REQUIRES = ["six", "numpy", "astropy", "sqlalchemy", "psycopg2", "alembic", "dateutil", - "tabulate", "pandas", "psutil", "pyproj"] +import os +import six +import subprocess +import json + +hera_mc_dir = os.path.dirname(os.path.realpath(__file__)) + + +def _get_git_output(args, capture_stderr=False): + """Get output from Git, ensuring that it is of the ``str`` type, + not bytes.""" + + argv = ['git', '-C', hera_mc_dir] + args + + if capture_stderr: + data = subprocess.check_output(argv, stderr=subprocess.STDOUT) + else: + data = subprocess.check_output(argv) + + data = data.strip() + + if six.PY2: + return data + return data.decode('utf8') + + +def _get_gitinfo_file(git_file=None): + """Get saved info from GIT_INFO file that was created when installing package""" + if git_file is None: + git_file = os.path.join(hera_mc_dir, 'GIT_INFO') + + with open(git_file) as data_file: + data = [_unicode_to_str(x) for x in json.loads(data_file.read().strip())] + git_origin = data[0] + git_hash = data[1] + git_description = data[2] + git_branch = data[3] + + return {'git_origin': git_origin, 'git_hash': git_hash, + 'git_description': git_description, 'git_branch': git_branch} + + +def _unicode_to_str(u): + if six.PY2: + return u.encode('utf8') + return u + + +def construct_version_info(): + + version_file = os.path.join(hera_mc_dir, 'VERSION') + with open(version_file) as f: + version = f.read().strip() + + git_origin = '' + git_hash = '' + git_description = '' + git_branch = '' + + version_info = {'version': version, 'git_origin': '', 'git_hash': '', + 'git_description': '', 'git_branch': ''} + + try: + version_info['git_origin'] = _get_git_output(['config', '--get', 'remote.origin.url'], capture_stderr=True) + version_info['git_hash'] = _get_git_output(['rev-parse', 'HEAD'], capture_stderr=True) + version_info['git_description'] = _get_git_output(['describe', '--dirty', '--tag', '--always']) + version_info['git_branch'] = _get_git_output(['rev-parse', '--abbrev-ref', 'HEAD'], capture_stderr=True) + except subprocess.CalledProcessError: # pragma: no cover + try: + # Check if a GIT_INFO file was created when installing package + version_info.update(_get_gitinfo_file()) + except (IOError, OSError): + pass + + return version_info + + +version_info = construct_version_info() +version = version_info['version'] +git_origin = version_info['git_origin'] +git_hash = version_info['git_hash'] +git_description = version_info['git_description'] +git_branch = version_info['git_branch'] + + +def main(): + print('Version = {0}'.format(version)) + print('git origin = {0}'.format(git_origin)) + print('git branch = {0}'.format(git_branch)) + print('git description = {0}'.format(git_description)) + + +if __name__ == '__main__': # pragma: no cover + main() diff --git a/setup.py b/setup.py index d9ad2868e..61e766aa7 100755 --- a/setup.py +++ b/setup.py @@ -6,33 +6,40 @@ from __future__ import absolute_import, division, print_function import os -from setuptools import setup, find_packages -PACKAGES = find_packages() - -# Get version and release info, which is all stored in shablona/version.py -ver_file = os.path.join('hera_mc', 'version.py') -with open(ver_file) as f: - exec(f.read()) - - -setup_args = dict(name=NAME, - maintainer=MAINTAINER, - maintainer_email=MAINTAINER_EMAIL, - description=DESCRIPTION, - long_description=LONG_DESCRIPTION, - url=URL, - download_url=DOWNLOAD_URL, - license=LICENSE, - classifiers=CLASSIFIERS, - author=AUTHOR, - author_email=AUTHOR_EMAIL, - platforms=PLATFORMS, - version=VERSION, - packages=PACKAGES, - package_data=PACKAGE_DATA, - scripts=SCRIPTS, - requires=REQUIRES) +from setuptools import setup +from hera_mc import version + + +data = [version.git_origin, version.git_hash, version.git_description, version.git_branch] +with open(os.path.join('hera_mc', 'GIT_INFO'), 'w') as outfile: + json.dump(data, outfile) + +with io.open('README.md', 'r', encoding='utf-8') as readme_file: + readme = readme_file.read() + +setup_args = { + 'name': "hera_mc", + 'description': "hera_mc: HERA monitor and control", + 'long_description': readme, + 'url': "https://github.com/HERA-Team/hera_mc", + 'license': "BSD", + 'author': "HERA Team", + 'author_email': "hera-sw@lists.berkeley.edu", + 'version': version.version, + 'packages': ['hera_mc', 'hera_mc.tests'], + 'scripts': glob.glob('scripts/*'), + 'include_package_data': True, + 'requires': ["six", "numpy", "astropy", "sqlalchemy", "psycopg2", "alembic", "dateutil", + "tabulate", "pandas", "psutil", "pyproj"] + 'classifiers' = ["Development Status :: 4 - Beta", + "Environment :: Console", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Scientific/Engineering"] +} if __name__ == '__main__': setup(**setup_args) From e09f3302b3b89f98622d24ecf6f51494e5ec387c Mon Sep 17 00:00:00 2001 From: Bryna Hazelton Date: Fri, 14 Dec 2018 13:03:23 -0800 Subject: [PATCH 2/8] setup.py bug fix --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 61e766aa7..1145c361b 100755 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ 'scripts': glob.glob('scripts/*'), 'include_package_data': True, 'requires': ["six", "numpy", "astropy", "sqlalchemy", "psycopg2", "alembic", "dateutil", - "tabulate", "pandas", "psutil", "pyproj"] + "tabulate", "pandas", "psutil", "pyproj"], 'classifiers' = ["Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Science/Research", From b1264eb85bb8357c6fa02df8b78270ba2997c8d1 Mon Sep 17 00:00:00 2001 From: Bryna Hazelton Date: Fri, 14 Dec 2018 13:34:30 -0800 Subject: [PATCH 3/8] another bug fix --- setup.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index 1145c361b..d2432354a 100755 --- a/setup.py +++ b/setup.py @@ -32,13 +32,13 @@ 'include_package_data': True, 'requires': ["six", "numpy", "astropy", "sqlalchemy", "psycopg2", "alembic", "dateutil", "tabulate", "pandas", "psutil", "pyproj"], - 'classifiers' = ["Development Status :: 4 - Beta", - "Environment :: Console", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Topic :: Scientific/Engineering"] + 'classifiers': ["Development Status :: 4 - Beta", + "Environment :: Console", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Scientific/Engineering"] } if __name__ == '__main__': From 97b7385c9d3ebc6712cdf13ecdecde14189c3653 Mon Sep 17 00:00:00 2001 From: Bryna Hazelton Date: Fri, 14 Dec 2018 13:42:16 -0800 Subject: [PATCH 4/8] setup.py import fix --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index d2432354a..57c473dca 100755 --- a/setup.py +++ b/setup.py @@ -6,6 +6,9 @@ from __future__ import absolute_import, division, print_function import os +import glob +import io +import json from setuptools import setup from hera_mc import version From 6cd8e8fd406640e5412d639f9fe9f8125b6f0c22 Mon Sep 17 00:00:00 2001 From: Bryna Hazelton Date: Fri, 14 Dec 2018 13:55:25 -0800 Subject: [PATCH 5/8] add manifest --- MANIFEST.in | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..c18c7d51d --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,9 @@ +include *.md +include LICENSE +include hera_mc/VERSION +include hera_mc/GIT_INFO +include scripts/*.sh +recursive-include hera_mc/data * +recursive-include docs * +exclude docs/.DS_Store +prune docs/_build From 165cfea9c3fbe505d3d336f08292ebebf20310e0 Mon Sep 17 00:00:00 2001 From: Bryna Hazelton Date: Mon, 17 Dec 2018 17:23:40 -0800 Subject: [PATCH 6/8] move `__version__` definition after imports --- hera_mc/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hera_mc/__init__.py b/hera_mc/__init__.py index 4378f7884..8ad90e142 100644 --- a/hera_mc/__init__.py +++ b/hera_mc/__init__.py @@ -85,8 +85,6 @@ def NotNull(kind, **kwargs): from . import version # noqa -__version__ = version.version - from . import autocorrelations # noqa from . import cm_transfer # noqa from . import part_connect # noqa @@ -101,3 +99,5 @@ def NotNull(kind, **kwargs): from . import node # noqa from . import correlator # noqa from . import mc # noqa keep this last. + +__version__ = version.version From 0a890805c83e22332b314f8f52b80bb481268975 Mon Sep 17 00:00:00 2001 From: Bryna Hazelton Date: Mon, 17 Dec 2018 17:24:13 -0800 Subject: [PATCH 7/8] Differentiate install vs test requirements, add pyyaml --- setup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 57c473dca..f72f2ea67 100755 --- a/setup.py +++ b/setup.py @@ -33,8 +33,10 @@ 'packages': ['hera_mc', 'hera_mc.tests'], 'scripts': glob.glob('scripts/*'), 'include_package_data': True, - 'requires': ["six", "numpy", "astropy", "sqlalchemy", "psycopg2", "alembic", "dateutil", - "tabulate", "pandas", "psutil", "pyproj"], + 'install_requires': ["six", "numpy", "astropy", "sqlalchemy", "psycopg2", + "alembic", "dateutil", "tabulate", "pandas", "psutil", + "pyproj"], + 'tests_require': ["pyyaml"], 'classifiers': ["Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Science/Research", From 3a0872592fcbf04452daa6f9128f1ba01a20d48f Mon Sep 17 00:00:00 2001 From: Bryna Hazelton Date: Mon, 17 Dec 2018 17:32:02 -0800 Subject: [PATCH 8/8] fix dateutil package name --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f72f2ea67..9a3f593cf 100755 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ 'scripts': glob.glob('scripts/*'), 'include_package_data': True, 'install_requires': ["six", "numpy", "astropy", "sqlalchemy", "psycopg2", - "alembic", "dateutil", "tabulate", "pandas", "psutil", + "alembic", "python-dateutil", "tabulate", "pandas", "psutil", "pyproj"], 'tests_require': ["pyyaml"], 'classifiers': ["Development Status :: 4 - Beta",