From 04a8d908948c23369e22fc00c1a605aefd4d6d3d Mon Sep 17 00:00:00 2001 From: Pey Lian Lim <2090236+pllim@users.noreply.github.com> Date: Fri, 6 Dec 2024 00:14:03 -1000 Subject: [PATCH] WIP: Infra clean-up --- .flake8 | 5 + .github/dependabot.yml | 1 - .github/workflows/ci_tests.yml | 31 ++-- LONG_DESCRIPTION.rst | 12 -- MANIFEST.in | 1 - README.rst | 22 ++- astroplan/__init__.py | 12 -- astroplan/conftest.py | 46 ------ astroplan/constraints.py | 257 ++++++++++++++++----------------- astroplan/observer.py | 12 +- astroplan/periodic.py | 2 +- astroplan/setup_package.py | 9 -- astroplan/target.py | 4 +- astroplan/tests/coveragerc | 31 ---- conftest.py | 24 +++ docs/Makefile | 2 +- docs/conf.py | 108 ++------------ docs/installation.rst | 12 +- pyproject.toml | 126 +++++++++++++++- setup.cfg | 98 ------------- setup.py | 63 -------- tox.ini | 32 +--- 22 files changed, 348 insertions(+), 562 deletions(-) create mode 100644 .flake8 delete mode 100644 LONG_DESCRIPTION.rst delete mode 100644 astroplan/conftest.py delete mode 100644 astroplan/setup_package.py delete mode 100644 astroplan/tests/coveragerc create mode 100644 conftest.py delete mode 100644 setup.cfg delete mode 100755 setup.py diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..2aec964a --- /dev/null +++ b/.flake8 @@ -0,0 +1,5 @@ +# flake8 does not support pyproject.toml (https://github.com/PyCQA/flake8/issues/234) + +[flake8] +max-line-length = 100 +exclude = __init__.py diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9c39a860..1a218f5e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,4 +13,3 @@ updates: actions: patterns: - "*" - diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 3dbfd4e2..838da41a 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -30,33 +30,38 @@ jobs: python: 3.x toxenv: codestyle - - name: Python 3.7 with minimal dependencies + - name: Link checks os: ubuntu-latest - python: 3.7 - toxenv: py37-test + python: 3.x + toxenv: linkcheck - - name: OS X - Python 3.9 with minimal dependencies + - name: OS X - Python 3.13 with minimal dependencies os: macos-latest - python: 3.9 - toxenv: py39-test + python: '3.13' + toxenv: py313-test - name: Windows - Python 3.11 with all optional dependencies os: windows-latest python: '3.11' - toxenv: py11-test-alldeps + toxenv: py311-test-alldeps toxargs: -v - - name: Python 3.11 with remote data, all dependencies, and coverage + - name: Python 3.12 with remote data, all dependencies, and coverage os: ubuntu-latest - python: '3.11' - toxenv: py11-test-alldeps-cov + python: '3.12' + toxenv: py312-test-alldeps-cov toxargs: -v posargs: --remote-data=any - - name: Python 3.11 with latest dev versions of key dependencies + - name: Python 3.13 with latest dev versions of key dependencies + os: ubuntu-latest + python: '3.13' + toxenv: py313-test-devdeps + + - name: Python 3.11 with oldest version of key dependencies os: ubuntu-latest python: '3.11' - toxenv: py11-test-devdeps + toxenv: py311-test-oldestdeps steps: - name: Checkout code @@ -70,7 +75,7 @@ jobs: - name: Install base dependencies run: | python -m pip install --upgrade pip - python -m pip install tox codecov + python -m pip install tox - name: Install graphviz dependency if: ${{ contains(matrix.toxenv, 'build_docs') }} run: sudo apt-get -y install graphviz diff --git a/LONG_DESCRIPTION.rst b/LONG_DESCRIPTION.rst deleted file mode 100644 index 9598f0e2..00000000 --- a/LONG_DESCRIPTION.rst +++ /dev/null @@ -1,12 +0,0 @@ -* Code: https://github.com/astropy/astroplan -* Docs: https://astroplan.readthedocs.io/ - -**astroplan** is an open source (BSD licensed) observation planning package for -astronomers that can help you plan for everything but the clouds. - -It is an in-development `Astropy `__ -`affiliated package `__ that -seeks to make your life as an observational astronomer a little less -infuriating. - -Contributions welcome! diff --git a/MANIFEST.in b/MANIFEST.in index 7743dc11..e51e016b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,7 +3,6 @@ include README.rst include CHANGES.rst include pyproject.toml -include setup.cfg recursive-include docs * recursive-include licenses * diff --git a/README.rst b/README.rst index e90f94d4..9ecd65da 100644 --- a/README.rst +++ b/README.rst @@ -1,12 +1,6 @@ astroplan ========= -Observation planning package for astronomers - -* Code: https://github.com/astropy/astroplan -* Docs: https://astroplan.readthedocs.io/ -* License: BSD-3 - .. image:: https://readthedocs.org/projects/astroplan/badge/?version=latest :target: https://astroplan.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status @@ -25,10 +19,24 @@ Observation planning package for astronomers :target: https://pypi.python.org/pypi/astroplan/ :alt: Latest release +* Code: https://github.com/astropy/astroplan +* Docs: https://astroplan.readthedocs.io/ +* License: BSD-3 Clause + +**astroplan** is an open-source observation planning package for +astronomers that can help you plan for everything but the clouds. + +It is an `Astropy `__ +`affiliated package `__ that +seeks to make your life as an observational astronomer a little less +infuriating. + +Contributions welcome! + Attribution +++++++++++ -If you use astroplan in your work, please cite `Morris et al. 2018 `_: +If you use astroplan in your work, please cite `Morris et al. 2018 `_: .. code :: bibtex diff --git a/astroplan/__init__.py b/astroplan/__init__.py index c5ce9258..fbb0fdac 100644 --- a/astroplan/__init__.py +++ b/astroplan/__init__.py @@ -1,16 +1,4 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst -""" -astroplan is an open source (BSD licensed) observation planning package for -astronomers that can help you plan for everything but the clouds. - -It is an in-development `Astropy `__ -`affiliated package `__ that -seeks to make your life as an observational astronomer a little less -infuriating. - -* Code: https://github.com/astropy/astroplan -* Docs: https://astroplan.readthedocs.io/ -""" try: from .version import version as __version__ diff --git a/astroplan/conftest.py b/astroplan/conftest.py deleted file mode 100644 index cfaf7aad..00000000 --- a/astroplan/conftest.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -This file contains functions that configure py.test like astropy but with -additions for astroplan. Py.test looks for specially-named functions -(like ``pytest_configure``) and uses those to configure itself. - -Here, we want to keep the behavior of astropy while *adding* more for astroplan. -To do that, in the functions below, we first invoke the functions from astropy, -and then after that do things specific to astroplan. But we also want astropy -functionality for any functions we have *not* overriden, so that's why the -``import *`` happens at the top. -""" -try: - from pytest_astropy_header.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS -except ImportError: # In case this plugin is not installed - PYTEST_HEADER_MODULES = {} - TESTED_VERSIONS = {} - -# We do this to pick up the test header report even when using LTS astropy -try: - from astropy.tests.pytest_plugins import pytest_report_header # noqa -except ImportError: - pass - -import os - -# This is to figure out the affiliated package version, rather than -# using Astropy's -try: - from .version import version -except ImportError: - version = 'dev' - -packagename = os.path.basename(os.path.dirname(__file__)) -TESTED_VERSIONS[packagename] = version - - -# Define list of packages for which to display version numbers in the test log -try: - PYTEST_HEADER_MODULES['Astropy'] = 'astropy' - PYTEST_HEADER_MODULES['pytz'] = 'pytz' - PYTEST_HEADER_MODULES['pyephem'] = 'ephem' - PYTEST_HEADER_MODULES['matplotlib'] = 'matplotlib' - PYTEST_HEADER_MODULES['pytest-mpl'] = 'pytest_mpl' - del PYTEST_HEADER_MODULES['h5py'] -except KeyError: - pass diff --git a/astroplan/constraints.py b/astroplan/constraints.py index 3de8351f..17b74f84 100644 --- a/astroplan/constraints.py +++ b/astroplan/constraints.py @@ -5,25 +5,24 @@ """ # Standard library -from abc import ABCMeta, abstractmethod import datetime import time import warnings +from abc import ABCMeta, abstractmethod # Third-party -from astropy.time import Time import astropy.units as u -from astropy.coordinates import get_body, get_sun, Galactic, SkyCoord -from astropy import table - import numpy as np +from astropy import table +from astropy.time import Time +from astropy.coordinates import get_body, get_sun, Galactic, SkyCoord from numpy.lib.stride_tricks import as_strided # Package +from .exceptions import MissingConstraintWarning from .moon import moon_illumination -from .utils import time_grid_from_range from .target import get_skycoord -from .exceptions import MissingConstraintWarning +from .utils import time_grid_from_range __all__ = ["AltitudeConstraint", "AirmassConstraint", "AtNightConstraint", "is_observable", "is_always_observable", "time_grid_from_range", @@ -214,7 +213,7 @@ def _get_meridian_transit_times(times, observer, targets): @abstractmethod -class Constraint(object): +class Constraint: """ Abstract class for objects defining observational constraints. """ @@ -318,7 +317,6 @@ class AltitudeConstraint(Constraint): This can misbehave if you try to constrain negative altitudes, as the `~astropy.coordinates.AltAz` frame tends to mishandle negative - Parameters ---------- min : `~astropy.units.Quantity` or `None` @@ -378,7 +376,7 @@ class AirmassConstraint(AltitudeConstraint): Examples -------- To create a constraint that requires the airmass be "better than 2", - i.e. at a higher altitude than airmass=2:: + i.e., at a higher altitude than airmass=2:: AirmassConstraint(2) """ @@ -490,19 +488,18 @@ def compute_constraint(self, times, observer, targets): class GalacticLatitudeConstraint(Constraint): """ Constrain the distance between the Galactic plane and some targets. + + Parameters + ---------- + min : `~astropy.units.Quantity` or `None` (optional) + Minimum acceptable Galactic latitude of target (inclusive). + `None` indicates no limit. + max : `~astropy.units.Quantity` or `None` (optional) + Minimum acceptable Galactic latitude of target (inclusive). + `None` indicates no limit. """ def __init__(self, min=None, max=None): - """ - Parameters - ---------- - min : `~astropy.units.Quantity` or `None` (optional) - Minimum acceptable Galactic latitude of target (inclusive). - `None` indicates no limit. - max : `~astropy.units.Quantity` or `None` (optional) - Minimum acceptable Galactic latitude of target (inclusive). - `None` indicates no limit. - """ self.min = min self.max = max @@ -524,19 +521,18 @@ def compute_constraint(self, times, observer, targets): class SunSeparationConstraint(Constraint): """ Constrain the distance between the Sun and some targets. + + Parameters + ---------- + min : `~astropy.units.Quantity` or `None` (optional) + Minimum acceptable separation between Sun and target (inclusive). + `None` indicates no limit. + max : `~astropy.units.Quantity` or `None` (optional) + Maximum acceptable separation between Sun and target (inclusive). + `None` indicates no limit. """ def __init__(self, min=None, max=None): - """ - Parameters - ---------- - min : `~astropy.units.Quantity` or `None` (optional) - Minimum acceptable separation between Sun and target (inclusive). - `None` indicates no limit. - max : `~astropy.units.Quantity` or `None` (optional) - Maximum acceptable separation between Sun and target (inclusive). - `None` indicates no limit. - """ self.min = min self.max = max @@ -566,23 +562,22 @@ def compute_constraint(self, times, observer, targets): class MoonSeparationConstraint(Constraint): """ Constrain the distance between the Earth's moon and some targets. + + Parameters + ---------- + min : `~astropy.units.Quantity` or `None` (optional) + Minimum acceptable separation between moon and target (inclusive). + `None` indicates no limit. + max : `~astropy.units.Quantity` or `None` (optional) + Maximum acceptable separation between moon and target (inclusive). + `None` indicates no limit. + ephemeris : str, optional + Ephemeris to use. If not given, use the one set with + ``astropy.coordinates.solar_system_ephemeris.set`` (which is + set to 'builtin' by default). """ def __init__(self, min=None, max=None, ephemeris=None): - """ - Parameters - ---------- - min : `~astropy.units.Quantity` or `None` (optional) - Minimum acceptable separation between moon and target (inclusive). - `None` indicates no limit. - max : `~astropy.units.Quantity` or `None` (optional) - Maximum acceptable separation between moon and target (inclusive). - `None` indicates no limit. - ephemeris : str, optional - Ephemeris to use. If not given, use the one set with - ``astropy.coordinates.solar_system_ephemeris.set`` (which is - set to 'builtin' by default). - """ self.min = min self.max = max self.ephemeris = ephemeris @@ -612,25 +607,23 @@ def compute_constraint(self, times, observer, targets): class MoonIlluminationConstraint(Constraint): """ Constrain the fractional illumination of the Earth's moon. - Constraint is also satisfied if the Moon has set. + + Parameters + ---------- + min : float or `None` (optional) + Minimum acceptable fractional illumination (inclusive). `None` + indicates no limit. + max : float or `None` (optional) + Maximum acceptable fractional illumination (inclusive). `None` + indicates no limit. + ephemeris : str, optional + Ephemeris to use. If not given, use the one set with + `~astropy.coordinates.solar_system_ephemeris` (which is + set to 'builtin' by default). """ def __init__(self, min=None, max=None, ephemeris=None): - """ - Parameters - ---------- - min : float or `None` (optional) - Minimum acceptable fractional illumination (inclusive). `None` - indicates no limit. - max : float or `None` (optional) - Maximum acceptable fractional illumination (inclusive). `None` - indicates no limit. - ephemeris : str, optional - Ephemeris to use. If not given, use the one set with - `~astropy.coordinates.solar_system_ephemeris` (which is - set to 'builtin' by default). - """ self.min = min self.max = max self.ephemeris = ephemeris @@ -638,8 +631,8 @@ def __init__(self, min=None, max=None, ephemeris=None): @classmethod def dark(cls, min=None, max=0.25, **kwargs): """ - initialize a `~astroplan.constraints.MoonIlluminationConstraint` - with defaults of no minimum and a maximum of 0.25 + Initialize a `~astroplan.constraints.MoonIlluminationConstraint` + with defaults of no minimum and a maximum of 0.25. Parameters ---------- @@ -655,8 +648,8 @@ def dark(cls, min=None, max=0.25, **kwargs): @classmethod def grey(cls, min=0.25, max=0.65, **kwargs): """ - initialize a `~astroplan.constraints.MoonIlluminationConstraint` - with defaults of a minimum of 0.25 and a maximum of 0.65 + Initialize a `~astroplan.constraints.MoonIlluminationConstraint` + with defaults of a minimum of 0.25 and a maximum of 0.65. Parameters ---------- @@ -672,8 +665,8 @@ def grey(cls, min=0.25, max=0.65, **kwargs): @classmethod def bright(cls, min=0.65, max=None, **kwargs): """ - initialize a `~astroplan.constraints.MoonIlluminationConstraint` - with defaults of a minimum of 0.65 and no maximum + Initialize a `~astroplan.constraints.MoonIlluminationConstraint` + with defaults of a minimum of 0.65 and no maximum. Parameters ---------- @@ -711,28 +704,26 @@ def compute_constraint(self, times, observer, targets): class LocalTimeConstraint(Constraint): """ Constrain the observable hours. - """ - def __init__(self, min=None, max=None): - """ - Parameters - ---------- - min : `~datetime.time` - Earliest local time (inclusive). `None` indicates no limit. + Parameters + ---------- + min : `~datetime.time` + Earliest local time (inclusive). `None` indicates no limit. - max : `~datetime.time` - Latest local time (inclusive). `None` indicates no limit. + max : `~datetime.time` + Latest local time (inclusive). `None` indicates no limit. - Examples - -------- - Constrain the observations to targets that are observable between - 23:50 and 04:08 local time: + Examples + -------- + Constrain the observations to targets that are observable between + 23:50 and 04:08 local time: - >>> import datetime as dt - >>> from astroplan.constraints import LocalTimeConstraint - >>> constraint = LocalTimeConstraint(min=dt.time(23, 50), max=dt.time(4, 8)) - """ + >>> import datetime as dt + >>> from astroplan.constraints import LocalTimeConstraint + >>> constraint = LocalTimeConstraint(min=dt.time(23, 50), max=dt.time(4, 8)) + """ + def __init__(self, min=None, max=None): self.min = min self.max = max @@ -796,29 +787,28 @@ class TimeConstraint(Constraint): time range with a specific observing block. This can be useful if not all observing blocks are valid over the time limits used in calls to `is_observable` or `is_always_observable`. + + Parameters + ---------- + min : `~astropy.time.Time` + Earliest time (inclusive). `None` indicates no limit. + + max : `~astropy.time.Time` + Latest time (inclusive). `None` indicates no limit. + + Examples + -------- + Constrain the observations to targets that are observable between + 2016-03-28 and 2016-03-30: + + >>> from astropy.time import Time + >>> from astroplan.constraints import TimeConstraint + >>> t1 = Time("2016-03-28T12:00:00") + >>> t2 = Time("2016-03-30T12:00:00") + >>> constraint = TimeConstraint(t1, t2) """ def __init__(self, min=None, max=None): - """ - Parameters - ---------- - min : `~astropy.time.Time` - Earliest time (inclusive). `None` indicates no limit. - - max : `~astropy.time.Time` - Latest time (inclusive). `None` indicates no limit. - - Examples - -------- - Constrain the observations to targets that are observable between - 2016-03-28 and 2016-03-30: - - >>> from astropy.time import Time - >>> from astroplan.constraints import TimeConstraint - >>> t1 = Time("2016-03-28T12:00:00") - >>> t2 = Time("2016-03-30T12:00:00") - >>> constraint = TimeConstraint(t1, t2) - """ self.min = min self.max = max @@ -848,15 +838,14 @@ def compute_constraint(self, times, observer, targets): class PrimaryEclipseConstraint(Constraint): """ Constrain observations to times during primary eclipse. + + Parameters + ---------- + eclipsing_system : `~astroplan.periodic.EclipsingSystem` + System which must be in primary eclipse. """ def __init__(self, eclipsing_system): - """ - Parameters - ---------- - eclipsing_system : `~astroplan.periodic.EclipsingSystem` - System which must be in primary eclipse. - """ self.eclipsing_system = eclipsing_system def compute_constraint(self, times, observer=None, targets=None): @@ -887,35 +876,37 @@ class PhaseConstraint(Constraint): """ Constrain observations to times in some range of phases for a periodic event (e.g.~transiting exoplanets, eclipsing binaries). + + Parameters + ---------- + periodic_event : `~astroplan.periodic.PeriodicEvent` or subclass + System on which to compute the phase. For example, the system + could be an eclipsing or non-eclipsing binary, or exoplanet system. + min : float (optional) + Minimum phase (inclusive) on interval [0, 1). Default is zero. + max : float (optional) + Maximum phase (inclusive) on interval [0, 1). Default is one. + + Examples + -------- + To constrain observations on orbital phases between 0.4 and 0.6: + + >>> from astroplan import PeriodicEvent + >>> from astropy.time import Time + >>> import astropy.units as u + >>> binary = PeriodicEvent(epoch=Time('2017-01-01 02:00'), period=1*u.day) + >>> constraint = PhaseConstraint(binary, min=0.4, max=0.6) + + The minimum and maximum phase must be described on the interval [0, 1). + To constrain observations on orbital phases between 0.6 and 1.2, for + example, you should subtract one from the second number: + + >>> constraint = PhaseConstraint(binary, min=0.6, max=0.2) """ def __init__(self, periodic_event, min=None, max=None): """ - Parameters - ---------- - periodic_event : `~astroplan.periodic.PeriodicEvent` or subclass - System on which to compute the phase. For example, the system - could be an eclipsing or non-eclipsing binary, or exoplanet system. - min : float (optional) - Minimum phase (inclusive) on interval [0, 1). Default is zero. - max : float (optional) - Maximum phase (inclusive) on interval [0, 1). Default is one. - - Examples - -------- - To constrain observations on orbital phases between 0.4 and 0.6: - - >>> from astroplan import PeriodicEvent - >>> from astropy.time import Time - >>> import astropy.units as u - >>> binary = PeriodicEvent(epoch=Time('2017-01-01 02:00'), period=1*u.day) - >>> constraint = PhaseConstraint(binary, min=0.4, max=0.6) - - The minimum and maximum phase must be described on the interval [0, 1). - To constrain observations on orbital phases between 0.6 and 1.2, for - example, you should subtract one from the second number: - - >>> constraint = PhaseConstraint(binary, min=0.6, max=0.2) + """ self.periodic_event = periodic_event if (min < 0) or (min > 1) or (max < 0) or (max > 1): diff --git a/astroplan/observer.py b/astroplan/observer.py index 0217ea6c..a86b4793 100644 --- a/astroplan/observer.py +++ b/astroplan/observer.py @@ -4,14 +4,16 @@ import sys import datetime import warnings + # Third-party + +import astropy.units as u +import numpy as np +import pytz from astropy.coordinates import (EarthLocation, SkyCoord, AltAz, get_sun, get_body, Angle, Longitude) -import astropy.units as u from astropy.time import Time from astropy.utils.exceptions import AstropyDeprecationWarning -import numpy as np -import pytz # Package from .exceptions import TargetNeverUpWarning, TargetAlwaysUpWarning @@ -29,7 +31,7 @@ def deprecation_wrap_module(mod, deprecated): """Return a wrapped object that warns about deprecated accesses""" deprecated = set(deprecated) - class DeprecateWrapper(object): + class DeprecateWrapper: def __getattr__(self, attr): if attr in deprecated: warnmsg = ("`MAGIC_TIME` will be deprecated in future versions " @@ -108,7 +110,7 @@ def _generate_24hr_grid(t0, start, end, n_grid_points, for_deriv=False): return t0 + time_grid -class Observer(object): +class Observer: """ A container class for information about an observer's location and diff --git a/astroplan/periodic.py b/astroplan/periodic.py index 74fb5105..0b92e8f3 100644 --- a/astroplan/periodic.py +++ b/astroplan/periodic.py @@ -6,7 +6,7 @@ __all__ = ['PeriodicEvent', 'EclipsingSystem'] -class PeriodicEvent(object): +class PeriodicEvent: """ A periodic event defined by an epoch and period. """ diff --git a/astroplan/setup_package.py b/astroplan/setup_package.py deleted file mode 100644 index 3073196f..00000000 --- a/astroplan/setup_package.py +++ /dev/null @@ -1,9 +0,0 @@ -# Licensed under a 3-clause BSD style license - see LICENSE.rst - - -def get_package_data(): - """Declare astroplan datafiles""" - pdata = dict() - pdata['astroplan.tests'] = ['coveragerc'] - pdata['astroplan.plots.tests'] = ['baseline_images/*.png'] - return pdata diff --git a/astroplan/target.py b/astroplan/target.py index c98bc860..e82c7e5e 100644 --- a/astroplan/target.py +++ b/astroplan/target.py @@ -16,7 +16,7 @@ __doctest_requires__ = {'FixedTarget.*': ['astropy.modeling.Hermite1D']} -class Target(object): +class Target: """ Abstract base class for target objects. @@ -272,7 +272,7 @@ def get_skycoord(targets): return SkyCoord(longitudes, latitudes, distances, frame=frame) -class SpecialObjectFlag(object): +class SpecialObjectFlag: """ Flag this object as a special non-fixed target, which has a ``get_*`` method within astropy (like the Sun or Moon) diff --git a/astroplan/tests/coveragerc b/astroplan/tests/coveragerc deleted file mode 100644 index bec7c291..00000000 --- a/astroplan/tests/coveragerc +++ /dev/null @@ -1,31 +0,0 @@ -[run] -source = {packagename} -omit = - {packagename}/_astropy_init* - {packagename}/conftest* - {packagename}/cython_version* - {packagename}/setup_package* - {packagename}/*/setup_package* - {packagename}/*/*/setup_package* - {packagename}/tests/* - {packagename}/*/tests/* - {packagename}/*/*/tests/* - {packagename}/version* - -[report] -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain about packages we have installed - except ImportError - - # Don't complain if tests don't hit assertions - raise AssertionError - raise NotImplementedError - - # Don't complain about script hooks - def main\(.*\): - - # Ignore branches that don't pertain to this version of Python - pragma: py{ignore_python_version} \ No newline at end of file diff --git a/conftest.py b/conftest.py new file mode 100644 index 00000000..bd125682 --- /dev/null +++ b/conftest.py @@ -0,0 +1,24 @@ +try: + from pytest_astropy_header.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS +except ImportError: # In case this plugin is not installed + PYTEST_HEADER_MODULES = {} + TESTED_VERSIONS = {} + +# This is to figure out the affiliated package version, rather than +# using Astropy's +try: + from astroplan import __version__ +except ImportError: + __version__ = 'dev' + +TESTED_VERSIONS["astroplan"] = __version__ + +# Define list of packages for which to display version numbers in the test log +PYTEST_HEADER_MODULES['astropy'] = 'astropy' +PYTEST_HEADER_MODULES['pytz'] = 'pytz' +PYTEST_HEADER_MODULES['pyephem'] = 'ephem' +PYTEST_HEADER_MODULES['matplotlib'] = 'matplotlib' +PYTEST_HEADER_MODULES['astroquery'] = 'astroquery' +PYTEST_HEADER_MODULES['pyvo'] = 'pyvo' +if "h5py" in PYTEST_HEADER_MODULES: + del PYTEST_HEADER_MODULES['h5py'] diff --git a/docs/Makefile b/docs/Makefile index fb03f26e..03886de1 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -129,5 +129,5 @@ linkcheck: "or in $(BUILDDIR)/linkcheck/output.txt." doctest: - @echo "Run 'python setup.py test' in the root directory to run doctests " \ + @echo "Run 'pytest' in the root directory to run doctests " \ @echo "in the documentation." diff --git a/docs/conf.py b/docs/conf.py index 9cb27f53..913c3046 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Licensed under a 3-clause BSD style license - see LICENSE.rst # -# Astropy documentation build configuration file. +# Astroplan documentation build configuration file. # # This file is execfile()d with the current directory set to its containing dir. # @@ -9,12 +9,12 @@ # # All configuration values have a default. Some values are defined in # the global Astropy configuration which is loaded here before anything else. -# See astropy.sphinx.conf for which values are set there. +# See astropy_sphinx.conf for which values are set there. -from configparser import ConfigParser import sys import datetime -from importlib import metadata + +import astroplan try: from sphinx_astropy.conf.v2 import * # noqa @@ -23,24 +23,13 @@ 'be installed') sys.exit(1) -# Get configuration information from setup.cfg -conf = ConfigParser() -conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')]) -setup_cfg = dict(conf.items('metadata')) - - # -- General configuration ---------------------------------------------------- -# By default, highlight as Python 3. -highlight_language = 'python3' - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.7' # Extend astropy intersphinx_mapping with packages we use here -intersphinx_mapping['astroquery'] = ('http://astroquery.readthedocs.io/en/latest/', None) +intersphinx_mapping['astroquery'] = ('http://astroquery.readthedocs.io/en/latest/', None) # noqa: F405 E501 # Exclude astropy intersphinx_mapping for unused packages -del intersphinx_mapping['h5py'] # noqa +del intersphinx_mapping['h5py'] # noqa: F405 # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -59,57 +48,31 @@ # -- Project information ------------------------------------------------------ # This does not *have* to match the package name, but typically does -project = setup_cfg['name'] -author = setup_cfg['author'] -copyright = '{0}, {1}'.format( - datetime.datetime.now().year, setup_cfg['author']) +project = "astroplan" +author = "Astroplan developers" +copyright = f"{datetime.datetime.now().year}, {author}" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # The full version, including alpha/beta/rc tags. -release = metadata.version(project) +release = astroplan.__version__ # The short X.Y version. version = ".".join(release.split(".")[:2]) # Only include dev docs in dev version. dev = "dev" in release - # -- Options for HTML output --------------------------------------------------- # A NOTE ON HTML THEMES -# The global astropy configuration uses a custom theme, 'bootstrap-astropy', -# which is installed along with astropy. A different theme can be used or -# the options for this theme can be modified by overriding some of the -# variables set in the global configuration. The variables set in the -# global configuration are listed below, commented out. - -# Add any paths that contain custom themes here, relative to this directory. -# To use a different custom theme, add the directory containing the theme. -#html_theme_path = [] - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. To override the custom theme, set this to the -# name of a builtin theme or the name of a custom theme in html_theme_path. -# html_theme = None - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = '' - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '' +# The global astropy configuration uses a custom theme +# which is installed along with astropy. # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -html_title = '{0} v{1}'.format(project, release) +html_title = f'{project} v{release}' # Output file base name for HTML help builder. htmlhelp_basename = project + 'doc' @@ -132,29 +95,10 @@ man_pages = [('index', project.lower(), project + u' Documentation', [author], 1)] - -# -- Options for the edit_on_github extension ---------------------------------- - -if setup_cfg.get('edit_on_github').lower() == 'true': - - extensions += ['sphinx_astropy.ext.edit_on_github'] - - edit_on_github_project = setup_cfg['github_project'] - edit_on_github_branch = "main" - - edit_on_github_source_root = "" - edit_on_github_doc_root = "docs" - -# Make appropriate substitutions to mock internet querying methods -# within the tests. -# Currently this is not needed because of the content of the tests, but we leave -# it here in case it's needed again in the future. BUT beware of: -# https://github.com/astropy/astroplan/issues/96 -#from astroplan.utils import _mock_remote_data -#_mock_remote_data() +# -- Add additional Sphinx extensions ----------------------------------------- # Add additional Sphinx extensions: -extensions += [ +extensions += [ # noqa: F405 'matplotlib.sphinxext.plot_directive', 'sphinx.ext.graphviz' ] @@ -199,25 +143,3 @@ # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. html_extra_path = ["robots.txt"] - -# -# Some warnings are impossible to suppress, and you can list specific references -# that should be ignored in a nitpick-exceptions file which should be inside -# the docs/ directory. The format of the file should be: -# -# -# -# for example: -# -# py:class astropy.io.votable.tree.Element -# py:class astropy.io.votable.tree.SimpleElement -# py:class astropy.io.votable.tree.SimpleElementWithContent -# -# Uncomment the following lines to enable the exceptions: -# -# for line in open('nitpick-exceptions'): -# if line.strip() == "" or line.startswith("#"): -# continue -# dtype, target = line.split(None, 1) -# target = target.strip() -# nitpick_ignore.append((dtype, str(target))) diff --git a/docs/installation.rst b/docs/installation.rst index 43fffb67..8413a505 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -9,15 +9,11 @@ Installation Requirements ============ -**astroplan** works on Linux, Mac OS X and Windows. -It requires Python 3.7+ as well as numpy, astropy, and pytz. +**astroplan** works on Linux, Mac OS X, and Windows. +It requires Python 3.11+ as well as numpy, astropy, and pytz. Additional features are available when you install `Matplotlib`_ and `astroquery`_. -First-time Python users may want to consider an all-in-one Python installation -package, such as the `Anaconda Python Distribution -`_ which provides all of the above dependencies. - Installation ============ @@ -59,6 +55,6 @@ More ==== astroplan follows `astropy `__'s guidelines for affiliated packages--installation -and testing for the two are quite similar! Please see astropy's -`installation page `_ +and testing for the two are quite similar! Please see +:ref:`astropy's installation page ` for more information. diff --git a/pyproject.toml b/pyproject.toml index 254fa99b..d186d40c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,4 +1,128 @@ +[project] +name = "astroplan" +authors = [ + { name = "Astroplan developers", email = "astropy-dev@googlegroups.com" } +] +license = { text = "BSD-3-Clause" } +description = "Observation planning package for astronomers" +classifiers = [ + "Intended Audience :: Science/Research", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Scientific/Engineering :: Astronomy", + "Topic :: Scientific/Engineering :: Physics", +] +keywords = [ + "astronomy", + "astrophysics", + "observation", + "planning", + "science", +] +dynamic = [ + "version" +] +requires-python = ">=3.11" +dependencies = [ + "numpy>=1.23.2", + "astropy>=6.0", + "pytz" +] + +[project.optional-dependencies] +all = [ + "matplotlib>=3.6.0", + "astroquery" +] +test = [ + "pytest-astropy", + "pytest-mpl" +] +docs = [ + "astroplan[all]", + "sphinx-astropy[confv2]", + "sphinx-rtd-theme" +] +plotting = [ + "astroplan[all]" +] + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[project.urls] +Homepage = "https://github.com/astropy/astroplan" +Documentation = "https://astroplan.readthedocs.io/en/latest/" + +[tool.setuptools] +zip-safe = false +include-package-data = true +license-files = ["LICENSE.rst", "licenses/*.rst"] + +[tool.setuptools.packages.find] +namespaces = true + +[tool.setuptools.package-data] +"astroplan.plots.tests" = [ + "baseline_images/*.png", +] + [build-system] requires = ["setuptools", "setuptools_scm"] -build-backend = 'setuptools.build_meta' +build-backend = "setuptools.build_meta" + +[tool.pytest.ini_options] +minversion = "7.0" +testpaths = [ + "astroplan", + "docs", +] +norecursedirs = [ + "build", + "docs[\\/]_build", +] +astropy_header = true +doctest_plus = "enabled" +text_file_format = "rst" +addopts = "--doctest-rst" +xfail_strict = true +filterwarnings = [ + "error", + "ignore:numpy\\.ufunc size changed:RuntimeWarning", + "ignore:numpy\\.ndarray size changed:RuntimeWarning", + # deprecated in Matplotlib 3.9 and will be removed in 3.11. Use plot instead. + "ignore:The plot_date function was deprecated", +] + +[tool.coverage.run] +omit = [ + "astroplan/conftest.py", + "astroplan/tests/*", + "astroplan/*/tests/*", + "astroplan/version*", + "*/astroplan/conftest.py", + "*/astroplan/tests/*", + "*/astroplan/*/tests/*", + "*/astroplan/version*", +] + +[tool.coverage.report] +exclude_lines = [ + # Have to re-enable the standard pragma + "pragma: no cover", + # Don't complain about packages we have installed + "except ImportError", + # Don't complain if tests don't hit assertions + "raise AssertionError", + "raise NotImplementedError", + # Don't complain about script hooks + "def main\\(.*\\):", + # 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/setup.cfg b/setup.cfg deleted file mode 100644 index 3cfdd4b2..00000000 --- a/setup.cfg +++ /dev/null @@ -1,98 +0,0 @@ -[metadata] -name = astroplan -author = Astroplan developers -author_email = astropy-dev@googlegroups.com -license = BSD -license_file = LICENSE.rst -url = https://github.com/astropy/astroplan -description = Observation planning package for astronomers -long_description = file: README.rst -long_description_content_type = text/x-rst -edit_on_github = False -github_project = astropy/astroplan - -[options] -zip_safe = False -packages = find: -python_requires = >=3.7 -setup_requires = setuptools_scm -install_requires = - numpy>=1.17 - astropy>=4 - pytz - -[options.extras_require] -all = - matplotlib>=1.4 - astroquery -test = - pytest-astropy - pytest-mpl -docs = - sphinx-astropy[confv2] - sphinx-rtd-theme - matplotlib>=1.4 - astroquery -plotting = - astroquery - matplotlib>=1.4 - -[options.package_data] -astroplan = data/* - -[tool:pytest] -testpaths = "astroplan" "docs" -astropy_header = true -doctest_plus = enabled -text_file_format = rst -addopts = --doctest-rst --doctest-ignore-import-errors -norecursedirs = build docs/_build -filterwarnings = - error - ignore:numpy\.ndarray size changed:RuntimeWarning - ignore:numpy\.ufunc size changed:RuntimeWarning - # Can remove ignore when you bump astropy minversion high enough - ignore:distutils Version classes are deprecated:DeprecationWarning - # deprecated in Matplotlib 3.9 and will be removed in 3.11. Use plot instead. - ignore:The plot_date function was deprecated - -[coverage:run] -omit = - astroplan/_astropy_init* - astroplan/conftest.py - astroplan/*setup_package* - astroplan/tests/* - astroplan/*/tests/* - astroplan/extern/* - astroplan/version* - */astroplan/_astropy_init* - */astroplan/conftest.py - */astroplan/*setup_package* - */astroplan/tests/* - */astroplan/*/tests/* - */astroplan/extern/* - */astroplan/version* - -[coverage:report] -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - # Don't complain about packages we have installed - except ImportError - # Don't complain if tests don't hit assertions - raise AssertionError - raise NotImplementedError - # Don't complain about script hooks - def main\(.*\): - # 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_ - -[flake8] -exclude = _astropy_init.py,extern,__init__.py -max-line-length = 100 - -[pycodestyle] -exclude = _astropy_init.py,extern,__init__.py -max-line-length = 100 diff --git a/setup.py b/setup.py deleted file mode 100755 index ff4f71e9..00000000 --- a/setup.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python -# Licensed under a 3-clause BSD style license - see LICENSE.rst - -# NOTE: The configuration for the package, including the name, version, and -# other information are set in the setup.cfg file. - -import os -import sys - -from setuptools import setup - -# First provide helpful messages if contributors try and run legacy commands -# for tests or docs. - -TEST_HELP = """ -Note: running tests is no longer done using 'python setup.py test'. Instead -you will need to run: - 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 .[test] - 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 -You can also build the documentation with Sphinx directly using:: - pip install -e .[docs] - cd docs - make html -For more information, see: - http://docs.astropy.org/en/latest/install.html#builddocs -""" - -if 'build_docs' in sys.argv or 'build_sphinx' in sys.argv: - print(DOCS_HELP) - sys.exit(1) - -VERSION_TEMPLATE = """ -# Note that we need to fall back to the hard-coded version if either -# setuptools_scm can't be imported or setuptools_scm can't determine the -# version, so we catch the generic 'Exception'. -try: - from setuptools_scm import get_version - version = get_version(root='..', relative_to=__file__) -except Exception: - version = '{version}' -""".lstrip() - -setup(use_scm_version={'write_to': os.path.join('astroplan', 'version.py'), - 'write_to_template': VERSION_TEMPLATE}) diff --git a/tox.ini b/tox.ini index a3d93881..c88e33ca 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,6 @@ [tox] envlist = - py{310,311,312}-test{,-alldeps,-devdeps}{,-cov} - py{310,311,312}-test-numpy{123,124,125} - py{310,311,312}-test-astropy{lts,53,60} + py{311,312,313}-test{,-alldeps,-devdeps,-oldestdeps}{,-cov} build_docs linkcheck codestyle @@ -35,34 +33,18 @@ description = devdeps: with the latest developer version of key dependencies oldestdeps: with the oldest supported version of key dependencies cov: and test coverage - numpy116: with numpy 1.16.* - numpy117: with numpy 1.17.* - numpy118: with numpy 1.18.* - astropy30: with astropy 3.0.* - astropy40: with astropy 4.0.* - astropylts: with the latest astropy LTS - astropy41: with astropy 4.1.* - astropy42: with astropy 4.2.* # The following provides some specific pinnings for key packages deps = - cov: coverage - numpy116: numpy==1.16.* - numpy117: numpy==1.17.* - numpy118: numpy==1.18.* - numpy119: numpy==1.19.* - - astropy30: astropy==3.0.* - astropy40: astropy==4.0.* - astropylts: astropy==4.0.* - astropy41: astropy==4.1.* - astropy42: astropy==4.2.* - devdeps: numpy>=0.0.dev0 devdeps: astropy>=0.0.dev0 -# The following indicates which extras_require from setup.cfg will be installed + oldestdeps: numpy==1.23.2 + oldestdeps: matplotlib==3.6.0 + oldestdeps: astropy==6.0.* + +# The following indicates which optional dependencies will be installed extras = test alldeps: all @@ -70,7 +52,7 @@ extras = commands = pip freeze !cov: pytest --pyargs astroplan {toxinidir}/docs {posargs} - cov: pytest --pyargs astroplan {toxinidir}/docs --cov astroplan --cov-config={toxinidir}/setup.cfg {posargs} + cov: pytest --pyargs astroplan {toxinidir}/docs --cov astroplan --cov-config={toxinidir}/pyproject.toml {posargs} cov: coverage xml -o {toxinidir}/coverage.xml [testenv:build_docs]