From 6841a1b38cd8bf65875807840a54f931c6b6f2e8 Mon Sep 17 00:00:00 2001 From: Samuel Bennett Date: Wed, 22 May 2024 19:19:37 +0100 Subject: [PATCH] Register template (#116) * Registers package with the SunPy template * Refines pyproject.toml * Update .coveragerc Co-authored-by: Nabil Freij * Update .cruft.json Co-authored-by: Nabil Freij * Update .github/workflows/ci.yml Co-authored-by: Nabil Freij * Update .ruff.toml Co-authored-by: Nabil Freij * Update pyproject.toml Co-authored-by: Nabil Freij * Update .isort.cfg Co-authored-by: Nabil Freij * Update pytest.ini Co-authored-by: Nabil Freij * Update .pre-commit-config.yaml Co-authored-by: Nabil Freij * Removes importlib-resources * Update python minimum version * Update template --------- Co-authored-by: Nabil Freij --- .codecov.yaml | 11 + .codespellrc | 14 ++ .coveragerc | 30 +++ .cruft.json | 31 +++ .flake8 | 27 +++ .github/workflows/ci.yml | 55 +++-- .github/workflows/sub_package_update.yml | 84 +++++++ .gitignore | 269 +++++++++++++++++++++-- .pre-commit-config.yaml | 21 +- .readthedocs.yaml | 12 +- .ruff.toml | 89 ++++++++ LICENSE | 2 +- MANIFEST.in | 11 + README.rst | 93 +------- docs/conf.py | 46 ++-- docs/index.rst | 40 +++- licenses/LICENSE.rst | 22 ++ licenses/README.rst | 9 + pyproject.toml | 126 ++++------- pytest.ini | 34 +++ setup.cfg | 60 ----- setup.py | 4 + sunpy_soar/_dev/scm_version.py | 8 +- sunpy_soar/attrs.py | 17 +- sunpy_soar/client.py | 11 +- sunpy_soar/conftest.py | 13 ++ sunpy_soar/data/README.rst | 6 + sunpy_soar/tests/__init__.py | 3 + sunpy_soar/tests/test_sunpy_soar.py | 8 +- tools/update_data.py | 28 ++- tox.ini | 72 ++++-- 31 files changed, 908 insertions(+), 348 deletions(-) create mode 100644 .codecov.yaml create mode 100644 .codespellrc create mode 100644 .coveragerc create mode 100644 .cruft.json create mode 100644 .flake8 create mode 100644 .github/workflows/sub_package_update.yml create mode 100644 .ruff.toml create mode 100644 MANIFEST.in create mode 100644 licenses/LICENSE.rst create mode 100644 licenses/README.rst create mode 100644 pytest.ini delete mode 100644 setup.cfg create mode 100755 setup.py create mode 100644 sunpy_soar/conftest.py create mode 100644 sunpy_soar/data/README.rst diff --git a/.codecov.yaml b/.codecov.yaml new file mode 100644 index 0000000..8fe09b7 --- /dev/null +++ b/.codecov.yaml @@ -0,0 +1,11 @@ +comment: off +coverage: + status: + project: + default: + threshold: 0.2% + +codecov: + require_ci_to_pass: false + notify: + wait_for_ci: true diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 0000000..7fd7041 --- /dev/null +++ b/.codespellrc @@ -0,0 +1,14 @@ +[codespell] +skip = *.asdf,*.fits,*.fts,*.header,*.json,*.xsh,*cache*,*egg*,*extern*,.git,.idea,.tox,_build,*truncated,*.svg,.asv_env,.history +ignore-words-list = + alog, + nd, + nin, + observ, + ot, + te, + upto, + afile, + precessed, + precess, + soop diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..24afd91 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,30 @@ +[run] +omit = + sunpy_soar/conftest.py + sunpy_soar/*setup_package* + sunpy_soar/extern/* + sunpy_soar/version* + */sunpy_soar/conftest.py + */sunpy_soar/*setup_package* + */sunpy_soar/extern/* + */sunpy_soar/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} + # Don't complain about IPython completion helper + def _ipython_key_completions_ + # typing.TYPE_CHECKING is False at runtime + if TYPE_CHECKING: + # Ignore typing overloads + @overload diff --git a/.cruft.json b/.cruft.json new file mode 100644 index 0000000..e67c145 --- /dev/null +++ b/.cruft.json @@ -0,0 +1,31 @@ +{ + "template": "https://github.com/sunpy/package-template", + "commit": "1eff2ed0ff32c123e64b5faacf7c505362cfbb92", + "checkout": null, + "context": { + "cookiecutter": { + "package_name": "sunpy-soar", + "module_name": "sunpy_soar", + "short_description": "A sunpy FIDO plugin for accessing data in the Solar Orbiter Archive (SOAR).", + "author_name": "The SunPy Community", + "author_email": "sunpy@googlegroups.com", + "project_url": "https://sunpy.org", + "license": "BSD 2-Clause", + "minimum_python_version": "3.10", + "use_compiled_extensions": "n", + "enable_dynamic_dev_versions": "y", + "include_example_code": "n", + "include_cruft_update_github_workflow": "y", + "_sphinx_theme": "alabaster", + "_parent_project": "", + "_install_requires": "", + "_copy_without_render": [ + "docs/_templates", + "docs/_static", + ".github/workflows/sub_package_update.yml" + ], + "_template": "https://github.com/sunpy/package-template" + } + }, + "directory": null +} diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..f835b67 --- /dev/null +++ b/.flake8 @@ -0,0 +1,27 @@ +[flake8] +ignore = + # missing-whitespace-around-operator + E225 + # missing-whitespace-around-arithmetic-operator + E226 + # line-too-long + E501 + # unused-import + F401 + # undefined-local-with-import-star + F403 + # redefined-while-unused + F811 + # Line break occurred before a binary operator + W503, + # Line break occurred after a binary operator + W504 +max-line-length = 110 +exclude = + .git + __pycache__ + docs/conf.py + build + sunpy_soar/__init__.py +rst-directives = + plot diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b996d4..d4b66b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,12 +28,24 @@ jobs: toxdeps: tox-pypi-filter posargs: -n auto envs: | - - linux: py311 + - linux: py312 secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + sdist_verify: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - run: python -m pip install -U --user build + - run: python -m build . --sdist + - run: python -m pip install -U --user twine + - run: python -m twine check dist/* + test: - needs: [core] + needs: [core, sdist_verify] uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main with: submodules: false @@ -41,9 +53,9 @@ jobs: toxdeps: tox-pypi-filter posargs: -n auto envs: | - - windows: py310 - - macos: py39 - - linux: py311-devdeps + - windows: py311 + - macos: py310 + - linux: py310-oldestdeps secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} @@ -51,7 +63,7 @@ jobs: needs: [core] uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main with: - default_python: '3.9' + default_python: '3.12' submodules: false pytest: false toxdeps: tox-pypi-filter @@ -66,13 +78,30 @@ jobs: envs: | - linux: build_docs - publish: - needs: [test] - uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@main + cron: + if: | + github.event_name == 'workflow_dispatch' || ( + github.event_name == 'pull_request' && + contains(github.event.pull_request.labels.*.name, 'Run cron CI') + ) + uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main with: - python-version: '3.9' - test_extras: 'tests' - test_command: 'pytest -p no:warnings --pyargs sunpy_soar' + default_python: '3.12' submodules: false + coverage: codecov + toxdeps: tox-pypi-filter + envs: | + - linux: py312-devdeps secrets: - pypi_token: ${{ secrets.pypi_token }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + publish_pure: + needs: [test, docs] + uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@main + with: + python-version: '3.12' + test_extras: 'tests' + test_command: 'pytest -p no:warnings --doctest-rst --pyargs sunpy_soar' + submodules: false + secrets: + pypi_token: ${{ secrets.pypi_token }} diff --git a/.github/workflows/sub_package_update.yml b/.github/workflows/sub_package_update.yml new file mode 100644 index 0000000..94a9e7e --- /dev/null +++ b/.github/workflows/sub_package_update.yml @@ -0,0 +1,84 @@ +# This template is taken from the cruft example code, for further information please see: +# https://cruft.github.io/cruft/#automating-updates-with-github-actions +name: Automatic Update from package template +permissions: + contents: write + pull-requests: write + +on: + # Allow manual runs through the web UI + workflow_dispatch: + schedule: + # ┌───────── minute (0 - 59) + # │ ┌───────── hour (0 - 23) + # │ │ ┌───────── day of the month (1 - 31) + # │ │ │ ┌───────── month (1 - 12 or JAN-DEC) + # │ │ │ │ ┌───────── day of the week (0 - 6 or SUN-SAT) + - cron: '0 7 * * 1' # Every Monday at 7am UTC + +jobs: + update: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + include: + - add-paths: . + body: apply the changes to this repo. + branch: cruft/update + commit-message: "Automatic package template update" + title: Updates from the package template + - add-paths: .cruft.json + body: reject these changes for this repo. + branch: cruft/reject + commit-message: "Reject this package template update" + title: Reject new updates from package template + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install Cruft + run: python -m pip install cruft + + - name: Check if update is available + continue-on-error: false + id: check + run: | + CHANGES=0 + if [ -f .cruft.json ]; then + if ! cruft check; then + CHANGES=1 + fi + else + echo "No .cruft.json file" + fi + + echo "has_changes=$CHANGES" >> "$GITHUB_OUTPUT" + + - name: Run update if available + if: steps.check.outputs.has_changes == '1' + run: | + git config --global user.email "${{ github.actor }}@users.noreply.github.com" + git config --global user.name "${{ github.actor }}" + + cruft update --skip-apply-ask --refresh-private-variables + git restore --staged . + + - name: Create pull request + if: steps.check.outputs.has_changes == '1' + uses: peter-evans/create-pull-request@v6 + with: + token: ${{ secrets.GITHUB_TOKEN }} + add-paths: ${{ matrix.add-paths }} + commit-message: ${{ matrix.commit-message }} + branch: ${{ matrix.branch }} + delete-branch: true + branch-suffix: timestamp + title: ${{ matrix.title }} + body: | + This is an autogenerated PR, which will ${{ matrix.body }}. + [Cruft](https://cruft.github.io/cruft/) has detected updates from the Package Template diff --git a/.gitignore b/.gitignore index 1808b00..2980c98 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,261 @@ -*.DS_Store -*.egg-info +### Python: https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore -docs/_build -docs/api -docs/auto_examples -*.coverage* +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class +tmp/ -__pycache__ -.eggs/* -dist/* -.history -.hypothesis/ +# C extensions +*.so -.vscode -.tox +# Distribution / packaging +.Python +pip-wheel-metadata/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST sunpy_soar/_version.py +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ +# automodapi +docs/api + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# Pyre type checker +.pyre/ + +# IDE +# PyCharm +.idea + +# Spyder project settings +.spyderproject +.spyproject + +### VScode: https://raw.githubusercontent.com/github/gitignore/master/Global/VisualStudioCode.gitignore +.vscode/* +.vs/* + +### https://raw.github.com/github/gitignore/master/Global/OSX.gitignore +.DS_Store +.AppleDouble +.LSOverride + +# Icon must ends with two \r. +Icon + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +### Linux: https://raw.githubusercontent.com/github/gitignore/master/Global/Linux.gitignore +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# pytype static type analyzer +.pytype/ + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Windows: https://raw.githubusercontent.com/github/gitignore/master/Global/Windows.gitignore + +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### Extra Python Items and SunPy Specific +docs/whatsnew/latest_changelog.txt +examples/**/*.csv +figure_test_images* +tags +baseline + +# Release script +.github_cache + +# Misc Stuff +.history +*.orig .tmp +node_modules/ +package-lock.json +package.json +.prettierrc + +# Log files generated by 'vagrant up' +*.log diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d613606..785b230 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,4 @@ +exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" repos: - repo: https://github.com/PyCQA/docformatter rev: v1.7.5 @@ -11,31 +12,19 @@ repos: args: ['--in-place', '--remove-all-unused-imports', '--remove-unused-variable'] exclude: ".*(.fits|.fts|.fit|.txt|tca.*|extern.*|.rst|.md|docs/conf.py)$" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: 'v0.3.5' + rev: 'v0.4.4' hooks: - id: ruff - args: ['--fix'] - - repo: https://github.com/psf/black - rev: 24.3.0 - hooks: - - id: black - exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" - - repo: https://github.com/PyCQA/isort - rev: 5.13.2 - hooks: - - id: isort - exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" + args: ["--fix", "--unsafe-fixes"] + - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-ast - id: check-case-conflict - id: trailing-whitespace - exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" - id: mixed-line-ending - exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" - id: end-of-file-fixer - exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" - id: check-yaml - id: debug-statements - repo: https://github.com/codespell-project/codespell diff --git a/.readthedocs.yaml b/.readthedocs.yaml index f9d4e27..790abab 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -18,10 +18,12 @@ sphinx: configuration: docs/conf.py fail_on_warning: false +formats: + - htmlzip + python: - install: - - method: pip - extra_requirements: - - all + install: + - method: pip + extra_requirements: - docs - path: . + path: . diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 0000000..4737020 --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,89 @@ +# Allow unused variables when underscore-prefixed. +lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" +target-version = "py310" +line-length = 120 +exclude=[ + ".git,", + "__pycache__", + "build", + "tools/**", +] +lint.select = [ + "A", + "ARG", + "ASYNC", + "B", + "BLE", + "C4", +# "C90", + "COM", +# "D", + "DTZ", + "E", + "EM", + "ERA", + "EXE", + "F", + "FBT", + "FLY", +# "FURB", + "G", + "I", + "ICN", + "INP", + "INT", + "ISC", + "LOG", +# "N", + "NPY", + "PERF", + "PGH", + "PIE", +# "PL", + "PLE", + "PT", + "PTH", + "PYI", + "Q", + "RET", + "RSE", + "RUF", +# "S", + "SIM", + "SLF", + "SLOT", + "T10", + "T20", + "TCH", + "TID", + "TRIO", + "TRY", + "UP", + "W", + "YTT", +] +lint.extend-ignore = [ + # TODO: Fix in future + "E501", # Line too long + "E741", # Ambiguous variable name + "FBT002", # Bool arg + "COM812", # May cause conflicts when used with the formatter + "ISC001", # May cause conflicts when used with the formatter +] + +[lint.per-file-ignores] +"examples/*.py" = [ + "INP001", # examples is part of an implicit namespace package + "T201", # We need print in our examples +] +"docs/conf.py" = [ + "INP001", # conf.py is part of an implicit namespace package +] + +[lint.pydocstyle] +convention = "numpy" + +[format] +docstring-code-format = true +indent-style = "space" +quote-style = "double" diff --git a/LICENSE b/LICENSE index a318769..a517f31 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021-2023 David Stansby and The SunPy Community All rights reserved. +Copyright (c) 2021-2024 David Stansby and The SunPy Community All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..66904b2 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,11 @@ +# Exclude specific files +# All files which are tracked by git and not explicitly excluded here are included by setuptools_scm +# Prune folders +prune build +prune docs/_build +prune docs/api +global-exclude *.pyc *.o + +# This subpackage is only used in development checkouts +# and should not be included in built tarballs +prune sunpy_soar/_dev diff --git a/README.rst b/README.rst index 5deaad2..4b7bf5d 100644 --- a/README.rst +++ b/README.rst @@ -12,95 +12,6 @@ :alt: Code coverage -A sunpy Fido plugin for accessing data in the Solar Orbiter Archive (SOAR). See the `documentation `_ for installation instructions and for some examples. +A sunpy Fido plugin for accessing data in the Solar Orbiter Archive (SOAR). -.. note:: - - With the updates to the SOAR, the product names now need to be lowercase. - This is fixed with the latest release of sunpy-soar (v1.9), so you will need to update if you are having issues finding data. - - -Installation ------------- - -``sunpy-soar`` requires ``python >= 3.9`` and ``sunpy >= 5.0``. -Currently it can only be installed from PyPI using: - -.. code-block:: bash - - pip install sunpy-soar - -or conda using - -.. code-block:: bash - - conda install -c conda-forge sunpy-soar - -Example usage -------------- - -The code below gives an example of how to search and download Solar Orbiter data using ``sunpy.net.Fido``: - -.. code-block:: python - - # Importing sunpy_soar registers the client with sunpy - import sunpy_soar - from sunpy.net import Fido - import sunpy.net.attrs as a - - # Create search attributes - instrument = a.Instrument('EUI') - time = a.Time('2021-02-01', '2021-02-02') - level = a.Level(1) - product = a.soar.Product('EUI-FSI174-IMAGE') - - # Do search - result = Fido.search(instrument & time & level & product) - print(result) - - # Download files - files = Fido.fetch(result) - print(files) - -Available search attributes ---------------------------- - -The easiest way to access search attributes is using ``import sunpy.net.attrs as a``. -When constructing a search for SOAR ``a.Time`` must be provided. -Other search attributes can be used too - ``sunpy-soar`` recognises the following: - -- ``a.Instrument`` -- ``a.Level`` - one of ``L0, L1, L2, L3, LL01, LL02, LL03`` -- ``a.soar.Product`` - -The third ``near`` argument to ``a.Time`` is not currently supported - you will have to manually filter the results if you want to find the one closest to a given time. - -``sunpy-soar`` and the VSO -========================== - -``sunpy-soar`` queries the official repository of Solar Orbiter data, the SOAR. -The Virtual Solar Observatory (VSO) as of writing (September 2022) mirrors a subset of the Solar Orbiter archive alongside many other solar physics data sources. -The VSO allows data from multiple missions/observatories to be easily queried in one go, but users should be aware that the VSO is not the official repository for Solar Orbiter data and does not currently (as of September 2022) provide a comprehensive listing of all available Solar Orbiter data. - -Getting Help -============ - -For more information or to ask questions about ``sunpy-soar`` or any other SunPy library, check out: - -- `sunpy-soar documentation `__ -- `SunPy Chat`_ -- `SunPy mailing list `__ -- `SunPy Community forum `__ - -Contributing -============ - -If you would like to get involved, start by joining the `SunPy Chat`_ and check out our `Newcomers' guide `__. -This will walk you through getting set up for contributing. - -Code of Conduct -=============== - -When you are interacting with the SunPy community you are asked to follow our `Code of Conduct `__. - -.. _SunPy Chat: https://app.element.io/#/room/#sunpy:openastronomy.org +See the `documentation `_ for installation instructions, examples, how to get help and how to contribute. diff --git a/docs/conf.py b/docs/conf.py index 3e8ecd0..809048f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,20 +1,22 @@ # Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config # -- Project information ----------------------------------------------------- - +import datetime from pathlib import Path -from datetime import datetime from sunpy_soar import __version__ project = "sunpy-soar" -copyright = f"{datetime.now().year}, The SunPy Community" # NOQA: A001 +copyright = f"{datetime.datetime.now().year}, The SunPy Community" # NOQA: A001, DTZ005 author = "The SunPy Community" release = __version__ is_development = ".dev" in __version__ # -- General configuration --------------------------------------------------- - extensions = [ "sphinx_automodapi.automodapi", "sphinx_automodapi.smart_resolver", @@ -30,7 +32,6 @@ "sphinx.ext.viewcode", "sphinx_copybutton", ] - exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] source_suffix = ".rst" master_doc = "index" @@ -39,19 +40,29 @@ napoleon_google_docstring = False # -- Options for intersphinx extension --------------------------------------- - intersphinx_mapping = { - "python": ("https://docs.python.org/3/", (None, "http://data.astropy.org/intersphinx/python3.inv")), - "numpy": ("https://docs.scipy.org/doc/numpy/", (None, "http://data.astropy.org/intersphinx/numpy.inv")), - "scipy": ("https://docs.scipy.org/doc/scipy/reference/", (None, "http://data.astropy.org/intersphinx/scipy.inv")), - "matplotlib": ("https://matplotlib.org/", (None, "http://data.astropy.org/intersphinx/matplotlib.inv")), + "python": ( + "https://docs.python.org/3/", + (None, "http://data.astropy.org/intersphinx/python3.inv"), + ), + "numpy": ( + "https://docs.scipy.org/doc/numpy/", + (None, "http://data.astropy.org/intersphinx/numpy.inv"), + ), + "scipy": ( + "https://docs.scipy.org/doc/scipy/reference/", + (None, "http://data.astropy.org/intersphinx/scipy.inv"), + ), + "matplotlib": ( + "https://matplotlib.org/", + (None, "http://data.astropy.org/intersphinx/matplotlib.inv"), + ), "astropy": ("http://docs.astropy.org/en/stable/", None), "sunpy": ("https://docs.sunpy.org/en/stable/", None), "parfive": ("https://parfive.readthedocs.io/en/stable/", None), } # -- Options for HTML output ------------------------------------------------- - html_theme = "sunpy" graphviz_output_format = "svg" graphviz_dot_args = [ @@ -72,9 +83,10 @@ nitpicky = True # This is not used. See docs/nitpick-exceptions file for the actual listing. nitpick_ignore = [] -for line in Path("nitpick-exceptions").open(): - if line.strip() == "" or line.startswith("#"): - continue - dtype, target = line.split(None, 1) - target = target.strip() - nitpick_ignore.append((dtype, target)) +with Path("nitpick-exceptions").open() as f: + for line in f.readlines(): + if line.strip() == "" or line.startswith("#"): + continue + dtype, target = line.split(None, 1) + target = target.strip() + nitpick_ignore.append((dtype, target)) diff --git a/docs/index.rst b/docs/index.rst index 6971954..86cd7a2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,7 +2,7 @@ ``sunpy-soar`` Documentation **************************** -This is the documentation for sunpy-soar. +A sunpy Fido plugin for accessing data in the Solar Orbiter Archive (SOAR). .. toctree:: :maxdepth: 1 @@ -17,13 +17,13 @@ Currently it can only be installed from PyPI using: .. code-block:: bash - pip install sunpy-soar + pip install sunpy_soar or conda using .. code-block:: bash - conda install -c conda-forge sunpy-soar + conda install -c conda-forge sunpy_soar Example ======= @@ -46,10 +46,34 @@ The code below gives an example of how to search and download Solar Orbiter data # Do search >>> result = Fido.search(instrument & time & level & product) >>> print(result) + Results from 1 Provider: + + 43 Results from the SOARClient: + + Instrument Data product Level Start time End time Filesize SOOP Name + Mbyte + ---------- ---------------- ----- ----------------------- ----------------------- -------- --------- + EUI eui-fsi174-image L1 2021-02-01 00:45:12.228 2021-02-01 00:45:22.228 3.393 none + EUI eui-fsi174-image L1 2021-02-01 01:15:12.232 2021-02-01 01:15:22.232 0.418 none + EUI eui-fsi174-image L1 2021-02-01 01:45:12.237 2021-02-01 01:45:22.237 0.406 none + EUI eui-fsi174-image L1 2021-02-01 02:15:12.238 2021-02-01 02:15:22.238 3.352 none + EUI eui-fsi174-image L1 2021-02-01 02:45:12.241 2021-02-01 02:45:22.241 0.406 none + EUI eui-fsi174-image L1 2021-02-01 03:15:12.244 2021-02-01 03:15:22.244 0.406 none + ... ... ... ... ... ... ... + EUI eui-fsi174-image L1 2021-02-01 20:44:52.224 2021-02-01 20:45:02.224 0.409 none + EUI eui-fsi174-image L1 2021-02-01 21:15:12.227 2021-02-01 21:15:22.227 3.387 none + EUI eui-fsi174-image L1 2021-02-01 21:45:12.230 2021-02-01 21:45:22.230 0.412 none + EUI eui-fsi174-image L1 2021-02-01 22:15:12.233 2021-02-01 22:15:22.233 0.415 none + EUI eui-fsi174-image L1 2021-02-01 22:44:52.236 2021-02-01 22:45:02.236 0.423 none + EUI eui-fsi174-image L1 2021-02-01 23:15:12.239 2021-02-01 23:15:22.239 3.459 none + EUI eui-fsi174-image L1 2021-02-01 23:45:12.242 2021-02-01 23:45:22.242 0.415 none + Length = 43 rows + + # Download files - >>> files = Fido.fetch(result) - >>> print(files) + >>> files = Fido.fetch(result) # doctest: +SKIP + >>> print(files) # doctest: +SKIP Available search attributes =========================== @@ -74,12 +98,12 @@ The VSO allows data from multiple missions/observatories to be easily queried in Getting Help ============ -For more information or to ask questions about ``sunpy-soar`` or any other SunPy library, check out: +For more information or to ask questions about ``sunpy-soar`` or any other SunPy Project library, check out: - `sunpy-soar documentation `__ -- `SunPy Chat`_ +- `SunPy chat`_ - `SunPy mailing list `__ -- `SunPy Community forum `__ +- `SunPy community forum `__ Contributing ============ diff --git a/licenses/LICENSE.rst b/licenses/LICENSE.rst new file mode 100644 index 0000000..8fcd399 --- /dev/null +++ b/licenses/LICENSE.rst @@ -0,0 +1,22 @@ +Copyright (c) 2024, The SunPy Community + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/README.rst b/licenses/README.rst new file mode 100644 index 0000000..67b82f6 --- /dev/null +++ b/licenses/README.rst @@ -0,0 +1,9 @@ +Licenses +======== + +This directory holds license and credit information for the package, +works the package is derived from, and/or datasets. + +Ensure that you pick a package licence which is in this folder and it matches +the one mentioned in the top level README.rst file. If you are using the +pre-rendered version of this template check for the word 'Other' in the README. diff --git a/pyproject.toml b/pyproject.toml index 691fbed..e85090e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,94 +1,58 @@ [build-system] -requires = ["setuptools>=45", "setuptools_scm[toml]>=6.2"] +requires = [ + "setuptools>=62.1", + "setuptools_scm[toml]>=6.2", + "wheel", +] build-backend = "setuptools.build_meta" -[tool.setuptools_scm] -write_to = "sunpy_soar/_version.py" - -[tool.black] -line-length = 120 -target-version = ['py39'] - -[tool.isort] -profile = "black" -line_length = 120 -length_sort = "False" -length_sort_sections = "stdlib" - -[tool.ruff] -# Allow unused variables when underscore-prefixed. -dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" -target-version = "py39" -line-length = 120 -exclude=[ - ".git,", - "__pycache__", - "build", - "tools/**", +[project] +name = "sunpy_soar" +description = "A sunpy FIDO plugin for accessing data in the Solar Orbiter Archive (SOAR)." +requires-python = ">=3.10" +readme = { file = "README.rst", content-type = "text/x-rst" } +license = { file = "licenses/LICENSE.rst" } +authors = [ + { name = "David Stansby"}, + { name = "The Sunpy Community", email = "sunpy@googlegroups.com" }, ] -select = [ - "E", - "F", - "W", - "UP", - "PT", - "RET", - "TID", - "PLE", - "NPY", - "RUF", - "PGH", - "PTH", - "BLE", - "FBT", - "B", - "A", - "COM", - "C4", - "T20", - "RSE", - "ERA", +dependencies = [ + "sunpy[net]>=5.0" ] -fixable = [ - "E", - "F", - "W", - "UP", - "PT", - "RET", - "TID", - "PLE", - "NPY", - "RUF", - "PGH", - "PTH", - "BLE", - "FBT", - "B", - "A", - "COM", - "C4", - "T20", - "RSE", - "ERA", +dynamic = ["version"] + +[project.optional-dependencies] +tests = [ + "pytest-cov", + "pytest-doctestplus", + "pytest-xdist", + "pytest", + "sunpy[map,net]>=5.0", ] -extend-ignore = [ - "E501", # Line too long - # TODO: Fix in future - "E741", # Ambiguous variable name +docs = [ + "sphinx", + "sphinx-automodapi", + "sphinx-changelog", + "sphinx-copybutton", + "sunpy-sphinx-theme", ] -[tool.ruff.per-file-ignores] -"examples/*.py" = [ - "T201", # We need print in our examples -] +[project.urls] +Homepage = "https://sunpy.org" +Download = "https://pypi.org/project/sunpy-soar/" +"Source Code" = "https://github.com/sunpy/sunpy-soar/" +Documentation = "https://docs.sunpy.org/projects/soar/" +Changelog = "https://docs.sunpy.org/projects/soar/changelog.html" +"Issue Tracker" = "https://github.com/sunpy/sunpy-soar/issues" + +[tool.setuptools] +zip-safe = false +include-package-data = true -[tool.ruff.pydocstyle] -convention = "numpy" +[tool.setuptools.packages.find] -[tool.codespell] -skip = "*.asdf,*.fits,*.fts,*.header,*.json,*.xsh,*cache*,*egg*,*extern*,.git,.idea,.tox,_build,*truncated,*.svg,.asv_env,.history" -ignore-words-list = "sav,soop," +[tool.setuptools_scm] +write_to = "sunpy_soar/_version.py" [tool.towncrier] package = "sunpy_soar" diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..dd8a39f --- /dev/null +++ b/pytest.ini @@ -0,0 +1,34 @@ +[pytest] +minversion = 7.0 +testpaths = + sunpy_soar + docs +norecursedirs = + docs/_build + docs/generated + sunpy_soar/_dev + sunpy_soar/extern +doctest_plus = enabled +doctest_optionflags = NORMALIZE_WHITESPACE FLOAT_CMP ELLIPSIS +text_file_format = rst +addopts = --doctest-rst -p no:unraisableexception -p no:threadexception +filterwarnings = + # Turn all warnings into errors so they do not pass silently. + error + # Do not fail on pytest config issues (i.e. missing plugins) but do show them + always::pytest.PytestConfigWarning + # A list of warnings to ignore follows. If you add to this list, you MUST + # add a comment or ideally a link to an issue that explains why the warning + # is being ignored + # https://github.com/pandas-dev/pandas/issues/54466 + ignore:\nPyarrow will become a required dependency of pandas in the next major release of pandas:DeprecationWarning + # See https://github.com/mvantellingen/python-zeep/issues/956 + ignore:defusedxml.lxml is no longer supported:DeprecationWarning + ignore:numpy.ndarray size changed + # This is coming from astropy + ignore:The distutils package is deprecated + # Zeep relies on deprecated cgi in Python 3.11 + ignore:'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning:zeep.utils + # Not sure what these are + ignore:unclosed = 3.9 -install_requires = - sunpy[net]>=5.0 -include_package_data = True - -[options.extras_require] -tests = - pytest - sunpy[map,net]>=5.0 -docs = - sphinx - sphinx-automodapi - # Remove next line when fixed in towncrier; see https://github.com/twisted/towncrier/issues/528 - importlib-resources<6 - sphinx-changelog - sphinx-copybutton - sunpy-sphinx-theme - -[tool:pytest] -testpaths = "sunpy_soar" "docs" -norecursedirs = ".tox" "build" "docs[\/]_build" "docs[\/]generated" "*.egg-info" "examples" "sunpy_soar[/\]_dev" ".jupyter" ".history" -addopts = -p no:unraisableexception -p no:threadexception -filterwarnings = - error - # https://github.com/pandas-dev/pandas/issues/54466 - ignore:\nPyarrow will become a required dependency of pandas in the next major release of pandas:DeprecationWarning - # See https://github.com/mvantellingen/python-zeep/issues/956 - ignore:defusedxml.lxml is no longer supported:DeprecationWarning - ignore:numpy.ndarray size changed - # This is coming from astropy - ignore:The distutils package is deprecated - # Zeep relies on deprecated cgi in Python 3.11 - ignore:'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning:zeep.utils - # Not sure what these are - ignore:unclosed ='{start}'+AND+begin_time<='{end}'") @walker.add_applier(a.Level) -def _(wlk, attr, params): +def _(wlk, attr, params): # NOQA: ARG001 level = attr.value if isinstance(level, int): level = f"L{level}" @@ -115,20 +112,20 @@ def _(wlk, attr, params): @walker.add_applier(a.Instrument) -def _(wlk, attr, params): +def _(wlk, attr, params): # NOQA: ARG001 params.append(f"instrument='{attr.value}'") @walker.add_applier(Product) -def _(wlk, attr, params): +def _(wlk, attr, params): # NOQA: ARG001 params.append(f"descriptor='{attr.value}'") @walker.add_applier(a.Provider) -def _(wlk, attr, params): +def _(wlk, attr, params): # NOQA: ARG001 params.append(f"provider='{attr.value}'") @walker.add_applier(SOOP) -def _(wlk, attr, params): +def _(wlk, attr, params): # NOQA: ARG001 params.append(f"soop_name='{attr.value}'") diff --git a/sunpy_soar/client.py b/sunpy_soar/client.py index a4918ea..07943a2 100644 --- a/sunpy_soar/client.py +++ b/sunpy_soar/client.py @@ -20,7 +20,7 @@ class SOARClient(BaseClient): Client to access the Solar Orbiter Archive (SOAR). """ - def search(self, *query, **kwargs): + def search(self, *query, **kwargs): # NOQA: ARG002 query = and_(*query) queries = walker.create(query) @@ -58,7 +58,12 @@ def _construct_payload(query): url_query["WHERE"] = "+AND+".join(query) adql_query = "+".join([f"{item}+{url_query[item]}" for item in url_query]) - return {"REQUEST": "doQuery", "LANG": "ADQL", "FORMAT": "json", "QUERY": adql_query} + return { + "REQUEST": "doQuery", + "LANG": "ADQL", + "FORMAT": "json", + "QUERY": adql_query, + } @staticmethod def _do_search(query): @@ -111,7 +116,7 @@ def _do_search(query): result_table.sort("Start time") return result_table - def fetch(self, query_results, *, path, downloader, **kwargs): + def fetch(self, query_results, *, path, downloader, **kwargs): # NOQA: ARG002 """ Queue a set of results to be downloaded. `sunpy.net.base_client.BaseClient` does the actual downloading, so we diff --git a/sunpy_soar/conftest.py b/sunpy_soar/conftest.py new file mode 100644 index 0000000..13046a7 --- /dev/null +++ b/sunpy_soar/conftest.py @@ -0,0 +1,13 @@ +import os + +import pytest + + +@pytest.fixture(scope="session", autouse=True) +def _hide_parfive_progress(request): # NOQA: ARG001 + """ + Set the PARFIVE_HIDE_PROGRESS to hide the parfive progress bar in tests. + """ + os.environ["PARFIVE_HIDE_PROGRESS"] = "True" + yield + del os.environ["PARFIVE_HIDE_PROGRESS"] diff --git a/sunpy_soar/data/README.rst b/sunpy_soar/data/README.rst new file mode 100644 index 0000000..382f6e7 --- /dev/null +++ b/sunpy_soar/data/README.rst @@ -0,0 +1,6 @@ +Data directory +============== + +This directory contains data files included with the package source +code distribution. Note that this is intended only for relatively small files +- large files should be externally hosted and downloaded as needed. diff --git a/sunpy_soar/tests/__init__.py b/sunpy_soar/tests/__init__.py index e69de29..92ea707 100644 --- a/sunpy_soar/tests/__init__.py +++ b/sunpy_soar/tests/__init__.py @@ -0,0 +1,3 @@ +""" +This module contains package tests. +""" diff --git a/sunpy_soar/tests/test_sunpy_soar.py b/sunpy_soar/tests/test_sunpy_soar.py index 9fbd70b..fe37fd9 100644 --- a/sunpy_soar/tests/test_sunpy_soar.py +++ b/sunpy_soar/tests/test_sunpy_soar.py @@ -98,8 +98,8 @@ def test_registered_attrs(): def test_registered_instr_attrs(): # Check if the Solo instruments are registered in a.Instrument instr_attr = a.Instrument - assert "SOAR" in instr_attr._attr_registry[instr_attr].client - assert "stix" in instr_attr._attr_registry[instr_attr].name + assert "SOAR" in instr_attr._attr_registry[instr_attr].client # NOQA: SLF001 + assert "stix" in instr_attr._attr_registry[instr_attr].name # NOQA: SLF001 def test_registered_soop_names(): @@ -128,7 +128,7 @@ def test_when_soar_provider_passed(): provider = a.Provider.soar res = Fido.search(time & instrument & provider) assert len(res) == 1 - assert "soar" in res.keys() + assert res["soar"] def test_when_sdac_provider_passed(): @@ -138,7 +138,7 @@ def test_when_sdac_provider_passed(): provider = a.Provider.sdac res = Fido.search(time & instrument & provider) assert len(res) == 1 - assert "vso" in res.keys() + assert res["vso"] def test_when_wrong_provider_passed(): diff --git a/tools/update_data.py b/tools/update_data.py index 8bd2e5c..45b9fb6 100644 --- a/tools/update_data.py +++ b/tools/update_data.py @@ -44,7 +44,18 @@ def get_all_instruments(): job = SOAR.launch_job("select * from soar.instrument") res = job.get_results() - instruments = ["EPD", "EUI", "MAG", "METIS", "PHI", "RPW", "SOLOHI", "SPICE", "STIX", "SWA"] + instruments = [ + "EPD", + "EUI", + "MAG", + "METIS", + "PHI", + "RPW", + "SOLOHI", + "SPICE", + "STIX", + "SWA", + ] instr_desc = {} for r in res: if r["name"] not in instruments: @@ -69,17 +80,26 @@ def get_all_soops(): if __name__ == "__main__": - attr_file = pathlib.Path(__file__).parent.parent / "sunpy_soar" / "data" / "attrs.json" + attr_file = ( + pathlib.Path(__file__).parent.parent / "sunpy_soar" / "data" / "attrs.json" + ) descriptors = get_all_descriptors() with attr_file.open("w") as attrs_file: json.dump(dict(sorted(descriptors.items())), attrs_file, indent=2) - instr_file = pathlib.Path(__file__).parent.parent / "sunpy_soar" / "data" / "instrument_attrs.json" + instr_file = ( + pathlib.Path(__file__).parent.parent + / "sunpy_soar" + / "data" + / "instrument_attrs.json" + ) instr_descriptors = get_all_instruments() with instr_file.open("w") as instrs_file: json.dump(dict(sorted(instr_descriptors.items())), instrs_file, indent=2) - soop_file = pathlib.Path(__file__).parent.parent / "sunpy_soar" / "data" / "soop_attrs.json" + soop_file = ( + pathlib.Path(__file__).parent.parent / "sunpy_soar" / "data" / "soop_attrs.json" + ) soop_descriptors = get_all_soops() with soop_file.open("w") as soops_file: json.dump(dict(sorted(soop_descriptors.items())), soops_file, indent=2) diff --git a/tox.ini b/tox.ini index 33e810a..9859ee5 100644 --- a/tox.ini +++ b/tox.ini @@ -1,42 +1,65 @@ [tox] +min_version = 4.0 +requires = + tox-pypi-filter>=0.14 envlist = - py{39,310,311}{,-devdeps} - build_docs + py{310,311,312} + py312-devdeps + py310-oldestdeps codestyle -isolated_build = true + build_docs [testenv] -whitelist_externals= - /bin/bash - /usr/bin/bash -changedir = .tmp/{envname} +pypi_filter = https://raw.githubusercontent.com/sunpy/sunpy/main/.test_package_pins.txt +# Run the tests in a temporary directory to make sure that we don't import +# the package from the source tree +change_dir = .tmp/{envname} description = run tests + oldestdeps: with the oldest supported version of key dependencies devdeps: with the latest developer version of key dependencies -setenv = +pass_env = + # A variable to tell tests we are on a CI system + CI + # Custom compiler locations (such as ccache) + CC + # Location of locales (needed by sphinx on some systems) + LOCALE_ARCHIVE + # If the user has set a LC override we should follow it + LC_ALL +set_env = MPLBACKEND = agg COLUMNS = 180 + devdeps: PIP_EXTRA_INDEX_URL = https://pypi.anaconda.org/astropy/simple https://pypi.anaconda.org/scientific-python-nightly-wheels/simple + # Define the base test command here to allow us to add more flags for each tox factor PYTEST_COMMAND = pytest -vvv -s -raR --pyargs sunpy_soar --cov-report=xml --cov=sunpy_soar {toxinidir}/docs + PARFIVE_HIDE_PROGRESS = True deps = - pytest-xdist + # For packages which publish nightly wheels this will pull the latest nightly + devdeps: numpy>=0.0.dev0 + # Packages without nightly wheels will be built from source like this + # devdeps: git+https://github.com/ndcube/ndcube + oldestdeps: minimum_dependencies pytest-cov devdeps: git+https://github.com/sunpy/sunpy + pytest-xdist +# The following indicates which extras_require will be installed extras = tests -commands = +commands_pre = + oldestdeps: minimum_dependencies sunpy-soar --filename requirements-min.txt + oldestdeps: pip install -r requirements-min.txt pip freeze --all --no-input - {env:PYTEST_COMMAND} {posargs} - -[testenv:build_docs] -changedir = docs -description = Invoke sphinx-build to build the HTML docs -extras = docs commands = - pip freeze --all --no-input - sphinx-build --color -W --keep-going -b html -d _build/.doctrees . _build/html {posargs} - python -c 'import pathlib; print("Documentation available under file://\{0\}".format(pathlib.Path(r"{toxinidir}") / "docs" / "_build" / "index.html"))' + # To run different commands for different factors exclude the factor from the default command like this + # !online: {env:PYTEST_COMMAND} {posargs} + # Then specify a specific one like this + # online: {env:PYTEST_COMMAND} --remote-data=any {posargs} + # If you have no factors which require different commands this is all you need: + {env:PYTEST_COMMAND} {posargs} [testenv:codestyle] +pypi_filter = skip_install = true description = Run all style and file checks with pre-commit deps = @@ -44,3 +67,14 @@ deps = commands = pre-commit install-hooks pre-commit run --color always --all-files --show-diff-on-failure + +[testenv:build_docs] +description = invoke sphinx-build to build the HTML docs +change_dir = + docs +extras = + docs +commands = + pip freeze --all --no-input + sphinx-build --color -W --keep-going -b html -d _build/.doctrees . _build/html {posargs} + python -c 'import pathlib; print("Documentation available under file://\{0\}".format(pathlib.Path(r"{toxinidir}") / "docs" / "_build" / "index.html"))'