From 02bce76dbe17884b715a4a1d92589dd0193d90fd Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Tue, 14 Jan 2020 20:36:57 -0700 Subject: [PATCH 01/22] Squash commits for rebase on master --- .gitignore | 1 + .travis.yml | 17 ++++++-- licenses/LICENSE.rst => LICENSE.rst | 0 MANIFEST.in | 12 ++++-- README.rst | 44 ++++++++------------ docs/conf.py | 12 ++---- docs/licenses.rst | 2 +- licenses/README.rst | 5 --- pydl/conftest.py | 63 +++++++++++++---------------- pydl/setup_package.py | 18 --------- pyproject.toml | 5 +++ setup.cfg | 46 ++++++++++++--------- setup.py | 34 +++++++--------- tox.ini | 31 ++++++++++++++ 14 files changed, 149 insertions(+), 141 deletions(-) rename licenses/LICENSE.rst => LICENSE.rst (100%) delete mode 100644 licenses/README.rst delete mode 100644 pydl/setup_package.py create mode 100644 pyproject.toml create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index 2a4f9ff5..fe0f57b1 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ distribute-*.tar.gz # Other .cache +.tmp .tox .*.sw[op] *~ diff --git a/.travis.yml b/.travis.yml index d86fa95d..4e7639f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,11 @@ language: c os: - linux +# Disable cloning with --depth=50 (the default). This should grab the tags +# needed for setuptools_scm to work. +git: + depth: false + # The apt packages below are needed for sphinx builds. A full list of packages # that can be included can be found here: # @@ -45,8 +50,8 @@ env: # For this package-template, we include examples of Cython modules, # so Cython is required for testing. If your package does not include # Cython code, you can set CONDA_DEPENDENCIES='' - - CONDA_DEPENDENCIES='scipy matplotlib pytest-mock' - - CONDA_DEPENDENCIES_DOC='scipy matplotlib sphinx-astropy' + - CONDA_DEPENDENCIES='tox setuptools_scm scipy matplotlib pytest-mock' + - CONDA_DEPENDENCIES_DOC='tox setuptools_scm scipy matplotlib sphinx-astropy' # List other runtime dependencies for the package that are available as # pip packages here. @@ -92,15 +97,19 @@ matrix: # Check for sphinx doc build warnings - we do this first because it # may run for a long time - os: linux - env: SETUP_CMD='build_docs -w' + env: MAIN_CMD='tox -e' + SETUP_CMD='build_docs' CONDA_DEPENDENCIES=$CONDA_DEPENDENCIES_DOC + # env: MAIN_CMD='sphinx-build' + # SETUP_CMD='docs docs/_build/html -W --keep-going -b html' + # CONDA_DEPENDENCIES=$CONDA_DEPENDENCIES_DOC # Now try Astropy dev with the latest Python and LTS with and 3.x. - os: linux env: ASTROPY_VERSION=development EVENT_TYPE='pull_request push cron' - os: linux - env: PYTHON_VERSION=3.6 ASTROPY_VERSION=lts NUMPY_VERSION=1.14 PYTEST_VERSION='<3.7' + env: PYTHON_VERSION=3.6 ASTROPY_VERSION=2.0.16 NUMPY_VERSION=1.14 PYTEST_VERSION='<3.7' # Add a job that runs from cron only and tests against astropy dev and # numpy dev to give a change for early discovery of issues and feedback diff --git a/licenses/LICENSE.rst b/LICENSE.rst similarity index 100% rename from licenses/LICENSE.rst rename to LICENSE.rst diff --git a/MANIFEST.in b/MANIFEST.in index aabb3e62..5ad372c8 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,15 +1,19 @@ include README.rst +include LICENSE.rst # include CHANGES.rst include ah_bootstrap.py +include pyproject.toml include setup.cfg include pydl/tests/coveragerc -recursive-include pydl *.pyx *.c *.pxd +# recursive-include pydl *.pyx *.c *.pxd recursive-include docs * -recursive-include licenses * -recursive-include cextern * -recursive-include scripts * +recursive-include pydl/*/data/* * +recursive-include pydl/tests/t * +recursive-include pydl/*/tests/t * +# recursive-include cextern * +# recursive-include scripts * prune build prune docs/_build diff --git a/README.rst b/README.rst index af550751..443ff5e7 100644 --- a/README.rst +++ b/README.rst @@ -6,6 +6,10 @@ PyDL :target: http://www.astropy.org :alt: Powered by Astropy Badge +.. image:: https://img.shields.io/pypi/l/pydl.svg + :target: https://pypi.python.org/pypi/pydl + :alt: License + .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.2575874.svg :target: https://doi.org/10.5281/zenodo.2575874 :alt: DOI: 10.5281/zenodo.2575874 @@ -14,6 +18,18 @@ PyDL :target: https://pypi.python.org/pypi/pydl :alt: PyPI Badge +.. image:: https://img.shields.io/travis/weaverba137/pydl.svg + :target: https://travis-ci.org/weaverba137/pydl + :alt: Travis Build Status + +.. image:: https://coveralls.io/repos/weaverba137/pydl/badge.svg?branch=master&service=github + :target: https://coveralls.io/github/weaverba137/pydl?branch=master + :alt: Test Coverage Status + +.. image:: https://readthedocs.org/projects/pydl/badge/?version=latest + :target: http://pydl.readthedocs.org/en/latest/ + :alt: Documentation Status + Description ----------- @@ -36,11 +52,6 @@ Full Documentation Please visit `PyDL on Read the Docs`_ -.. image:: https://readthedocs.org/projects/pydl/badge/?version=latest - :target: http://pydl.readthedocs.org/en/latest/ - :alt: Documentation Status - - History ------- @@ -48,32 +59,11 @@ This package was initially developed on the SDSS-III_ `svn repository`_. It was moved to the new GitHub_ repository on 2013-03-06. The present location of the repository is http://github.com/weaverba137/pydl . - -Travis Build Status -------------------- - -.. image:: https://img.shields.io/travis/weaverba137/pydl.svg - :target: https://travis-ci.org/weaverba137/pydl - :alt: Travis Build Status - - -Test Coverage Status --------------------- - -.. image:: https://coveralls.io/repos/weaverba137/pydl/badge.svg?branch=master&service=github - :target: https://coveralls.io/github/weaverba137/pydl?branch=master - :alt: Test Coverage Status - - License ------- -.. image:: https://img.shields.io/pypi/l/pydl.svg - :target: https://pypi.python.org/pypi/pydl - :alt: License PyDL is free software licensed under a 3-clause BSD-style license. For details see -the ``licenses/LICENSE.rst`` file. - +the ``LICENSE.rst`` file. Legal ----- diff --git a/docs/conf.py b/docs/conf.py index 0dc9640e..6d0a6188 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,7 +28,7 @@ import os import sys import datetime -from importlib import import_module +from pkg_resources import get_distribution try: from sphinx_astropy.conf.v1 import * # noqa @@ -76,13 +76,9 @@ # |version| and |release|, also used in various other places throughout the # built documents. -import_module(setup_cfg['name']) -package = sys.modules[setup_cfg['name']] - -# The short X.Y version. -version = package.__version__.split('-', 1)[0] -# The full version, including alpha/beta/rc tags. -release = package.__version__ +release = get_distribution(setup_cfg['name']).version +# for example take major/minor +version = '.'.join(release.split('.')[:2]) # -- Options for HTML output -------------------------------------------------- diff --git a/docs/licenses.rst b/docs/licenses.rst index d7d746c3..e8eed3b9 100644 --- a/docs/licenses.rst +++ b/docs/licenses.rst @@ -7,7 +7,7 @@ PyDL License PyDL is licensed under a 3-clause BSD style license: -.. include:: ../licenses/LICENSE.rst +.. include:: ../LICENSE.rst .. Other Licenses .. ============== diff --git a/licenses/README.rst b/licenses/README.rst deleted file mode 100644 index 20c7cd4d..00000000 --- a/licenses/README.rst +++ /dev/null @@ -1,5 +0,0 @@ -Licenses -======== - -This directory holds license and credit information for the affiliated package, -works the affiliated package is derived from, and/or datasets. diff --git a/pydl/conftest.py b/pydl/conftest.py index f7490bf8..8cd90036 100644 --- a/pydl/conftest.py +++ b/pydl/conftest.py @@ -1,17 +1,24 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +# -*- coding: utf-8 -*- +# # This file is used to configure the behavior of pytest when using the Astropy # test infrastructure. +# +import os from astropy.version import version as astropy_version if astropy_version < '3.0': + # # With older versions of Astropy, we actually need to import the pytest # plugins themselves in order to make them discoverable by pytest. + # from astropy.tests.pytest_plugins import * + del pytest_report_header else: - # As of Astropy 3.0, the pytest plugins provided by Astropy are - # automatically made available when Astropy is installed. This means it's - # not necessary to import them here, but we still need to import global - # variables that are used for configuration. - from astropy.tests.plugins.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS + # As of Astropy 4.0, the pytest plugins provided by Astropy are + # now in the pytest-astropy-header package. This is backward-compatible + # with Astropy 3. + from pytest_astropy_header.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS from astropy.tests.helper import enable_deprecations_as_exceptions @@ -27,38 +34,24 @@ ## warnings_to_ignore_by_pyver={(MAJOR, MINOR): ['Message to ignore']} # enable_deprecations_as_exceptions() -## Uncomment and customize the following lines to add/remove entries from -## the list of packages for which version numbers are displayed when running -## the tests. Making it pass for KeyError is essential in some cases when -## the package uses other astropy affiliated packages. -try: +def pytest_configure(config): + + config.option.astropy_header = True + # + # Customize the following lines to add/remove entries from + # the list of packages for which version numbers are displayed when running + # the tests. + # PYTEST_HEADER_MODULES['Astropy'] = 'astropy' PYTEST_HEADER_MODULES['PyDL'] = 'pydl' - try: - del PYTEST_HEADER_MODULES['h5py'] - except KeyError: - pass - try: - del PYTEST_HEADER_MODULES['Pandas'] - except KeyError: - pass -except (NameError, KeyError): # NameError is needed to support Astropy < 1.0 - pass - -## Uncomment the following lines to display the version number of the -## package rather than the version number of Astropy in the top line when -## running the tests. -import os - -## This is to figure out the package version, rather than -## using Astropy's -try: - from .version import version -except ImportError: - version = 'dev' + PYTEST_HEADER_MODULES.pop('Pandas', None) + PYTEST_HEADER_MODULES.pop('h5py', None) -try: + from .version import version #, astropy_helpers_version packagename = os.path.basename(os.path.dirname(__file__)) + # + # Display the version number of the package rather than the version number + # of Astropy in the top line when running the tests. + # TESTED_VERSIONS[packagename] = version -except NameError: # Needed to support Astropy <= 1.0.0 - pass + # TESTED_VERSIONS['astropy_helpers'] = astropy_helpers_version diff --git a/pydl/setup_package.py b/pydl/setup_package.py deleted file mode 100644 index a8173b2b..00000000 --- a/pydl/setup_package.py +++ /dev/null @@ -1,18 +0,0 @@ -# Licensed under a 3-clause BSD style license -# -*- coding: utf-8 -*- - - -def get_package_data(): - # Installs the testing data files. Unable to get package_data - # to deal with a directory hierarchy of files, so just explicitly list. - return { - 'pydl.tests': ['coveragerc', 't/*'], - 'pydl.photoop.tests': ['t/*'], - 'pydl.pydlspec2d.tests': ['t/*'], - 'pydl.pydlutils': ['data/cooling/*', 'data/filters/*'], - 'pydl.pydlutils.tests': ['t/*'], - } - - -# def requires_2to3(): -# return False diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..0889579c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,5 @@ +[build-system] +requires = ["setuptools", + "setuptools_scm", + "wheel"] +build-backend = 'setuptools.build_meta' diff --git a/setup.cfg b/setup.cfg index b0596b89..2ce976c7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,28 +1,19 @@ [metadata] name = pydl # version should be PEP440 compatible (http://www.python.org/dev/peps/pep-0440) -version = 1.0.0.dev +# version = 1.0.0.dev author = Benjamin Alan Weaver author_email = baweaver@lbl.gov description = Astropy affiliated package -long_description = ==== - pydl - ==== - - Python replacements for functions that are part of the IDL_ built-in library, or - part of astronomical IDL libraries. The emphasis is on reproducing results of - the astronomical library functions. Only the bare minimum of IDL_ built-in - functions are implemented to support this. - - .. _IDL: http://www.harrisgeospatial.com/SoftwareTechnology/IDL.aspx - -license = BSD +long_description = file: README.rst +license = BSD 3-Clause License url = http://github.com/weaverba137/pydl edit_on_github = False github_project = weaverba137/pydl # Note: you will also need to change this in your package's __init__.py python_requires = ">=3.5" -classifiers = Development Status :: 5 - Production/Stable +classifiers = + Development Status :: 5 - Production/Stable Environment :: Console Intended Audience :: Science/Research License :: OSI Approved :: BSD License @@ -34,22 +25,39 @@ classifiers = Development Status :: 5 - Production/Stable [options] # install_requires should be formatted as a semicolon-separated list, e.g.: # install_requires = astropy; scipy; matplotlib -install_requires = astropy; scipy; matplotlib +setup_requires = + setuptools_scm +install_requires = + astropy + scipy + matplotlib zip_safe = False use_2to3 = False +packages = find: +include_package_data = True [options.entry_points] console_scripts = - get_juldate = pydl.goddard.astro:get_juldate_main hogg_iau_name = pydl.pydlutils.misc:hogg_iau_name_main compute_templates = pydl.pydlspec2d.spec1d:template_input_main +[options.extras_require] +test = + pytest-astropy + pytest-mock + pytest-cov +docs = + sphinx-astropy # [options.package_data] # * = *.c -# packagename = data/* -# packagename.tests = coveragerc +# pydl.tests = coveragerc, t/* +# pydl.goddard.tests = t/* +# pydl.photoop.tests = t/* +# pydl.pydlspec2d.tests = t/* +# pydl.pydlutils = data/cooling/*, data/filters/* +# pydl.pydlutils.tests = t/* [build_sphinx] source-dir = docs @@ -69,7 +77,7 @@ show-response = 1 minversion = 3.0 norecursedirs = build docs/_build doctest_plus = enabled -addopts = -p no:warnings +addopts = -p no:warnings --doctest-rst [ah_bootstrap] auto_use = True diff --git a/setup.py b/setup.py index c7715256..b7a2ea34 100755 --- a/setup.py +++ b/setup.py @@ -1,33 +1,27 @@ #!/usr/bin/env python - +# -*- coding: utf-8 -*- # Licensed under a 3-clause BSD style license - see LICENSE.rst -import builtins +# Needed to import local helpers when pyproject.toml exists. +import sys +sys.path.append(".") # Ensure that astropy-helpers is available import ah_bootstrap # noqa from setuptools import setup -from setuptools.config import read_configuration - -from astropy_helpers.setup_helpers import register_commands, get_package_info -from astropy_helpers.version_helpers import generate_version_py -# Store the package name in a built-in variable so it's easy -# to get from other parts of the setup infrastructure -builtins._ASTROPY_PACKAGE_NAME_ = read_configuration('setup.cfg')['metadata']['name'] +from astropy_helpers.setup_helpers import register_commands +# from distutils.command.sdist import sdist as DistutilsSdist # Create a dictionary with setup command overrides. Note that this gets # information about the package (name and version) from the setup.cfg file. cmdclass = register_commands() - -# Freeze build information in version.py. Note that this gets information -# about the package (name and version) from the setup.cfg file. -version = generate_version_py() - -# Get configuration information from all of the various subpackages. -# See the docstring for setup_helpers.update_package_files for more -# details. -package_info = get_package_info() - -setup(version=version, cmdclass=cmdclass, **package_info) +# cmdclass = {'sdist': DistutilsSdist} +cmdclass.pop('build_sphinx', None) +cmdclass.pop('build_docs', None) +# cmdclass.pop('sdist', None) +cmdclass.pop('build_ext', None) +# print(cmdclass) + +setup(use_scm_version={"write_to": "pydl/version.py"}, cmdclass=cmdclass) diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..e6b5e480 --- /dev/null +++ b/tox.ini @@ -0,0 +1,31 @@ +[tox] +requires = + setuptools >= 30.3.0 + pip >= 19.3.1 + setuptools_scm +# isolated_build = true + +[testenv] +extras = test +changedir = + test: .tmp/{envname} + +[testenv:test] +commands = + pytest --pyargs pydl {toxinidir}/docs {posargs} + +[testenv:coverage] +requires = + pytest-cov + coverage +commands = + pytest --cov pydl + +[testenv:build_docs] +description = Invoke sphinx-build to build the HTML docs. +extras = docs +# setenv = +# HOME = {envtmpdir} +changedir = docs +commands = + sphinx-build . ./_build/html -W --keep-going -b html {posargs} From 19cdae5290954c39830f89c73452ef2b94af66c6 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 11:20:27 -0700 Subject: [PATCH 02/22] remove astropy_helpers from setup.py --- MANIFEST.in | 30 ++++++++++++------------ setup.cfg | 45 ++++++++++++------------------------ setup.py | 66 +++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 79 insertions(+), 62 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 5ad372c8..f574e556 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,7 +2,7 @@ include README.rst include LICENSE.rst # include CHANGES.rst -include ah_bootstrap.py +# include ah_bootstrap.py include pyproject.toml include setup.cfg include pydl/tests/coveragerc @@ -23,21 +23,21 @@ prune docs/api # the next few stanzas are for astropy_helpers. It's derived from the # astropy_helpers/MANIFEST.in, but requires additional includes for the actual # package directory and egg-info. - -include astropy_helpers/README.rst -include astropy_helpers/CHANGES.rst -include astropy_helpers/LICENSE.rst -recursive-include astropy_helpers/licenses * - -include astropy_helpers/ah_bootstrap.py - -recursive-include astropy_helpers/astropy_helpers *.py *.pyx *.c *.h *.rst -recursive-include astropy_helpers/astropy_helpers.egg-info * +# +# include astropy_helpers/README.rst +# include astropy_helpers/CHANGES.rst +# include astropy_helpers/LICENSE.rst +# recursive-include astropy_helpers/licenses * +# +# include astropy_helpers/ah_bootstrap.py +# +# recursive-include astropy_helpers/astropy_helpers *.py *.pyx *.c *.h *.rst +# recursive-include astropy_helpers/astropy_helpers.egg-info * # include the sphinx stuff with "*" because there are css/html/rst/etc. -recursive-include astropy_helpers/astropy_helpers/sphinx * - -prune astropy_helpers/build -prune astropy_helpers/astropy_helpers/tests +# recursive-include astropy_helpers/astropy_helpers/sphinx * +# +# prune astropy_helpers/build +# prune astropy_helpers/astropy_helpers/tests global-exclude *.pyc *.o diff --git a/setup.cfg b/setup.cfg index 2ce976c7..81a5080b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,6 +7,7 @@ author_email = baweaver@lbl.gov description = Astropy affiliated package long_description = file: README.rst license = BSD 3-Clause License +license_file = LICENSE.rst url = http://github.com/weaverba137/pydl edit_on_github = False github_project = weaverba137/pydl @@ -25,12 +26,9 @@ classifiers = [options] # install_requires should be formatted as a semicolon-separated list, e.g.: # install_requires = astropy; scipy; matplotlib -setup_requires = - setuptools_scm install_requires = astropy scipy - matplotlib zip_safe = False use_2to3 = False packages = find: @@ -43,6 +41,8 @@ console_scripts = compute_templates = pydl.pydlspec2d.spec1d:template_input_main [options.extras_require] +all = + matplotlib test = pytest-astropy pytest-mock @@ -50,37 +50,22 @@ test = docs = sphinx-astropy -# [options.package_data] +[options.package_data] # * = *.c -# pydl.tests = coveragerc, t/* -# pydl.goddard.tests = t/* -# pydl.photoop.tests = t/* -# pydl.pydlspec2d.tests = t/* -# pydl.pydlutils = data/cooling/*, data/filters/* -# pydl.pydlutils.tests = t/* - -[build_sphinx] -source-dir = docs -build-dir = docs/_build -all_files = 1 - -[build_docs] -source-dir = docs -build-dir = docs/_build -all_files = 1 - -[upload_docs] -upload-dir = docs/_build/html -show-response = 1 +pydl.tests = coveragerc, t/* +pydl.goddard.tests = t/* +pydl.photoop.tests = t/* +pydl.pydlspec2d.tests = t/* +pydl.pydlutils = data/cooling/*, data/filters/* +pydl.pydlutils.tests = t/* [tool:pytest] -minversion = 3.0 -norecursedirs = build docs/_build +testpaths = "pydl" "docs" +astropy_header = true doctest_plus = enabled -addopts = -p no:warnings --doctest-rst - -[ah_bootstrap] -auto_use = True +text_file_format = rst +addopts = --doctest-rst +# addopts = -p no:warnings --doctest-rst [flake8] select = E101,W191,W291,W292,W293,W391,E111,E112,E113,E901,E902 diff --git a/setup.py b/setup.py index b7a2ea34..dd7b461f 100755 --- a/setup.py +++ b/setup.py @@ -2,26 +2,58 @@ # -*- coding: utf-8 -*- # Licensed under a 3-clause BSD style license - see LICENSE.rst -# Needed to import local helpers when pyproject.toml exists. +import os import sys -sys.path.append(".") +# Needed to import local helpers when pyproject.toml exists. +# sys.path.append(".") +from setuptools import setup +from distutils.command.sdist import sdist as DistutilsSdist -# Ensure that astropy-helpers is available -import ah_bootstrap # noqa +TEST_HELP = """ +Note: running tests is no longer done using 'python setup.py test'. Instead +you will need to run: -from setuptools import setup + tox -e test + +If you don't already have tox installed, you can install it with: + + pip install tox + +If you only want to run part of the test suite, you can also use pytest +directly with:: + + pip install -e . + pytest + +For more information, see: + + http://docs.astropy.org/en/latest/development/testguide.html#running-tests +""" + +if 'test' in sys.argv: + print(TEST_HELP) + sys.exit(1) + +DOCS_HELP = """ +Note: building the documentation is no longer done using +'python setup.py build_docs'. Instead you will need to run: + + tox -e build_docs + +If you don't already have tox installed, you can install it with: + + pip install tox + +For more information, see: + + http://docs.astropy.org/en/latest/install.html#builddocs +""" -from astropy_helpers.setup_helpers import register_commands -# from distutils.command.sdist import sdist as DistutilsSdist +if 'build_docs' in sys.argv or 'build_sphinx' in sys.argv: + print(DOCS_HELP) + sys.exit(1) -# Create a dictionary with setup command overrides. Note that this gets -# information about the package (name and version) from the setup.cfg file. -cmdclass = register_commands() -# cmdclass = {'sdist': DistutilsSdist} -cmdclass.pop('build_sphinx', None) -cmdclass.pop('build_docs', None) -# cmdclass.pop('sdist', None) -cmdclass.pop('build_ext', None) -# print(cmdclass) +cmdclass = {'sdist': DistutilsSdist} -setup(use_scm_version={"write_to": "pydl/version.py"}, cmdclass=cmdclass) +setup(use_scm_version={"write_to": os.path.join("pydl", "version.py")}, + cmdclass=cmdclass) From 0c39dd5e33707c097f27b1ef6ff70fa6e73b8d45 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 11:50:56 -0700 Subject: [PATCH 03/22] make matplotlib optional --- pydl/_astropy_init.py | 7 +---- pydl/pydlspec2d/spec1d.py | 13 +++++---- tox.ini | 60 ++++++++++++++++++++++++++------------- 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/pydl/_astropy_init.py b/pydl/_astropy_init.py index 73a52fb3..cdeaafe3 100644 --- a/pydl/_astropy_init.py +++ b/pydl/_astropy_init.py @@ -1,6 +1,6 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst -__all__ = ['__version__', '__githash__', 'test'] +__all__ = ['__version__', 'test'] # this indicates whether or not we are in the package's setup.py try: @@ -17,11 +17,6 @@ from .version import version as __version__ except ImportError: __version__ = '' -try: - from .version import githash as __githash__ -except ImportError: - __githash__ = '' - # set up the test command def _get_test_runner(): diff --git a/pydl/pydlspec2d/spec1d.py b/pydl/pydlspec2d/spec1d.py index b72d4628..5d664473 100644 --- a/pydl/pydlspec2d/spec1d.py +++ b/pydl/pydlspec2d/spec1d.py @@ -8,11 +8,14 @@ from warnings import warn import numpy as np from numpy.linalg import solve -import matplotlib -matplotlib.use('Agg') -matplotlib.rcParams['figure.figsize'] = (16.0, 12.0) -import matplotlib.pyplot as plt -from matplotlib.font_manager import fontManager, FontProperties +try: + import matplotlib + matplotlib.use('Agg') + matplotlib.rcParams['figure.figsize'] = (16.0, 12.0) + import matplotlib.pyplot as plt + from matplotlib.font_manager import fontManager, FontProperties +except ImportError: + pass from astropy import log from astropy.io import ascii, fits from . import Pydlspec2dException, Pydlspec2dUserWarning diff --git a/tox.ini b/tox.ini index e6b5e480..1aac543c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,31 +1,53 @@ [tox] +envlist = + py{35,36,37,38}-test{,-all,-dev} + build_docs + codestyle requires = setuptools >= 30.3.0 pip >= 19.3.1 setuptools_scm -# isolated_build = true +isolated_build = true [testenv] -extras = test +passenv = + HOME + WINDIR + LC_ALL + LC_CTYPE +extras = + test: test + build_docs: docs + all: all changedir = test: .tmp/{envname} - -[testenv:test] + build_docs: docs +description = + test: Run tests with pytest. + build_docs: Invoke sphinx-build to build the HTML docs. + all: Run tests with all optional dependencies. + dev: Run tests with numpy and astropy dev versions. commands = - pytest --pyargs pydl {toxinidir}/docs {posargs} + test: pytest --pyargs pydl {toxinidir}/docs {posargs} + build_docs: sphinx-build . ./_build/html -W --keep-going -b html {posargs} +deps = + astropylts: astropy==4.0 + astropy2: astropy==2.0.14 + numpy116: numpy==1.16.* + numpy117: numpy==1.17.* + numpy118: numpy==1.18.* + dev: git+https://github.com/numpy/numpy.git#egg=numpy + dev: git+https://github.com/astropy/astropy.git#egg=astropy -[testenv:coverage] -requires = - pytest-cov - coverage -commands = - pytest --cov pydl +; [testenv:coverage] +; requires = +; pytest-cov +; coverage +; commands = +; pytest --cov pydl -[testenv:build_docs] -description = Invoke sphinx-build to build the HTML docs. -extras = docs -# setenv = -# HOME = {envtmpdir} -changedir = docs -commands = - sphinx-build . ./_build/html -W --keep-going -b html {posargs} +[testenv:codestyle] +skip_install = true +description = Check package code style. +deps = flake8 +commands = flake8 pydl --count --show-source --statistics {posargs} From d68a1274eae0f9e6ec6128363264a5c31d7c68bb Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 12:05:17 -0700 Subject: [PATCH 04/22] update travis --- .travis.yml | 97 +++++++++++++++++++++++++++---------------------- readthedocs.yml | 15 ++++++-- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4e7639f3..690d479f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,23 +39,25 @@ env: # The following versions are the 'default' for tests, unless # overridden underneath. They are defined here in order to save having # to repeat them for all configurations. - - PYTHON_VERSION=3.7 - - NUMPY_VERSION=stable - - ASTROPY_VERSION=stable - - MAIN_CMD='python setup.py' - - SETUP_CMD='test' - - EVENT_TYPE='pull_request push' - + # - PYTHON_VERSION=3.7 + # - NUMPY_VERSION=stable + # - ASTROPY_VERSION=stable + # - MAIN_CMD='python setup.py' + # - SETUP_CMD='test' + # - EVENT_TYPE='pull_request push' + - TOXENV='' + - TOXARGS='' + - TOXPOSARGS='' # For this package-template, we include examples of Cython modules, # so Cython is required for testing. If your package does not include # Cython code, you can set CONDA_DEPENDENCIES='' - - CONDA_DEPENDENCIES='tox setuptools_scm scipy matplotlib pytest-mock' - - CONDA_DEPENDENCIES_DOC='tox setuptools_scm scipy matplotlib sphinx-astropy' + # - CONDA_DEPENDENCIES='tox setuptools_scm scipy matplotlib pytest-mock' + # - CONDA_DEPENDENCIES_DOC='tox setuptools_scm scipy matplotlib sphinx-astropy' # List other runtime dependencies for the package that are available as # pip packages here. - - PIP_DEPENDENCIES='' + # - PIP_DEPENDENCIES='' # Conda packages for affiliated packages are hosted in channel # "astropy" while builds for astropy LTS with recent numpy versions @@ -71,7 +73,7 @@ env: # If you want to ignore certain flake8 errors, you can list them # in FLAKE8_OPT, for example: # - FLAKE8_OPT='--ignore=E501' - - FLAKE8_OPT='' + # - FLAKE8_OPT='' matrix: @@ -79,67 +81,70 @@ matrix: fast_finish: true include: + - os: linux + stage: Initial tests + python: 3.8 + env: TOXENV='test' + # Make sure that egg_info works without dependencies - - stage: Initial tests - env: PYTHON_VERSION=3.7 SETUP_CMD='egg_info' + # - stage: Initial tests + # env: PYTHON_VERSION=3.7 SETUP_CMD='egg_info' # Try MacOS X, usually enough only to run from cron as hardly there are # issues that are not picked up by a linux worker - - os: osx - stage: Cron tests - env: SETUP_CMD='test' EVENT_TYPE='cron' + # - os: osx + # stage: Cron tests + # env: SETUP_CMD='test' EVENT_TYPE='cron' # Do a coverage test. - - os: linux - stage: Initial tests - env: SETUP_CMD='test --coverage' + # - os: linux + # stage: Initial tests + # env: SETUP_CMD='test --coverage' # Check for sphinx doc build warnings - we do this first because it # may run for a long time - os: linux - env: MAIN_CMD='tox -e' - SETUP_CMD='build_docs' - CONDA_DEPENDENCIES=$CONDA_DEPENDENCIES_DOC - # env: MAIN_CMD='sphinx-build' - # SETUP_CMD='docs docs/_build/html -W --keep-going -b html' - # CONDA_DEPENDENCIES=$CONDA_DEPENDENCIES_DOC + python: 3.7 + env: TOXENV='build_docs' # Now try Astropy dev with the latest Python and LTS with and 3.x. - - os: linux - env: ASTROPY_VERSION=development - EVENT_TYPE='pull_request push cron' - - os: linux - env: PYTHON_VERSION=3.6 ASTROPY_VERSION=2.0.16 NUMPY_VERSION=1.14 PYTEST_VERSION='<3.7' + # - os: linux + # env: ASTROPY_VERSION=development + # EVENT_TYPE='pull_request push cron' + # - os: linux + # env: PYTHON_VERSION=3.6 ASTROPY_VERSION=2.0.16 NUMPY_VERSION=1.14 PYTEST_VERSION='<3.7' # Add a job that runs from cron only and tests against astropy dev and # numpy dev to give a change for early discovery of issues and feedback # for both developer teams. - - os: linux - stage: Cron tests - env: ASTROPY_VERSION=development NUMPY_VERSION=development - EVENT_TYPE='cron' + # - os: linux + # stage: Cron tests + # env: ASTROPY_VERSION=development NUMPY_VERSION=development + # EVENT_TYPE='cron' # Try all python versions and Numpy versions. Since we can assume that # the Numpy developers have taken care of testing Numpy with different # versions of Python, we can vary Python and Numpy versions at the same # time. - - os: linux - env: PYTHON_VERSION=3.6 NUMPY_VERSION=1.16 - - os: linux - env: NUMPY_VERSION=1.16 + # - os: linux + # env: PYTHON_VERSION=3.6 NUMPY_VERSION=1.16 + # - os: linux + # env: NUMPY_VERSION=1.16 # Do a PEP8 test with flake8 - os: linux stage: Initial tests - env: MAIN_CMD='flake8 pydl --count --show-source --statistics $FLAKE8_OPT' SETUP_CMD='' + python: 3.7 + env: TOXENV='codestyle' allow_failures: # Do a PEP8 test with flake8 # (do allow to fail unless your code completely compliant) - os: linux stage: Initial tests - env: MAIN_CMD='flake8 pydl --count --show-source --statistics $FLAKE8_OPT' SETUP_CMD='' + python: 3.7 + env: TOXENV='codestyle' install: @@ -154,8 +159,12 @@ install: # in how to install a package, in which case you can have additional # commands in the install: section below. - - git clone --depth 1 git://github.com/astropy/ci-helpers.git - - source ci-helpers/travis/setup_conda.sh + - if [[ ${TRAVIS_OS_NAME} == 'osx' || ${TRAVIS_OS_NAME} == 'windows' ]]; then + git clone --depth 1 git://github.com/astropy/ci-helpers.git; + source ci-helpers/travis/setup_conda.sh; + fi + + - pip install tox --upgrade # As described above, using ci-helpers, you should be able to set up an # environment with dependencies installed using conda and pip, but in some @@ -167,9 +176,9 @@ install: # other dependencies. script: - - $MAIN_CMD $SETUP_CMD + - tox -e ${TOXENV} ${TOXARGS} -- ${TOXPOSARGS} after_success: # If coveralls.io is set up for this package, uncomment the line below. # The coveragerc file may be customized as needed for your package. - - if [[ $SETUP_CMD == *coverage* ]]; then coveralls --rcfile='pydl/tests/coveragerc'; fi + - if [[ ${TOXENV} == 'coverage' ]]; then coveralls --rcfile='pydl/tests/coveragerc'; fi diff --git a/readthedocs.yml b/readthedocs.yml index 9092548d..fd323c14 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -1,7 +1,14 @@ # See https://docs.readthedocs.io/en/latest/yaml-config.html -conda: - file: .rtd-environment.yml +version: 2 + +build: + image: latest python: - version: 3 - setup_py_install: true + version: 3.7 + install: + - method: pip + path: . + extra_requirements: + - docs + - all From e7f5e37f82ca977ab576c4f7e0032a79b98a2560 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 12:12:52 -0700 Subject: [PATCH 05/22] update .gitignore --- .gitignore | 1 + readthedocs.yml => .readthedocs.yml | 0 .rtd-environment.yml | 16 ---------------- 3 files changed, 1 insertion(+), 16 deletions(-) rename readthedocs.yml => .readthedocs.yml (100%) delete mode 100644 .rtd-environment.yml diff --git a/.gitignore b/.gitignore index fe0f57b1..2f628df9 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ sdist develop-eggs .installed.cfg distribute-*.tar.gz +pip-wheel-metadata # Other .cache diff --git a/readthedocs.yml b/.readthedocs.yml similarity index 100% rename from readthedocs.yml rename to .readthedocs.yml diff --git a/.rtd-environment.yml b/.rtd-environment.yml deleted file mode 100644 index 38a6f215..00000000 --- a/.rtd-environment.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: pydl - -channels: - - astropy - -dependencies: - - python>=3.6 - - astropy - - Cython - - matplotlib - - numpy - - scipy -# - sphinx-astropy - - pip: - - sphinx-astropy - - sphinx-gallery From aae3b18853a0ea5e2f855499d851a3c8bfccd8bb Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 13:28:17 -0700 Subject: [PATCH 06/22] change travis language --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 690d479f..c20508a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ # We set the language to c because python isn't supported on the MacOS X nodes # on Travis. However, the language ends up being irrelevant anyway, since we # install Python ourselves using conda. -language: c +language: python os: - linux From 118836c6267dd723b8daf6017ea89b722de17d47 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 13:44:51 -0700 Subject: [PATCH 07/22] remove bootstrap file --- ah_bootstrap.py | 1010 ----------------------------------------------- 1 file changed, 1010 deletions(-) delete mode 100644 ah_bootstrap.py diff --git a/ah_bootstrap.py b/ah_bootstrap.py deleted file mode 100644 index 512a05a1..00000000 --- a/ah_bootstrap.py +++ /dev/null @@ -1,1010 +0,0 @@ -""" -This bootstrap module contains code for ensuring that the astropy_helpers -package will be importable by the time the setup.py script runs. It also -includes some workarounds to ensure that a recent-enough version of setuptools -is being used for the installation. - -This module should be the first thing imported in the setup.py of distributions -that make use of the utilities in astropy_helpers. If the distribution ships -with its own copy of astropy_helpers, this module will first attempt to import -from the shipped copy. However, it will also check PyPI to see if there are -any bug-fix releases on top of the current version that may be useful to get -past platform-specific bugs that have been fixed. When running setup.py, use -the ``--offline`` command-line option to disable the auto-upgrade checks. - -When this module is imported or otherwise executed it automatically calls a -main function that attempts to read the project's setup.cfg file, which it -checks for a configuration section called ``[ah_bootstrap]`` the presences of -that section, and options therein, determine the next step taken: If it -contains an option called ``auto_use`` with a value of ``True``, it will -automatically call the main function of this module called -`use_astropy_helpers` (see that function's docstring for full details). -Otherwise no further action is taken and by default the system-installed version -of astropy-helpers will be used (however, ``ah_bootstrap.use_astropy_helpers`` -may be called manually from within the setup.py script). - -This behavior can also be controlled using the ``--auto-use`` and -``--no-auto-use`` command-line flags. For clarity, an alias for -``--no-auto-use`` is ``--use-system-astropy-helpers``, and we recommend using -the latter if needed. - -Additional options in the ``[ah_boostrap]`` section of setup.cfg have the same -names as the arguments to `use_astropy_helpers`, and can be used to configure -the bootstrap script when ``auto_use = True``. - -See https://github.com/astropy/astropy-helpers for more details, and for the -latest version of this module. -""" - -import contextlib -import errno -import io -import locale -import os -import re -import subprocess as sp -import sys - -from distutils import log -from distutils.debug import DEBUG - -from configparser import ConfigParser, RawConfigParser - -import pkg_resources - -from setuptools import Distribution -from setuptools.package_index import PackageIndex - -# This is the minimum Python version required for astropy-helpers -__minimum_python_version__ = (3, 5) - -# TODO: Maybe enable checking for a specific version of astropy_helpers? -DIST_NAME = 'astropy-helpers' -PACKAGE_NAME = 'astropy_helpers' -UPPER_VERSION_EXCLUSIVE = None - -# Defaults for other options -DOWNLOAD_IF_NEEDED = True -INDEX_URL = 'https://pypi.python.org/simple' -USE_GIT = True -OFFLINE = False -AUTO_UPGRADE = True - -# A list of all the configuration options and their required types -CFG_OPTIONS = [ - ('auto_use', bool), ('path', str), ('download_if_needed', bool), - ('index_url', str), ('use_git', bool), ('offline', bool), - ('auto_upgrade', bool) -] - -# Start off by parsing the setup.cfg file - -SETUP_CFG = ConfigParser() - -if os.path.exists('setup.cfg'): - - try: - SETUP_CFG.read('setup.cfg') - except Exception as e: - if DEBUG: - raise - - log.error( - "Error reading setup.cfg: {0!r}\n{1} will not be " - "automatically bootstrapped and package installation may fail." - "\n{2}".format(e, PACKAGE_NAME, _err_help_msg)) - -# We used package_name in the package template for a while instead of name -if SETUP_CFG.has_option('metadata', 'name'): - parent_package = SETUP_CFG.get('metadata', 'name') -elif SETUP_CFG.has_option('metadata', 'package_name'): - parent_package = SETUP_CFG.get('metadata', 'package_name') -else: - parent_package = None - -if SETUP_CFG.has_option('options', 'python_requires'): - - python_requires = SETUP_CFG.get('options', 'python_requires') - - # The python_requires key has a syntax that can be parsed by SpecifierSet - # in the packaging package. However, we don't want to have to depend on that - # package, so instead we can use setuptools (which bundles packaging). We - # have to add 'python' to parse it with Requirement. - - from pkg_resources import Requirement - req = Requirement.parse('python' + python_requires) - - # We want the Python version as a string, which we can get from the platform module - import platform - # strip off trailing '+' incase this is a dev install of python - python_version = platform.python_version().strip('+') - # allow pre-releases to count as 'new enough' - if not req.specifier.contains(python_version, True): - if parent_package is None: - message = "ERROR: Python {} is required by this package\n".format(req.specifier) - else: - message = "ERROR: Python {} is required by {}\n".format(req.specifier, parent_package) - sys.stderr.write(message) - sys.exit(1) - -if sys.version_info < __minimum_python_version__: - - if parent_package is None: - message = "ERROR: Python {} or later is required by astropy-helpers\n".format( - __minimum_python_version__) - else: - message = "ERROR: Python {} or later is required by astropy-helpers for {}\n".format( - __minimum_python_version__, parent_package) - - sys.stderr.write(message) - sys.exit(1) - -_str_types = (str, bytes) - - -# What follows are several import statements meant to deal with install-time -# issues with either missing or misbehaving pacakges (including making sure -# setuptools itself is installed): - -# Check that setuptools 30.3 or later is present -from distutils.version import LooseVersion - -try: - import setuptools - assert LooseVersion(setuptools.__version__) >= LooseVersion('30.3') -except (ImportError, AssertionError): - sys.stderr.write("ERROR: setuptools 30.3 or later is required by astropy-helpers\n") - sys.exit(1) - -# typing as a dependency for 1.6.1+ Sphinx causes issues when imported after -# initializing submodule with ah_boostrap.py -# See discussion and references in -# https://github.com/astropy/astropy-helpers/issues/302 - -try: - import typing # noqa -except ImportError: - pass - - -# Note: The following import is required as a workaround to -# https://github.com/astropy/astropy-helpers/issues/89; if we don't import this -# module now, it will get cleaned up after `run_setup` is called, but that will -# later cause the TemporaryDirectory class defined in it to stop working when -# used later on by setuptools -try: - import setuptools.py31compat # noqa -except ImportError: - pass - - -# matplotlib can cause problems if it is imported from within a call of -# run_setup(), because in some circumstances it will try to write to the user's -# home directory, resulting in a SandboxViolation. See -# https://github.com/matplotlib/matplotlib/pull/4165 -# Making sure matplotlib, if it is available, is imported early in the setup -# process can mitigate this (note importing matplotlib.pyplot has the same -# issue) -try: - import matplotlib - matplotlib.use('Agg') - import matplotlib.pyplot -except: - # Ignore if this fails for *any* reason* - pass - - -# End compatibility imports... - - -class _Bootstrapper(object): - """ - Bootstrapper implementation. See ``use_astropy_helpers`` for parameter - documentation. - """ - - def __init__(self, path=None, index_url=None, use_git=None, offline=None, - download_if_needed=None, auto_upgrade=None): - - if path is None: - path = PACKAGE_NAME - - if not (isinstance(path, _str_types) or path is False): - raise TypeError('path must be a string or False') - - if not isinstance(path, str): - fs_encoding = sys.getfilesystemencoding() - path = path.decode(fs_encoding) # path to unicode - - self.path = path - - # Set other option attributes, using defaults where necessary - self.index_url = index_url if index_url is not None else INDEX_URL - self.offline = offline if offline is not None else OFFLINE - - # If offline=True, override download and auto-upgrade - if self.offline: - download_if_needed = False - auto_upgrade = False - - self.download = (download_if_needed - if download_if_needed is not None - else DOWNLOAD_IF_NEEDED) - self.auto_upgrade = (auto_upgrade - if auto_upgrade is not None else AUTO_UPGRADE) - - # If this is a release then the .git directory will not exist so we - # should not use git. - git_dir_exists = os.path.exists(os.path.join(os.path.dirname(__file__), '.git')) - if use_git is None and not git_dir_exists: - use_git = False - - self.use_git = use_git if use_git is not None else USE_GIT - # Declared as False by default--later we check if astropy-helpers can be - # upgraded from PyPI, but only if not using a source distribution (as in - # the case of import from a git submodule) - self.is_submodule = False - - @classmethod - def main(cls, argv=None): - if argv is None: - argv = sys.argv - - config = cls.parse_config() - config.update(cls.parse_command_line(argv)) - - auto_use = config.pop('auto_use', False) - bootstrapper = cls(**config) - - if auto_use: - # Run the bootstrapper, otherwise the setup.py is using the old - # use_astropy_helpers() interface, in which case it will run the - # bootstrapper manually after reconfiguring it. - bootstrapper.run() - - return bootstrapper - - @classmethod - def parse_config(cls): - - if not SETUP_CFG.has_section('ah_bootstrap'): - return {} - - config = {} - - for option, type_ in CFG_OPTIONS: - if not SETUP_CFG.has_option('ah_bootstrap', option): - continue - - if type_ is bool: - value = SETUP_CFG.getboolean('ah_bootstrap', option) - else: - value = SETUP_CFG.get('ah_bootstrap', option) - - config[option] = value - - return config - - @classmethod - def parse_command_line(cls, argv=None): - if argv is None: - argv = sys.argv - - config = {} - - # For now we just pop recognized ah_bootstrap options out of the - # arg list. This is imperfect; in the unlikely case that a setup.py - # custom command or even custom Distribution class defines an argument - # of the same name then we will break that. However there's a catch22 - # here that we can't just do full argument parsing right here, because - # we don't yet know *how* to parse all possible command-line arguments. - if '--no-git' in argv: - config['use_git'] = False - argv.remove('--no-git') - - if '--offline' in argv: - config['offline'] = True - argv.remove('--offline') - - if '--auto-use' in argv: - config['auto_use'] = True - argv.remove('--auto-use') - - if '--no-auto-use' in argv: - config['auto_use'] = False - argv.remove('--no-auto-use') - - if '--use-system-astropy-helpers' in argv: - config['auto_use'] = False - argv.remove('--use-system-astropy-helpers') - - return config - - def run(self): - strategies = ['local_directory', 'local_file', 'index'] - dist = None - - # First, remove any previously imported versions of astropy_helpers; - # this is necessary for nested installs where one package's installer - # is installing another package via setuptools.sandbox.run_setup, as in - # the case of setup_requires - for key in list(sys.modules): - try: - if key == PACKAGE_NAME or key.startswith(PACKAGE_NAME + '.'): - del sys.modules[key] - except AttributeError: - # Sometimes mysterious non-string things can turn up in - # sys.modules - continue - - # Check to see if the path is a submodule - self.is_submodule = self._check_submodule() - - for strategy in strategies: - method = getattr(self, 'get_{0}_dist'.format(strategy)) - dist = method() - if dist is not None: - break - else: - raise _AHBootstrapSystemExit( - "No source found for the {0!r} package; {0} must be " - "available and importable as a prerequisite to building " - "or installing this package.".format(PACKAGE_NAME)) - - # This is a bit hacky, but if astropy_helpers was loaded from a - # directory/submodule its Distribution object gets a "precedence" of - # "DEVELOP_DIST". However, in other cases it gets a precedence of - # "EGG_DIST". However, when activing the distribution it will only be - # placed early on sys.path if it is treated as an EGG_DIST, so always - # do that - dist = dist.clone(precedence=pkg_resources.EGG_DIST) - - # Otherwise we found a version of astropy-helpers, so we're done - # Just active the found distribution on sys.path--if we did a - # download this usually happens automatically but it doesn't hurt to - # do it again - # Note: Adding the dist to the global working set also activates it - # (makes it importable on sys.path) by default. - - try: - pkg_resources.working_set.add(dist, replace=True) - except TypeError: - # Some (much) older versions of setuptools do not have the - # replace=True option here. These versions are old enough that all - # bets may be off anyways, but it's easy enough to work around just - # in case... - if dist.key in pkg_resources.working_set.by_key: - del pkg_resources.working_set.by_key[dist.key] - pkg_resources.working_set.add(dist) - - @property - def config(self): - """ - A `dict` containing the options this `_Bootstrapper` was configured - with. - """ - - return dict((optname, getattr(self, optname)) - for optname, _ in CFG_OPTIONS if hasattr(self, optname)) - - def get_local_directory_dist(self): - """ - Handle importing a vendored package from a subdirectory of the source - distribution. - """ - - if not os.path.isdir(self.path): - return - - log.info('Attempting to import astropy_helpers from {0} {1!r}'.format( - 'submodule' if self.is_submodule else 'directory', - self.path)) - - dist = self._directory_import() - - if dist is None: - log.warn( - 'The requested path {0!r} for importing {1} does not ' - 'exist, or does not contain a copy of the {1} ' - 'package.'.format(self.path, PACKAGE_NAME)) - elif self.auto_upgrade and not self.is_submodule: - # A version of astropy-helpers was found on the available path, but - # check to see if a bugfix release is available on PyPI - upgrade = self._do_upgrade(dist) - if upgrade is not None: - dist = upgrade - - return dist - - def get_local_file_dist(self): - """ - Handle importing from a source archive; this also uses setup_requires - but points easy_install directly to the source archive. - """ - - if not os.path.isfile(self.path): - return - - log.info('Attempting to unpack and import astropy_helpers from ' - '{0!r}'.format(self.path)) - - try: - dist = self._do_download(find_links=[self.path]) - except Exception as e: - if DEBUG: - raise - - log.warn( - 'Failed to import {0} from the specified archive {1!r}: ' - '{2}'.format(PACKAGE_NAME, self.path, str(e))) - dist = None - - if dist is not None and self.auto_upgrade: - # A version of astropy-helpers was found on the available path, but - # check to see if a bugfix release is available on PyPI - upgrade = self._do_upgrade(dist) - if upgrade is not None: - dist = upgrade - - return dist - - def get_index_dist(self): - if not self.download: - log.warn('Downloading {0!r} disabled.'.format(DIST_NAME)) - return None - - log.warn( - "Downloading {0!r}; run setup.py with the --offline option to " - "force offline installation.".format(DIST_NAME)) - - try: - dist = self._do_download() - except Exception as e: - if DEBUG: - raise - log.warn( - 'Failed to download and/or install {0!r} from {1!r}:\n' - '{2}'.format(DIST_NAME, self.index_url, str(e))) - dist = None - - # No need to run auto-upgrade here since we've already presumably - # gotten the most up-to-date version from the package index - return dist - - def _directory_import(self): - """ - Import astropy_helpers from the given path, which will be added to - sys.path. - - Must return True if the import succeeded, and False otherwise. - """ - - # Return True on success, False on failure but download is allowed, and - # otherwise raise SystemExit - path = os.path.abspath(self.path) - - # Use an empty WorkingSet rather than the man - # pkg_resources.working_set, since on older versions of setuptools this - # will invoke a VersionConflict when trying to install an upgrade - ws = pkg_resources.WorkingSet([]) - ws.add_entry(path) - dist = ws.by_key.get(DIST_NAME) - - if dist is None: - # We didn't find an egg-info/dist-info in the given path, but if a - # setup.py exists we can generate it - setup_py = os.path.join(path, 'setup.py') - if os.path.isfile(setup_py): - # We use subprocess instead of run_setup from setuptools to - # avoid segmentation faults - see the following for more details: - # https://github.com/cython/cython/issues/2104 - sp.check_output([sys.executable, 'setup.py', 'egg_info'], cwd=path) - - for dist in pkg_resources.find_distributions(path, True): - # There should be only one... - return dist - - return dist - - def _do_download(self, version='', find_links=None): - if find_links: - allow_hosts = '' - index_url = None - else: - allow_hosts = None - index_url = self.index_url - - # Annoyingly, setuptools will not handle other arguments to - # Distribution (such as options) before handling setup_requires, so it - # is not straightforward to programmatically augment the arguments which - # are passed to easy_install - class _Distribution(Distribution): - def get_option_dict(self, command_name): - opts = Distribution.get_option_dict(self, command_name) - if command_name == 'easy_install': - if find_links is not None: - opts['find_links'] = ('setup script', find_links) - if index_url is not None: - opts['index_url'] = ('setup script', index_url) - if allow_hosts is not None: - opts['allow_hosts'] = ('setup script', allow_hosts) - return opts - - if version: - req = '{0}=={1}'.format(DIST_NAME, version) - else: - if UPPER_VERSION_EXCLUSIVE is None: - req = DIST_NAME - else: - req = '{0}<{1}'.format(DIST_NAME, UPPER_VERSION_EXCLUSIVE) - - attrs = {'setup_requires': [req]} - - # NOTE: we need to parse the config file (e.g. setup.cfg) to make sure - # it honours the options set in the [easy_install] section, and we need - # to explicitly fetch the requirement eggs as setup_requires does not - # get honored in recent versions of setuptools: - # https://github.com/pypa/setuptools/issues/1273 - - try: - - context = _verbose if DEBUG else _silence - with context(): - dist = _Distribution(attrs=attrs) - try: - dist.parse_config_files(ignore_option_errors=True) - dist.fetch_build_eggs(req) - except TypeError: - # On older versions of setuptools, ignore_option_errors - # doesn't exist, and the above two lines are not needed - # so we can just continue - pass - - # If the setup_requires succeeded it will have added the new dist to - # the main working_set - return pkg_resources.working_set.by_key.get(DIST_NAME) - except Exception as e: - if DEBUG: - raise - - msg = 'Error retrieving {0} from {1}:\n{2}' - if find_links: - source = find_links[0] - elif index_url != INDEX_URL: - source = index_url - else: - source = 'PyPI' - - raise Exception(msg.format(DIST_NAME, source, repr(e))) - - def _do_upgrade(self, dist): - # Build up a requirement for a higher bugfix release but a lower minor - # release (so API compatibility is guaranteed) - next_version = _next_version(dist.parsed_version) - - req = pkg_resources.Requirement.parse( - '{0}>{1},<{2}'.format(DIST_NAME, dist.version, next_version)) - - package_index = PackageIndex(index_url=self.index_url) - - upgrade = package_index.obtain(req) - - if upgrade is not None: - return self._do_download(version=upgrade.version) - - def _check_submodule(self): - """ - Check if the given path is a git submodule. - - See the docstrings for ``_check_submodule_using_git`` and - ``_check_submodule_no_git`` for further details. - """ - - if (self.path is None or - (os.path.exists(self.path) and not os.path.isdir(self.path))): - return False - - if self.use_git: - return self._check_submodule_using_git() - else: - return self._check_submodule_no_git() - - def _check_submodule_using_git(self): - """ - Check if the given path is a git submodule. If so, attempt to initialize - and/or update the submodule if needed. - - This function makes calls to the ``git`` command in subprocesses. The - ``_check_submodule_no_git`` option uses pure Python to check if the given - path looks like a git submodule, but it cannot perform updates. - """ - - cmd = ['git', 'submodule', 'status', '--', self.path] - - try: - log.info('Running `{0}`; use the --no-git option to disable git ' - 'commands'.format(' '.join(cmd))) - returncode, stdout, stderr = run_cmd(cmd) - except _CommandNotFound: - # The git command simply wasn't found; this is most likely the - # case on user systems that don't have git and are simply - # trying to install the package from PyPI or a source - # distribution. Silently ignore this case and simply don't try - # to use submodules - return False - - stderr = stderr.strip() - - if returncode != 0 and stderr: - # Unfortunately the return code alone cannot be relied on, as - # earlier versions of git returned 0 even if the requested submodule - # does not exist - - # This is a warning that occurs in perl (from running git submodule) - # which only occurs with a malformatted locale setting which can - # happen sometimes on OSX. See again - # https://github.com/astropy/astropy/issues/2749 - perl_warning = ('perl: warning: Falling back to the standard locale ' - '("C").') - if not stderr.strip().endswith(perl_warning): - # Some other unknown error condition occurred - log.warn('git submodule command failed ' - 'unexpectedly:\n{0}'.format(stderr)) - return False - - # Output of `git submodule status` is as follows: - # - # 1: Status indicator: '-' for submodule is uninitialized, '+' if - # submodule is initialized but is not at the commit currently indicated - # in .gitmodules (and thus needs to be updated), or 'U' if the - # submodule is in an unstable state (i.e. has merge conflicts) - # - # 2. SHA-1 hash of the current commit of the submodule (we don't really - # need this information but it's useful for checking that the output is - # correct) - # - # 3. The output of `git describe` for the submodule's current commit - # hash (this includes for example what branches the commit is on) but - # only if the submodule is initialized. We ignore this information for - # now - _git_submodule_status_re = re.compile( - r'^(?P[+-U ])(?P[0-9a-f]{40}) ' - r'(?P\S+)( .*)?$') - - # The stdout should only contain one line--the status of the - # requested submodule - m = _git_submodule_status_re.match(stdout) - if m: - # Yes, the path *is* a git submodule - self._update_submodule(m.group('submodule'), m.group('status')) - return True - else: - log.warn( - 'Unexpected output from `git submodule status`:\n{0}\n' - 'Will attempt import from {1!r} regardless.'.format( - stdout, self.path)) - return False - - def _check_submodule_no_git(self): - """ - Like ``_check_submodule_using_git``, but simply parses the .gitmodules file - to determine if the supplied path is a git submodule, and does not exec any - subprocesses. - - This can only determine if a path is a submodule--it does not perform - updates, etc. This function may need to be updated if the format of the - .gitmodules file is changed between git versions. - """ - - gitmodules_path = os.path.abspath('.gitmodules') - - if not os.path.isfile(gitmodules_path): - return False - - # This is a minimal reader for gitconfig-style files. It handles a few of - # the quirks that make gitconfig files incompatible with ConfigParser-style - # files, but does not support the full gitconfig syntax (just enough - # needed to read a .gitmodules file). - gitmodules_fileobj = io.StringIO() - - # Must use io.open for cross-Python-compatible behavior wrt unicode - with io.open(gitmodules_path) as f: - for line in f: - # gitconfig files are more flexible with leading whitespace; just - # go ahead and remove it - line = line.lstrip() - - # comments can start with either # or ; - if line and line[0] in (':', ';'): - continue - - gitmodules_fileobj.write(line) - - gitmodules_fileobj.seek(0) - - cfg = RawConfigParser() - - try: - cfg.readfp(gitmodules_fileobj) - except Exception as exc: - log.warn('Malformatted .gitmodules file: {0}\n' - '{1} cannot be assumed to be a git submodule.'.format( - exc, self.path)) - return False - - for section in cfg.sections(): - if not cfg.has_option(section, 'path'): - continue - - submodule_path = cfg.get(section, 'path').rstrip(os.sep) - - if submodule_path == self.path.rstrip(os.sep): - return True - - return False - - def _update_submodule(self, submodule, status): - if status == ' ': - # The submodule is up to date; no action necessary - return - elif status == '-': - if self.offline: - raise _AHBootstrapSystemExit( - "Cannot initialize the {0} submodule in --offline mode; " - "this requires being able to clone the submodule from an " - "online repository.".format(submodule)) - cmd = ['update', '--init'] - action = 'Initializing' - elif status == '+': - cmd = ['update'] - action = 'Updating' - if self.offline: - cmd.append('--no-fetch') - elif status == 'U': - raise _AHBootstrapSystemExit( - 'Error: Submodule {0} contains unresolved merge conflicts. ' - 'Please complete or abandon any changes in the submodule so that ' - 'it is in a usable state, then try again.'.format(submodule)) - else: - log.warn('Unknown status {0!r} for git submodule {1!r}. Will ' - 'attempt to use the submodule as-is, but try to ensure ' - 'that the submodule is in a clean state and contains no ' - 'conflicts or errors.\n{2}'.format(status, submodule, - _err_help_msg)) - return - - err_msg = None - cmd = ['git', 'submodule'] + cmd + ['--', submodule] - log.warn('{0} {1} submodule with: `{2}`'.format( - action, submodule, ' '.join(cmd))) - - try: - log.info('Running `{0}`; use the --no-git option to disable git ' - 'commands'.format(' '.join(cmd))) - returncode, stdout, stderr = run_cmd(cmd) - except OSError as e: - err_msg = str(e) - else: - if returncode != 0: - err_msg = stderr - - if err_msg is not None: - log.warn('An unexpected error occurred updating the git submodule ' - '{0!r}:\n{1}\n{2}'.format(submodule, err_msg, - _err_help_msg)) - -class _CommandNotFound(OSError): - """ - An exception raised when a command run with run_cmd is not found on the - system. - """ - - -def run_cmd(cmd): - """ - Run a command in a subprocess, given as a list of command-line - arguments. - - Returns a ``(returncode, stdout, stderr)`` tuple. - """ - - try: - p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) - # XXX: May block if either stdout or stderr fill their buffers; - # however for the commands this is currently used for that is - # unlikely (they should have very brief output) - stdout, stderr = p.communicate() - except OSError as e: - if DEBUG: - raise - - if e.errno == errno.ENOENT: - msg = 'Command not found: `{0}`'.format(' '.join(cmd)) - raise _CommandNotFound(msg, cmd) - else: - raise _AHBootstrapSystemExit( - 'An unexpected error occurred when running the ' - '`{0}` command:\n{1}'.format(' '.join(cmd), str(e))) - - - # Can fail of the default locale is not configured properly. See - # https://github.com/astropy/astropy/issues/2749. For the purposes under - # consideration 'latin1' is an acceptable fallback. - try: - stdio_encoding = locale.getdefaultlocale()[1] or 'latin1' - except ValueError: - # Due to an OSX oddity locale.getdefaultlocale() can also crash - # depending on the user's locale/language settings. See: - # http://bugs.python.org/issue18378 - stdio_encoding = 'latin1' - - # Unlikely to fail at this point but even then let's be flexible - if not isinstance(stdout, str): - stdout = stdout.decode(stdio_encoding, 'replace') - if not isinstance(stderr, str): - stderr = stderr.decode(stdio_encoding, 'replace') - - return (p.returncode, stdout, stderr) - - -def _next_version(version): - """ - Given a parsed version from pkg_resources.parse_version, returns a new - version string with the next minor version. - - Examples - ======== - >>> _next_version(pkg_resources.parse_version('1.2.3')) - '1.3.0' - """ - - if hasattr(version, 'base_version'): - # New version parsing from setuptools >= 8.0 - if version.base_version: - parts = version.base_version.split('.') - else: - parts = [] - else: - parts = [] - for part in version: - if part.startswith('*'): - break - parts.append(part) - - parts = [int(p) for p in parts] - - if len(parts) < 3: - parts += [0] * (3 - len(parts)) - - major, minor, micro = parts[:3] - - return '{0}.{1}.{2}'.format(major, minor + 1, 0) - - -class _DummyFile(object): - """A noop writeable object.""" - - errors = '' # Required for Python 3.x - encoding = 'utf-8' - - def write(self, s): - pass - - def flush(self): - pass - - -@contextlib.contextmanager -def _verbose(): - yield - -@contextlib.contextmanager -def _silence(): - """A context manager that silences sys.stdout and sys.stderr.""" - - old_stdout = sys.stdout - old_stderr = sys.stderr - sys.stdout = _DummyFile() - sys.stderr = _DummyFile() - exception_occurred = False - try: - yield - except: - exception_occurred = True - # Go ahead and clean up so that exception handling can work normally - sys.stdout = old_stdout - sys.stderr = old_stderr - raise - - if not exception_occurred: - sys.stdout = old_stdout - sys.stderr = old_stderr - - -_err_help_msg = """ -If the problem persists consider installing astropy_helpers manually using pip -(`pip install astropy_helpers`) or by manually downloading the source archive, -extracting it, and installing by running `python setup.py install` from the -root of the extracted source code. -""" - - -class _AHBootstrapSystemExit(SystemExit): - def __init__(self, *args): - if not args: - msg = 'An unknown problem occurred bootstrapping astropy_helpers.' - else: - msg = args[0] - - msg += '\n' + _err_help_msg - - super(_AHBootstrapSystemExit, self).__init__(msg, *args[1:]) - - -BOOTSTRAPPER = _Bootstrapper.main() - - -def use_astropy_helpers(**kwargs): - """ - Ensure that the `astropy_helpers` module is available and is importable. - This supports automatic submodule initialization if astropy_helpers is - included in a project as a git submodule, or will download it from PyPI if - necessary. - - Parameters - ---------- - - path : str or None, optional - A filesystem path relative to the root of the project's source code - that should be added to `sys.path` so that `astropy_helpers` can be - imported from that path. - - If the path is a git submodule it will automatically be initialized - and/or updated. - - The path may also be to a ``.tar.gz`` archive of the astropy_helpers - source distribution. In this case the archive is automatically - unpacked and made temporarily available on `sys.path` as a ``.egg`` - archive. - - If `None` skip straight to downloading. - - download_if_needed : bool, optional - If the provided filesystem path is not found an attempt will be made to - download astropy_helpers from PyPI. It will then be made temporarily - available on `sys.path` as a ``.egg`` archive (using the - ``setup_requires`` feature of setuptools. If the ``--offline`` option - is given at the command line the value of this argument is overridden - to `False`. - - index_url : str, optional - If provided, use a different URL for the Python package index than the - main PyPI server. - - use_git : bool, optional - If `False` no git commands will be used--this effectively disables - support for git submodules. If the ``--no-git`` option is given at the - command line the value of this argument is overridden to `False`. - - auto_upgrade : bool, optional - By default, when installing a package from a non-development source - distribution ah_boostrap will try to automatically check for patch - releases to astropy-helpers on PyPI and use the patched version over - any bundled versions. Setting this to `False` will disable that - functionality. If the ``--offline`` option is given at the command line - the value of this argument is overridden to `False`. - - offline : bool, optional - If `False` disable all actions that require an internet connection, - including downloading packages from the package index and fetching - updates to any git submodule. Defaults to `True`. - """ - - global BOOTSTRAPPER - - config = BOOTSTRAPPER.config - config.update(**kwargs) - - # Create a new bootstrapper with the updated configuration and run it - BOOTSTRAPPER = _Bootstrapper(**config) - BOOTSTRAPPER.run() From 58df92941d4009a2a9e7ecd874ab89a2ecb6705b Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 13:45:35 -0700 Subject: [PATCH 08/22] remove astropy_helpers --- .gitmodules | 3 --- astropy_helpers | 1 - 2 files changed, 4 deletions(-) delete mode 160000 astropy_helpers diff --git a/.gitmodules b/.gitmodules index 6a20fa6e..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "astropy_helpers"] - path = astropy_helpers - url = https://github.com/astropy/astropy-helpers.git diff --git a/astropy_helpers b/astropy_helpers deleted file mode 160000 index ce42e6e2..00000000 --- a/astropy_helpers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ce42e6e238c200a4715785ef8c9d233f612d0c75 From 6eb81099e020758d617adbebb3d979228f6c0cd1 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 13:45:54 -0700 Subject: [PATCH 09/22] remove .gitmodules --- .gitmodules | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29b..00000000 From 69b25790cd4bc57a8396061a2c5abf460fbcfdb5 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 13:59:15 -0700 Subject: [PATCH 10/22] add tests --- .travis.yml | 37 +++++++++++++++++++++++++++++++++---- MANIFEST.in | 22 ---------------------- setup.py | 2 -- tox.ini | 4 +++- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index c20508a5..db18b55a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -92,9 +92,15 @@ matrix: # Try MacOS X, usually enough only to run from cron as hardly there are # issues that are not picked up by a linux worker - # - os: osx - # stage: Cron tests - # env: SETUP_CMD='test' EVENT_TYPE='cron' + - os: osx + stage: Cron tests + python: 3.7 + env: TOXENV='test' + + - os: windows + stage: Cron tests + python: 3.7 + env: TOXENV='test' # Do a coverage test. # - os: linux @@ -111,6 +117,14 @@ matrix: # - os: linux # env: ASTROPY_VERSION=development # EVENT_TYPE='pull_request push cron' + - os: linux + python: 3.7 + env: TOXENV='test-dev' + EVENT_TYPE='pull_request push cron' + + - os: linux + python: 3.6 + env: TOXENV='test-astropy2' # - os: linux # env: PYTHON_VERSION=3.6 ASTROPY_VERSION=2.0.16 NUMPY_VERSION=1.14 PYTEST_VERSION='<3.7' @@ -122,6 +136,12 @@ matrix: # env: ASTROPY_VERSION=development NUMPY_VERSION=development # EVENT_TYPE='cron' + - os: linux + stage: Cron tests + python: 3.7 + env: TOXENV='test-all-dev' + EVENT_TYPE='cron' + # Try all python versions and Numpy versions. Since we can assume that # the Numpy developers have taken care of testing Numpy with different # versions of Python, we can vary Python and Numpy versions at the same @@ -132,6 +152,14 @@ matrix: # - os: linux # env: NUMPY_VERSION=1.16 + - os: linux + python: 3.6 + env: TOXENV='test-numpy116' + + - os: linux + python: 3.7 + env: TOXENV='test-numpy117' + # Do a PEP8 test with flake8 - os: linux stage: Initial tests @@ -164,7 +192,8 @@ install: source ci-helpers/travis/setup_conda.sh; fi - - pip install tox --upgrade + - pip install --upgrade pip + - pip install --upgrade tox # As described above, using ci-helpers, you should be able to set up an # environment with dependencies installed using conda and pip, but in some diff --git a/MANIFEST.in b/MANIFEST.in index f574e556..39699d04 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,7 +2,6 @@ include README.rst include LICENSE.rst # include CHANGES.rst -# include ah_bootstrap.py include pyproject.toml include setup.cfg include pydl/tests/coveragerc @@ -19,25 +18,4 @@ prune build prune docs/_build prune docs/api - -# the next few stanzas are for astropy_helpers. It's derived from the -# astropy_helpers/MANIFEST.in, but requires additional includes for the actual -# package directory and egg-info. -# -# include astropy_helpers/README.rst -# include astropy_helpers/CHANGES.rst -# include astropy_helpers/LICENSE.rst -# recursive-include astropy_helpers/licenses * -# -# include astropy_helpers/ah_bootstrap.py -# -# recursive-include astropy_helpers/astropy_helpers *.py *.pyx *.c *.h *.rst -# recursive-include astropy_helpers/astropy_helpers.egg-info * -# include the sphinx stuff with "*" because there are css/html/rst/etc. -# recursive-include astropy_helpers/astropy_helpers/sphinx * -# -# prune astropy_helpers/build -# prune astropy_helpers/astropy_helpers/tests - - global-exclude *.pyc *.o diff --git a/setup.py b/setup.py index dd7b461f..82b1d7ad 100755 --- a/setup.py +++ b/setup.py @@ -4,8 +4,6 @@ import os import sys -# Needed to import local helpers when pyproject.toml exists. -# sys.path.append(".") from setuptools import setup from distutils.command.sdist import sdist as DistutilsSdist diff --git a/tox.ini b/tox.ini index 1aac543c..4389557f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py{35,36,37,38}-test{,-all,-dev} + py{35,36,37,38}-test{,-all,-dev,-astropy2} build_docs codestyle requires = @@ -33,6 +33,8 @@ commands = deps = astropylts: astropy==4.0 astropy2: astropy==2.0.14 + astropy2: numpy==1.14.* + astropy2: pytest<3.7 numpy116: numpy==1.16.* numpy117: numpy==1.17.* numpy118: numpy==1.18.* From dcca585f1d8827de5237bfd7c19a1927eb4fcc44 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 14:28:35 -0700 Subject: [PATCH 11/22] separate out astropy2 test --- .travis.yml | 2 +- tox.ini | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index db18b55a..c82949f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -124,7 +124,7 @@ matrix: - os: linux python: 3.6 - env: TOXENV='test-astropy2' + env: TOXENV='astropy2' # - os: linux # env: PYTHON_VERSION=3.6 ASTROPY_VERSION=2.0.16 NUMPY_VERSION=1.14 PYTEST_VERSION='<3.7' diff --git a/tox.ini b/tox.ini index 4389557f..ad6a1658 100644 --- a/tox.ini +++ b/tox.ini @@ -32,7 +32,7 @@ commands = build_docs: sphinx-build . ./_build/html -W --keep-going -b html {posargs} deps = astropylts: astropy==4.0 - astropy2: astropy==2.0.14 + astropy2: astropy==2.0.16 astropy2: numpy==1.14.* astropy2: pytest<3.7 numpy116: numpy==1.16.* @@ -41,6 +41,15 @@ deps = dev: git+https://github.com/numpy/numpy.git#egg=numpy dev: git+https://github.com/astropy/astropy.git#egg=astropy +[testenv:astropy2] +description = Run tests on Astropy 2.0.x. +deps = + astropy==2.0.16 + numpy==1.14.* + pytest<3.7 + pytest-mock +commands = pytest --pyargs pydl {toxinidir}/docs {posargs} + ; [testenv:coverage] ; requires = ; pytest-cov From 86cc062d534424b29fb97dd614efa5051ebb3ba5 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 14:48:00 -0700 Subject: [PATCH 12/22] add coverage test --- .travis.yml | 6 +++--- tox.ini | 15 +++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index c82949f8..4d3a4b59 100644 --- a/.travis.yml +++ b/.travis.yml @@ -103,9 +103,9 @@ matrix: env: TOXENV='test' # Do a coverage test. - # - os: linux - # stage: Initial tests - # env: SETUP_CMD='test --coverage' + - os: linux + stage: Initial tests + env: TOXENV='coverage' # Check for sphinx doc build warnings - we do this first because it # may run for a long time diff --git a/tox.ini b/tox.ini index ad6a1658..f3dfac4f 100644 --- a/tox.ini +++ b/tox.ini @@ -50,12 +50,15 @@ deps = pytest-mock commands = pytest --pyargs pydl {toxinidir}/docs {posargs} -; [testenv:coverage] -; requires = -; pytest-cov -; coverage -; commands = -; pytest --cov pydl +[testenv:coverage] +description = Run coverage test with all optional dependencies. +extras = + test + all +requires = + coveralls +commands = + pytest --cov pydl {posargs} [testenv:codestyle] skip_install = true From 57bb5c2e8f7d1fdbfcb100ebe07bab9a3889f098 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 14:55:11 -0700 Subject: [PATCH 13/22] install coveralls --- .travis.yml | 2 ++ tox.ini | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4d3a4b59..ad1a0f28 100644 --- a/.travis.yml +++ b/.travis.yml @@ -105,6 +105,7 @@ matrix: # Do a coverage test. - os: linux stage: Initial tests + python: 3.7 env: TOXENV='coverage' # Check for sphinx doc build warnings - we do this first because it @@ -194,6 +195,7 @@ install: - pip install --upgrade pip - pip install --upgrade tox + - if [[ ${TOXENV} == 'coverage' ]]; then pip install coveralls; fi # As described above, using ci-helpers, you should be able to set up an # environment with dependencies installed using conda and pip, but in some diff --git a/tox.ini b/tox.ini index f3dfac4f..66dd65d6 100644 --- a/tox.ini +++ b/tox.ini @@ -55,8 +55,8 @@ description = Run coverage test with all optional dependencies. extras = test all -requires = - coveralls +; requires = +; coveralls commands = pytest --cov pydl {posargs} From a75cb06e5e9f494bd77029ce9a98851d72a16819 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 15:06:04 -0700 Subject: [PATCH 14/22] update coveragerc --- pydl/tests/coveragerc | 16 +++++++++++----- tox.ini | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pydl/tests/coveragerc b/pydl/tests/coveragerc index 02719b10..4d615c55 100644 --- a/pydl/tests/coveragerc +++ b/pydl/tests/coveragerc @@ -3,17 +3,20 @@ source = pydl omit = pydl/_astropy_init* pydl/conftest* - pydl/cython_version* - pydl/setup_package* - pydl/*/setup_package* - pydl/*/*/setup_package* pydl/tests/* pydl/*/tests/* pydl/*/*/tests/* pydl/version* [report] -exclude_lines = +omit = + pydl/_astropy_init* + pydl/conftest* + pydl/tests/test_* + pydl/*/tests/* + pydl/*/*/tests/* + pydl/version* +exclude_lines= # Have to re-enable the standard pragma pragma: no cover @@ -29,3 +32,6 @@ exclude_lines = # Ignore branches that don't pertain to this version of Python pragma: py{ignore_python_version} + + # Don't complain about IPython completion helper + def _ipython_key_completions_ diff --git a/tox.ini b/tox.ini index 66dd65d6..94eafe72 100644 --- a/tox.ini +++ b/tox.ini @@ -58,7 +58,7 @@ extras = ; requires = ; coveralls commands = - pytest --cov pydl {posargs} + pytest --pyargs pydl {toxinidir}/docs --cov pydl --cov-config={toxinidir}/astropy/tests/coveragerc {posargs} [testenv:codestyle] skip_install = true From ce2bb9d23d0faa4d79b91a710fbe885dc83fb7d5 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 15:11:54 -0700 Subject: [PATCH 15/22] fix coveragerc path --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 94eafe72..a01559c0 100644 --- a/tox.ini +++ b/tox.ini @@ -58,7 +58,7 @@ extras = ; requires = ; coveralls commands = - pytest --pyargs pydl {toxinidir}/docs --cov pydl --cov-config={toxinidir}/astropy/tests/coveragerc {posargs} + pytest --pyargs pydl {toxinidir}/docs --cov pydl --cov-config={toxinidir}/pydl/tests/coveragerc {posargs} [testenv:codestyle] skip_install = true From 0ce0c762314e0703648363d1121da22fe721ebf3 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Wed, 15 Jan 2020 16:02:37 -0700 Subject: [PATCH 16/22] additional numpy tests --- .travis.yml | 8 ++++++++ tox.ini | 5 +---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ad1a0f28..a3dbce31 100644 --- a/.travis.yml +++ b/.travis.yml @@ -153,6 +153,10 @@ matrix: # - os: linux # env: NUMPY_VERSION=1.16 + - os: linux + python: 3.5 + env: TOXENV='test-numpy116' + - os: linux python: 3.6 env: TOXENV='test-numpy116' @@ -161,6 +165,10 @@ matrix: python: 3.7 env: TOXENV='test-numpy117' + - os: linux + python: 3.7 + env: TOXENV='test-numpy118' + # Do a PEP8 test with flake8 - os: linux stage: Initial tests diff --git a/tox.ini b/tox.ini index a01559c0..0fc863fe 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py{35,36,37,38}-test{,-all,-dev,-astropy2} + py{35,36,37,38}-test{,-all,-dev,-astropylts,-numpy116,-numpy117,-numpy118} build_docs codestyle requires = @@ -32,9 +32,6 @@ commands = build_docs: sphinx-build . ./_build/html -W --keep-going -b html {posargs} deps = astropylts: astropy==4.0 - astropy2: astropy==2.0.16 - astropy2: numpy==1.14.* - astropy2: pytest<3.7 numpy116: numpy==1.16.* numpy117: numpy==1.17.* numpy118: numpy==1.18.* From c472b26fda12cb623ed1840faa5da91267e314a1 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Thu, 16 Jan 2020 16:10:14 -0700 Subject: [PATCH 17/22] update conftest.py to match package-template --- pydl/conftest.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/pydl/conftest.py b/pydl/conftest.py index 8cd90036..cbd8a18a 100644 --- a/pydl/conftest.py +++ b/pydl/conftest.py @@ -13,7 +13,7 @@ # plugins themselves in order to make them discoverable by pytest. # from astropy.tests.pytest_plugins import * - del pytest_report_header + # del pytest_report_header else: # As of Astropy 4.0, the pytest plugins provided by Astropy are # now in the pytest-astropy-header package. This is backward-compatible @@ -34,24 +34,24 @@ ## warnings_to_ignore_by_pyver={(MAJOR, MINOR): ['Message to ignore']} # enable_deprecations_as_exceptions() -def pytest_configure(config): +# def pytest_configure(config): - config.option.astropy_header = True - # - # Customize the following lines to add/remove entries from - # the list of packages for which version numbers are displayed when running - # the tests. - # - PYTEST_HEADER_MODULES['Astropy'] = 'astropy' - PYTEST_HEADER_MODULES['PyDL'] = 'pydl' - PYTEST_HEADER_MODULES.pop('Pandas', None) - PYTEST_HEADER_MODULES.pop('h5py', None) +# config.option.astropy_header = True +# +# Customize the following lines to add/remove entries from +# the list of packages for which version numbers are displayed when running +# the tests. +# +PYTEST_HEADER_MODULES['Astropy'] = 'astropy' +PYTEST_HEADER_MODULES['PyDL'] = 'pydl' +PYTEST_HEADER_MODULES.pop('Pandas', None) +PYTEST_HEADER_MODULES.pop('h5py', None) - from .version import version #, astropy_helpers_version - packagename = os.path.basename(os.path.dirname(__file__)) - # - # Display the version number of the package rather than the version number - # of Astropy in the top line when running the tests. - # - TESTED_VERSIONS[packagename] = version - # TESTED_VERSIONS['astropy_helpers'] = astropy_helpers_version +from .version import version #, astropy_helpers_version +packagename = os.path.basename(os.path.dirname(__file__)) +# +# Display the version number of the package rather than the version number +# of Astropy in the top line when running the tests. +# +TESTED_VERSIONS[packagename] = version +# TESTED_VERSIONS['astropy_helpers'] = astropy_helpers_version From 55bfbbac30e40277dc2386ce500a1ac6a5f30d18 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Fri, 17 Jan 2020 13:58:52 -0700 Subject: [PATCH 18/22] update license date [skip ci] --- LICENSE.rst | 2 +- pydl/conftest.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/LICENSE.rst b/LICENSE.rst index a92c0063..c5a100e9 100644 --- a/LICENSE.rst +++ b/LICENSE.rst @@ -1,4 +1,4 @@ -Copyright (c) 2010-2018, Benjamin Alan Weaver +Copyright (c) 2010-2020, Benjamin Alan Weaver All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/pydl/conftest.py b/pydl/conftest.py index cbd8a18a..c755ff55 100644 --- a/pydl/conftest.py +++ b/pydl/conftest.py @@ -55,3 +55,4 @@ # TESTED_VERSIONS[packagename] = version # TESTED_VERSIONS['astropy_helpers'] = astropy_helpers_version +TESTED_VERSIONS.pop('astropy_helpers', None) From b32b09d2750df34e057e3d51efc15f32c1e88015 Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Fri, 17 Jan 2020 14:16:54 -0700 Subject: [PATCH 19/22] allow language: c for osx and windows builds --- .travis.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a3dbce31..6f8080fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ # We set the language to c because python isn't supported on the MacOS X nodes # on Travis. However, the language ends up being irrelevant anyway, since we # install Python ourselves using conda. -language: python +language: c os: - linux @@ -20,6 +20,7 @@ addons: apt: packages: - graphviz + - tzdata stage: Comprehensive tests @@ -82,6 +83,7 @@ matrix: include: - os: linux + language: python stage: Initial tests python: 3.8 env: TOXENV='test' @@ -104,6 +106,7 @@ matrix: # Do a coverage test. - os: linux + language: python stage: Initial tests python: 3.7 env: TOXENV='coverage' @@ -111,6 +114,7 @@ matrix: # Check for sphinx doc build warnings - we do this first because it # may run for a long time - os: linux + language: python python: 3.7 env: TOXENV='build_docs' @@ -119,11 +123,13 @@ matrix: # env: ASTROPY_VERSION=development # EVENT_TYPE='pull_request push cron' - os: linux + language: python python: 3.7 env: TOXENV='test-dev' EVENT_TYPE='pull_request push cron' - os: linux + language: python python: 3.6 env: TOXENV='astropy2' # - os: linux @@ -138,6 +144,7 @@ matrix: # EVENT_TYPE='cron' - os: linux + language: python stage: Cron tests python: 3.7 env: TOXENV='test-all-dev' @@ -154,23 +161,28 @@ matrix: # env: NUMPY_VERSION=1.16 - os: linux + language: python python: 3.5 env: TOXENV='test-numpy116' - os: linux + language: python python: 3.6 env: TOXENV='test-numpy116' - os: linux + language: python python: 3.7 env: TOXENV='test-numpy117' - os: linux + language: python python: 3.7 env: TOXENV='test-numpy118' # Do a PEP8 test with flake8 - os: linux + language: python stage: Initial tests python: 3.7 env: TOXENV='codestyle' @@ -179,6 +191,7 @@ matrix: # Do a PEP8 test with flake8 # (do allow to fail unless your code completely compliant) - os: linux + language: python stage: Initial tests python: 3.7 env: TOXENV='codestyle' From 2f136867dbda524e8468ad2cffbe169227ece5ad Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Fri, 17 Jan 2020 14:41:48 -0700 Subject: [PATCH 20/22] fix some test warnings --- pydl/pydlutils/mangle.py | 4 ++-- pydl/tests/test_pydl.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pydl/pydlutils/mangle.py b/pydl/pydlutils/mangle.py index 459c2aae..81c5836e 100644 --- a/pydl/pydlutils/mangle.py +++ b/pydl/pydlutils/mangle.py @@ -286,7 +286,7 @@ def _garea_helper(self): """ if self.gzeroar(): return 0.0 - warnings.warn(("The ManglePolygon.garea() method is incomplete" + + warnings.warn(("The ManglePolygon.garea() method is incomplete " + "and is returning a dummy value."), PydlutilsUserWarning) return 1.0 @@ -675,7 +675,7 @@ def read_mangle_polygons(filename): :class:`~pydl.pydlutils.mangle.ManglePolygon` objects and any metadata. """ - with open(filename, 'rU') as ply: + with open(filename, 'r') as ply: lines = ply.read().split(ply.newlines) try: npoly = int(lines[0].split()[0]) diff --git a/pydl/tests/test_pydl.py b/pydl/tests/test_pydl.py index d817966e..5a23a4d6 100644 --- a/pydl/tests/test_pydl.py +++ b/pydl/tests/test_pydl.py @@ -7,7 +7,7 @@ try: from astropy.tests.compat import assert_allclose except ImportError: - from numpy.testing.utils import assert_allclose + from numpy.testing import assert_allclose from astropy.tests.helper import raises from astropy.utils.data import get_pkg_data_filename from ..file_lines import file_lines From 019cd4bd25a2d494940d7a51bdd4c57a5da4c44e Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Fri, 17 Jan 2020 14:49:14 -0700 Subject: [PATCH 21/22] try to eliminate index warnings --- pydl/__init__.py | 10 +++++----- pydl/rebin.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pydl/__init__.py b/pydl/__init__.py index 8042e9b9..7da94da8 100644 --- a/pydl/__init__.py +++ b/pydl/__init__.py @@ -42,11 +42,11 @@ class UnsupportedPythonError(Exception): # Workaround: Numpy 1.14.x changes the way arrays are printed. -try: - from numpy import set_printoptions - set_printoptions(legacy='1.13') -except Exception: - pass +# try: +# from numpy import set_printoptions +# set_printoptions(legacy='1.13') +# except Exception: +# pass class PydlException(Exception): diff --git a/pydl/rebin.py b/pydl/rebin.py index 1844ad94..17458658 100644 --- a/pydl/rebin.py +++ b/pydl/rebin.py @@ -105,7 +105,7 @@ def rebin(x, d, sample=False): r[sliceobj] = xx[sliceobj0] else: sliceobj0[k] = slice(int(f*i), int(f*(i+1))) - rshape = r[sliceobj].shape + rshape = r[tuple(sliceobj)].shape r[sliceobj] = xx[sliceobj0].sum(k).reshape(rshape)/f xx = r return r From 41db21a904c90f734efe060db8cbd2c75e38d3eb Mon Sep 17 00:00:00 2001 From: Benjamin Alan Weaver Date: Fri, 17 Jan 2020 14:56:32 -0700 Subject: [PATCH 22/22] eliminate warnings. Fixes #57. Fixes #56. --- pydl/pydlutils/cooling.py | 2 +- pydl/rebin.py | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pydl/pydlutils/cooling.py b/pydl/pydlutils/cooling.py index d855c650..be78e8a7 100644 --- a/pydl/pydlutils/cooling.py +++ b/pydl/pydlutils/cooling.py @@ -39,7 +39,7 @@ def read_ds_cooling(fname, logT=None): >>> from pydl.pydlutils.cooling import read_ds_cooling >>> logT, loglambda = read_ds_cooling('m-15.cie') >>> logT[0:5] # doctest: +NORMALIZE_WHITESPACE - array([ 4. , 4.05, 4.1 , 4.15, 4.2 ]) + array([4. , 4.05, 4.1 , 4.15, 4.2 ]) >>> loglambda[0:5] # doctest: +NORMALIZE_WHITESPACE array([-26. , -24.66, -23.52, -22.62, -22.11]) """ diff --git a/pydl/rebin.py b/pydl/rebin.py index 17458658..4969da94 100644 --- a/pydl/rebin.py +++ b/pydl/rebin.py @@ -44,9 +44,9 @@ def rebin(x, d, sample=False): >>> from numpy import arange, float >>> from pydl import rebin >>> rebin(arange(10, dtype=float), (5,)) # doctest: +NORMALIZE_WHITESPACE - array([ 0.5, 2.5, 4.5, 6.5, 8.5]) + array([0.5, 2.5, 4.5, 6.5, 8.5]) >>> rebin(arange(5, dtype=float), (10,)) # doctest: +NORMALIZE_WHITESPACE - array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4. ]) + array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4. ]) """ from numpy import floor, zeros d0 = x.shape @@ -80,32 +80,32 @@ def rebin(x, d, sample=False): sliceobj0[k] = slice(fp, fp + 1) sliceobj[k] = slice(i, i + 1) if sample: - r[sliceobj] = xx[sliceobj0] + r[tuple(sliceobj)] = xx[tuple(sliceobj0)] else: if p < d0[k] - 1: sliceobj1[k] = slice(fp + 1, fp + 2) - rshape = r[sliceobj].shape - r[sliceobj] = (xx[sliceobj0].reshape(rshape) + - (p - fp)*(xx[sliceobj1] - - xx[sliceobj0]).reshape(rshape) + rshape = r[tuple(sliceobj)].shape + r[tuple(sliceobj)] = (xx[tuple(sliceobj0)].reshape(rshape) + + (p - fp)*(xx[tuple(sliceobj1)] - + xx[tuple(sliceobj0)]).reshape(rshape) ) else: - r[sliceobj] = xx[sliceobj0] + r[tuple(sliceobj)] = xx[tuple(sliceobj0)] elif d[k] == d0[k]: for i in range(d[k]): sliceobj0[k] = slice(i, i + 1) sliceobj[k] = slice(i, i + 1) - r[sliceobj] = xx[sliceobj0] + r[tuple(sliceobj)] = xx[tuple(sliceobj0)] else: for i in range(d[k]): sliceobj[k] = slice(i, i + 1) if sample: fp = int(floor(f*i)) sliceobj0[k] = slice(fp, fp + 1) - r[sliceobj] = xx[sliceobj0] + r[tuple(sliceobj)] = xx[tuple(sliceobj0)] else: sliceobj0[k] = slice(int(f*i), int(f*(i+1))) rshape = r[tuple(sliceobj)].shape - r[sliceobj] = xx[sliceobj0].sum(k).reshape(rshape)/f + r[tuple(sliceobj)] = xx[tuple(sliceobj0)].sum(k).reshape(rshape)/f xx = r return r