diff --git a/.black b/.black
new file mode 100644
index 0000000..aedc909
--- /dev/null
+++ b/.black
@@ -0,0 +1,17 @@
+target-version = ['py310']
+exclude = '''
+(
+ /(
+ \.eggs
+ | \.git
+ | \.mypy_cache
+ | \.tox
+ | \.venv
+ | _build
+ | build
+ | dist
+ | docs
+ | .history
+ )/
+)
+'''
diff --git a/.codecov.yaml b/.codecov.yaml
index bd2cef3..8fe09b7 100644
--- a/.codecov.yaml
+++ b/.codecov.yaml
@@ -4,3 +4,8 @@ coverage:
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..cf3fcbe
--- /dev/null
+++ b/.codespellrc
@@ -0,0 +1,15 @@
+[codespell]
+skip = *.asdf,*.fits,*.fts,*.header,*.json,*.xsh,*cache*,*egg*,*extern*,.git,.idea,.tox,_build,*truncated,*.svg,.asv_env,.history
+ignore-words-list =
+ afile,
+ alog,
+ nd,
+ nin,
+ observ,
+ ot,
+ precess
+ precessed,
+ requestor,
+ sav,
+ te,
+ upto,
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..6e20457
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,30 @@
+[run]
+omit =
+ drms/conftest.py
+ drms/*setup_package*
+ drms/extern/*
+ drms/version*
+ */drms/conftest.py
+ */drms/*setup_package*
+ */drms/extern/*
+ */drms/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..3874a52
--- /dev/null
+++ b/.cruft.json
@@ -0,0 +1,31 @@
+{
+ "template": "https://github.com/sunpy/package-template",
+ "commit": "c0e51ac3283d88346534da0aac441f37f624b283",
+ "checkout": null,
+ "context": {
+ "cookiecutter": {
+ "package_name": "drms",
+ "module_name": "drms",
+ "short_description": "Access HMI, AIA and MDI data from the Standford JSOC DRMS",
+ "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..a0f9eab
--- /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
+ drms/__init__.py
+rst-directives =
+ plot
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 34344fb..e755edb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,6 +12,7 @@ on:
- '!*pre*'
- '!*post*'
pull_request:
+ # Allow manual runs through the web UI
workflow_dispatch:
schedule:
# ┌───────── minute (0 - 59)
@@ -35,9 +36,23 @@ jobs:
posargs: -n auto
envs: |
- 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
@@ -48,14 +63,16 @@ jobs:
- windows: py10
- macos: py311
- linux: py310-oldestdeps
+ secrets:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
docs:
needs: [core]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main
with:
+ default_python: '3.12'
submodules: false
pytest: false
- default_python: '3.12'
toxdeps: "tox-pypi-filter"
libraries: |
apt:
@@ -64,10 +81,9 @@ jobs:
- linux: build_docs
online:
- if: "!startsWith(github.event.ref, 'refs/tags/v')"
- needs: [docs]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main
with:
+ default_python: '3.12'
submodules: false
coverage: codecov
toxdeps: "tox-pypi-filter"
@@ -75,21 +91,23 @@ jobs:
envs: |
- linux: py312-online
- linux: py312-sunpy
+ secrets:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
publish:
- # Build wheels when pushing to any branch
- # publish_pure_python.yml will only publish if tagged ^v.*
+ # Build wheels on PRs only when labelled. Releases will only be published if tagged ^v.*
+ # see https://github-actions-workflows.openastronomy.org/en/latest/publish.html#upload-to-pypi
if: |
+ github.event_name != 'pull_request' ||
(
- github.event_name != 'pull_request'
- ) || (
github.event_name == 'pull_request' &&
contains(github.event.pull_request.labels.*.name, 'Run publish')
)
- needs: [test]
+ needs: [test, docs]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@main
with:
- test_extras: 'dev'
+ python-version: '3.12'
+ test_extras: 'tests'
test_command: 'pytest -p no:warnings --doctest-rst --pyargs drms'
submodules: false
secrets:
diff --git a/.github/workflows/sub_package_update.yml b/.github/workflows/sub_package_update.yml
new file mode 100644
index 0000000..7455847
--- /dev/null
+++ b/.github/workflows/sub_package_update.yml
@@ -0,0 +1,79 @@
+# 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
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.11"
+
+ - name: Install Cruft
+ run: python -m pip install git+https://github.com/Cadair/cruft@patch-p1
+
+ - 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@v7
+ 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 6a2621c..110d24e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,11 +24,12 @@ parts/
sdist/
var/
wheels/
+share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
-
+drms/_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.
@@ -42,15 +43,17 @@ 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/
-junit/
+cover/
# Translations
*.mo
@@ -60,6 +63,7 @@ junit/
*.log
local_settings.py
db.sqlite3
+db.sqlite3-journal
# Flask stuff:
instance/
@@ -70,18 +74,47 @@ instance/
# Sphinx documentation
docs/_build/
+# automodapi
+docs/api
+docs/sg_execution_times.rst
# PyBuilder
+.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
-# pyenv
-.python-version
+# IPython
+profile_default/
+ipython_config.py
-# celery beat schedule file
+# 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
@@ -95,10 +128,6 @@ ENV/
env.bak/
venv.bak/
-# Spyder project settings
-.spyderproject
-.spyproject
-
# Rope project settings
.ropeproject
@@ -108,8 +137,22 @@ venv.bak/
# mypy
.mypy_cache/
-### https://raw.github.com/github/gitignore/master/Global/OSX.gitignore
+# 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
@@ -117,7 +160,6 @@ venv.bak/
# Icon must ends with two \r.
Icon
-
# Thumbnails
._*
@@ -126,7 +168,6 @@ Icon
.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
@@ -141,7 +182,8 @@ Icon
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
-### MacOS: https://raw.githubusercontent.com/github/gitignore/master/Global/macOS.gitignore
+# pytype static type analyzer
+.pytype/
# General
.DS_Store
@@ -197,11 +239,7 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
-### VScode: https://raw.githubusercontent.com/github/gitignore/master/Global/VisualStudioCode.gitignore
-.vscode/*
-.vs/*
-
-### Extra Python Items and DRMS Specific
+### Extra Python Items and SunPy Specific
.hypothesis
.pytest_cache
docs/_build
@@ -215,9 +253,6 @@ examples/jsoc.stanford.edu/
jsoc.stanford.edu/
docs/sg_execution_times.rst
-### Pycharm(?)
-.idea
-
# Release script
.github_cache
@@ -225,3 +260,10 @@ docs/sg_execution_times.rst
.history
*.orig
.tmp
+node_modules/
+package-lock.json
+package.json
+.prettierrc
+
+# Log files generated by 'vagrant up'
+*.log
diff --git a/.isort.cfg b/.isort.cfg
new file mode 100644
index 0000000..62e8c62
--- /dev/null
+++ b/.isort.cfg
@@ -0,0 +1,16 @@
+[settings]
+balanced_wrapping = true
+skip =
+ docs/conf.py
+ drms/__init__.py
+default_section = THIRDPARTY
+include_trailing_comma = true
+known_astropy = astropy, asdf
+known_sunpy = sunpy
+known_first_party = drms
+length_sort = false
+length_sort_sections = stdlib
+line_length = 110
+multi_line_output = 3
+no_lines_before = LOCALFOLDER
+sections = STDLIB, THIRDPARTY, ASTROPY, SUNPY, FIRSTPARTY, LOCALFOLDER
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 70be7a3..d3ad645 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,49 +1,34 @@
repos:
- - repo: https://github.com/PyCQA/docformatter
- rev: v1.7.5
- hooks:
- - id: docformatter
- args: [--in-place, --pre-summary-newline, --make-summary-multi]
- - repo: https://github.com/PyCQA/autoflake
- rev: v2.3.1
- hooks:
- - id: autoflake
- 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.5.0'
+ rev: "v0.6.4"
hooks:
- id: ruff
args: ['--fix', '--unsafe-fixes']
- - repo: https://github.com/psf/black
- rev: 24.4.2
- hooks:
- - id: black
- exclude: ".*(.fits|.fts|.fit|.txt|.csv)$"
+ - id: ruff-format
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
exclude: ".*(.fits|.fts|.fit|.txt|.csv)$"
- - repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.6.0
- hooks:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v5.0.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)$"
+ exclude: ".*(.fits|.fts|.fit|.header|.txt)$"
- id: check-yaml
- id: debug-statements
+ - id: check-added-large-files
+ args: ["--enforce-all", "--maxkb=1054"]
+ - id: end-of-file-fixer
+ exclude: ".*(.fits|.fts|.fit|.header|.txt|tca.*|.json)$|^CITATION.rst$"
+ - id: mixed-line-ending
+ exclude: ".*(.fits|.fts|.fit|.header|.txt|tca.*)$"
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
- additional_dependencies:
- - tomli
ci:
autofix_prs: false
autoupdate_schedule: "quarterly"
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..3d9312d
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,29 @@
+version: 2
+
+build:
+ os: ubuntu-lts-latest
+ tools:
+ python: "mambaforge-latest"
+ jobs:
+ post_checkout:
+ - git fetch --unshallow || true
+ pre_install:
+ - git update-index --assume-unchanged .rtd-environment.yml docs/conf.py
+
+conda:
+ environment: .rtd-environment.yml
+
+sphinx:
+ builder: html
+ configuration: docs/conf.py
+ fail_on_warning: false
+
+formats:
+ - htmlzip
+
+python:
+ install:
+ - method: pip
+ extra_requirements:
+ - docs
+ path: .
diff --git a/.rtd-environment.yml b/.rtd-environment.yml
new file mode 100644
index 0000000..770b614
--- /dev/null
+++ b/.rtd-environment.yml
@@ -0,0 +1,7 @@
+name: drms
+channels:
+ - conda-forge
+dependencies:
+ - python=3.12
+ - pip
+ - graphviz!=2.42.*,!=2.43.*
diff --git a/.ruff.toml b/.ruff.toml
new file mode 100644
index 0000000..707968c
--- /dev/null
+++ b/.ruff.toml
@@ -0,0 +1,87 @@
+target-version = "py310"
+line-length = 120
+exclude = [
+ "drms/version.py",
+ ".git,",
+ "__pycache__",
+ "__pypackages__",
+ "_build",
+ ".bzr",
+ ".direnv",
+ ".eggs",
+ ".git-rewrite",
+ ".git",
+ ".hg",
+ ".mypy_cache",
+ ".nox",
+ ".pants.d",
+ ".pytype",
+ ".ruff_cache",
+ ".svn",
+ ".tox",
+ ".venv",
+ "buck-out",
+ "build",
+ "dist",
+ "node_modules",
+ "paper/create_joss_figure.py",
+ "tools/**",
+ "venv",
+]
+
+[lint]
+select = [
+ "E",
+ "F",
+ "W",
+ "UP",
+ "PT",
+ "RET",
+ "TID",
+ "PLE",
+ "NPY",
+ "RUF",
+ "PGH",
+ "PTH",
+ "BLE",
+ "FBT",
+ "B",
+ "A",
+ "C4",
+ "T20",
+ "RSE",
+ "ERA",
+]
+extend-ignore = [
+ # pycodestyle (E, W)
+ "E501", # LineTooLong # TODO! fix
+ # pytest (PT)
+ "PT001", # Always use pytest.fixture()
+ "PT004", # Fixtures which don't return anything should have leading _
+ "PT007", # Parametrize should be lists of tuples # TODO! fix
+ "PT011", # Too broad exception assert # TODO! fix
+ "PT023", # Always use () on pytest decorators
+]
+
+[lint.per-file-ignores]
+# Part of configuration, not a package.
+"setup.py" = ["INP001"]
+"conftest.py" = ["INP001"]
+"docs/conf.py" = [
+ "E402" # Module imports not at top of file
+]
+"docs/*.py" = [
+ "INP001", # Implicit-namespace-package. The examples are not a package.
+]
+"__init__.py" = ["E402", "F401", "F403"]
+"test_*.py" = ["B011", "D", "E402", "PGH001", "S101"]
+"examples/*.py" = [
+ "T201",
+ # We need print in our examples
+]
+"examples/plot_hmi_modes.py" = [
+ "E741", # Ambiguous variable name
+]
+
+[lint.pydocstyle]
+convention = "numpy"
diff --git a/MANIFEST.in b/MANIFEST.in
index 153dcb8..ab1f5d3 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,11 @@
-prune paper
-# This subpackage is only used in development checkouts and should not be included in built tarballs
+# 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 drms/_dev
diff --git a/README.rst b/README.rst
index ead1987..4532d91 100644
--- a/README.rst
+++ b/README.rst
@@ -2,6 +2,8 @@
drms
====
+Access HMI, AIA and MDI data from the Standford JSOC DRMS.
+
`Docs `__ |
`Tutorial `__ |
`Github `__ |
@@ -26,12 +28,46 @@ For more information or to ask questions about ``drms``, check out:
- `drms Documentation `__
- `SunPy Chat `__
+License
+-------
+
+This project is Copyright (c) The SunPy Community and licensed under
+the terms of the BSD 2-Clause license. This package is based upon
+the `Openastronomy packaging guide `_
+which is licensed under the BSD 3-clause licence. See the licenses folder for
+more information.
+
Contributing
------------
-If you would like to get involved, read our `Newcomers' guide `__.
-
-Help is always welcome so let us know what you like to work on, or check out the `issues page `__ for a list of known outstanding items.
+We love contributions! drms is open source,
+built on open source, and we'd love to have you hang out in our community.
+
+**Imposter syndrome disclaimer**: We want your help. No, really.
+
+There may be a little voice inside your head that is telling you that you're not
+ready to be an open source contributor; that your skills aren't nearly good
+enough to contribute. What could you possibly offer a project like this one?
+
+We assure you - the little voice in your head is wrong. If you can write code at
+all, you can contribute code to open source. Contributing to open source
+projects is a fantastic way to advance one's coding skills. Writing perfect code
+isn't the measure of a good developer (that would disqualify all of us!); it's
+trying to create something, making mistakes, and learning from those
+mistakes. That's how we all improve, and we are happy to help others learn.
+
+Being an open source contributor doesn't just mean writing code, either. You can
+help out by writing documentation, tests, or even giving feedback about the
+project (and yes - that includes giving feedback about the contribution
+process). Some of these contributions may be the most valuable to the project as
+a whole, because you're coming to the project with fresh eyes, so you can see
+the errors and assumptions that seasoned contributors have glossed over.
+
+Note: This disclaimer was originally written by
+`Adrienne Lowe `_ for a
+`PyCon talk `_, and was adapted by
+drms based on its use in the README file for the
+`MetPy project `_.
Citation
--------
diff --git a/docs/conf.py b/docs/conf.py
index 8db95cb..bd8a4ed 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,6 +1,8 @@
-"""
-Configuration file for the Sphinx documentation builder.
-"""
+# 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
import os
import datetime
@@ -8,17 +10,23 @@
from sunpy_sphinx_theme import PNG_ICON
-from drms import __version__
# -- Project information -----------------------------------------------------
-project = "drms"
-author = "The SunPy Project"
-copyright = f"{datetime.datetime.now().year}, {author}" # NOQA: A001
+
# The full version, including alpha/beta/rc tags
+from drms import __version__
+
release = __version__
-is_development = ".dev" in __version__
+
+project = "drms"
+author = "The SunPy Community"
+copyright = f"{datetime.datetime.now().year}, {author}" # noqa: A001
# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named "sphinx.ext.*") or your custom
+# ones.
extensions = [
"hoverxref.extension",
"sphinx_copybutton",
@@ -36,11 +44,25 @@
"sphinx.ext.todo",
"sphinx.ext.viewcode",
]
+
+# Add any paths that contain templates here, relative to this directory.
+# templates_path = ["_templates"] # NOQA: ERA001
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
automodapi_toctreedirnm = "generated/api"
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
source_suffix = ".rst"
+
+# The master toctree document.
master_doc = "index"
-default_role = "obj"
+
+# Treat everything in single ` as a Python reference.
+default_role = "py:obj"
# -- Options for hoverxref -----------------------------------------------------
if os.environ.get("READTHEDOCS"):
diff --git a/docs/index.rst b/docs/index.rst
index b07fd42..0101879 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -11,6 +11,7 @@ Python library for accessing HMI, AIA and MDI data from the Joint Science Operat
.. toctree::
:maxdepth: 2
+ :caption: Contents:
intro
tutorial
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644
index 0000000..2119f51
--- /dev/null
+++ b/docs/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/docs/tutorial.rst b/docs/tutorial.rst
index 0cc7015..77de7b4 100644
--- a/docs/tutorial.rst
+++ b/docs/tutorial.rst
@@ -224,8 +224,6 @@ The following, for example, only downloads the first file of the request:
.. code-block:: python
>>> export_request.download(out_dir, index=0) # doctest: +REMOTE_DATA
- record url download
- 0 hmi.V_45s[2016.04.01_00:00:00_TAI][2]{Dopplerg... http://jsoc.stanford.edu/SUM58/D803708321/S000... ...
Being a direct ``as-is`` export, there are no keyword data written to any FITS headers.
If you need keyword data added to the headers, you have to use the ``fits`` export protocol instead, which is described below.
diff --git a/drms/__init__.py b/drms/__init__.py
index 17a5273..594c830 100644
--- a/drms/__init__.py
+++ b/drms/__init__.py
@@ -20,12 +20,12 @@
datefmt="%Y-%m-%d %H:%M:%S",
)
-from .client import Client, ExportRequest, SeriesInfo # NOQA: E402
-from .config import ServerConfig, register_server # NOQA: E402
-from .exceptions import DrmsError, DrmsExportError, DrmsOperationNotSupported, DrmsQueryError # NOQA: E402
-from .json import HttpJsonClient, HttpJsonRequest, JsocInfoConstants # NOQA: E402
-from .utils import to_datetime # NOQA: E402
-from .version import version as __version__ # NOQA: E402
+from .client import Client, ExportRequest, SeriesInfo
+from .config import ServerConfig, register_server
+from .exceptions import DrmsError, DrmsExportError, DrmsOperationNotSupported, DrmsQueryError
+from .json import HttpJsonClient, HttpJsonRequest, JsocInfoConstants
+from .utils import to_datetime
+from .version import version as __version__
def _get_bibtex():
diff --git a/drms/client.py b/drms/client.py
index f85172c..491fe77 100644
--- a/drms/client.py
+++ b/drms/client.py
@@ -11,7 +11,6 @@
import pandas as pd
from drms import logger
-
from .exceptions import DrmsExportError, DrmsOperationNotSupported, DrmsQueryError
from .json import HttpJsonClient
from .utils import _extract_series_name, _pd_to_numeric_coerce, _split_arg
diff --git a/drms/data/README.rst b/drms/data/README.rst
new file mode 100644
index 0000000..382f6e7
--- /dev/null
+++ b/drms/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/drms/json.py b/drms/json.py
index 9556ad6..852ef32 100644
--- a/drms/json.py
+++ b/drms/json.py
@@ -4,7 +4,6 @@
from urllib.request import HTTPError, urlopen
from drms import logger
-
from .config import ServerConfig, _server_configs
from .utils import _split_arg
diff --git a/drms/tests/__init__.py b/drms/tests/__init__.py
index e69de29..92ea707 100644
--- a/drms/tests/__init__.py
+++ b/drms/tests/__init__.py
@@ -0,0 +1,3 @@
+"""
+This module contains package tests.
+"""
diff --git a/drms/tests/test_jsoc_query.py b/drms/tests/test_jsoc_query.py
index 032aef4..659cb25 100644
--- a/drms/tests/test_jsoc_query.py
+++ b/drms/tests/test_jsoc_query.py
@@ -97,7 +97,10 @@ def test_query_invalid_series(jsoc_client):
@pytest.mark.remote_data()
@pytest.mark.parametrize(
"query",
- ["hmi.v_45s[2014.01.01_00:00:35_TAI-2014.01.01_01:00:35_TAI]", "hmi.M_720s[2011.04.14_00:30:00_TAI/6h@2h]"],
+ [
+ "hmi.v_45s[2014.01.01_00:00:35_TAI-2014.01.01_01:00:35_TAI]",
+ "hmi.M_720s[2011.04.14_00:30:00_TAI/6h@2h]",
+ ],
)
def test_query_hexadecimal_strings(query):
# Exercise the part of client.py that deals with hexadecimal strings
diff --git a/drms/version.py b/drms/version.py
index bd90735..9eef714 100644
--- a/drms/version.py
+++ b/drms/version.py
@@ -1,5 +1,5 @@
# NOTE: First try _dev.scm_version if it exists and setuptools_scm is installed
-# This file is not included in muse wheels/tarballs, so otherwise it will
+# This file is not included in wheels/tarballs, so otherwise it will
# fall back on the generated _version module.
try:
try:
diff --git a/examples/plot_synoptic_mr.py b/examples/plot_synoptic_mr.py
index f79cb7b..a5da520 100644
--- a/examples/plot_synoptic_mr.py
+++ b/examples/plot_synoptic_mr.py
@@ -7,6 +7,7 @@
"""
import matplotlib.pyplot as plt
+
from astropy.io import fits
import drms
diff --git a/pyproject.toml b/pyproject.toml
index c5527d5..3fa4fcc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,116 +1,62 @@
[build-system]
requires = [
- "setuptools",
- "setuptools_scm[toml]",
+ "setuptools>=62.1",
+ "setuptools_scm[toml]>=6.2",
"wheel",
- "oldest-supported-numpy",
]
-build-backend = 'setuptools.build_meta'
-
-[tool.black]
-line-length = 120
-target-version = ['py310']
-exclude = '''
-(
- /(
- \.eggs
- | \.git
- | \.mypy_cache
- | \.tox
- | \.venv
- | _build
- | build
- | dist
- | docs
- | .history
- )/
-)
-'''
-
-[tool.isort]
-profile = "black"
-line_length = 120
-length_sort = "False"
-length_sort_sections = "stdlib"
-
-[tool.ruff]
-target-version = "py310"
-line-length = 120
-exclude=[
- "__pycache__",
- "__pypackages__",
- "_build",
- ".bzr",
- ".direnv",
- ".eggs",
- ".git-rewrite",
- ".git",
- ".hg",
- ".mypy_cache",
- ".nox",
- ".pants.d",
- ".pytype",
- ".ruff_cache",
- ".svn",
- ".tox",
- ".venv",
- "buck-out",
- "build",
- "dist",
- "node_modules",
- "paper/create_joss_figure.py",
- "tools/**",
- "venv",
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "drms"
+description = "Access HMI, AIA and MDI data from the Standford JSOC DRMS"
+requires-python = ">=3.10"
+readme = { file = "README.rst", content-type = "text/x-rst" }
+license = { file = "licenses/LICENSE.rst" }
+authors = [
+ { name = "The SunPy Community", email = "sunpy@googlegroups.com" },
]
-
-[tool.ruff.lint]
-# Allow unused variables when underscore-prefixed.
-dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
-select = [
- "E",
- "F",
- "W",
- "UP",
- "PT",
- "RET",
- "TID",
- "PLE",
- "NPY",
- "RUF",
- "PGH",
- "PTH",
- "BLE",
- "FBT",
- "B",
- "A",
- "COM",
- "C4",
- "T20",
- "RSE",
- "ERA",
-]
-extend-ignore = [
- "E501", # Line too long
+dependencies = [
+ "numpy>=1.23.5",
+ "pandas>=1.5.1",
+ "packaging>=23.0"
]
-
-[tool.ruff.lint.per-file-ignores]
-"examples/*.py" = [
- "T201",
- # We need print in our examples
+dynamic = [ "version" ]
+
+[project.optional-dependencies]
+tests = [
+ "pytest",
+ "pytest-astropy",
+ "pytest-doctestplus",
+ "pytest-cov",
+ "pytest-xdist",
+ "astropy",
]
-"examples/plot_hmi_modes.py" = [
- "E741", # Ambiguous variable name
+docs = [
+ "astropy",
+ "matplotlib",
+ "sphinx",
+ "sphinx-automodapi",
+ "sphinx-changelog",
+ "sphinx-copybutton",
+ "sphinx-gallery",
+ "sphinx-hoverxref",
+ "sphinxext-opengraph",
+ "sunpy-sphinx-theme",
+ "sphinx-automodapi",
]
+[project.urls]
+repository = "https://sunpy.org"
-[tool.ruff.lint.pydocstyle]
-convention = "numpy"
+[tool.setuptools]
+zip-safe = false
+include-package-data = true
-[tool.ruff.lint.flake8-quotes]
-docstring-quotes = "double"
+[tool.setuptools.packages.find]
+include = ["drms*"]
+exclude = ["drms._dev*"]
-[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,requestor"
+[tool.setuptools_scm]
+write_to = "drms/_version.py"
[ tool.gilesbot ]
[ tool.gilesbot.pull_requests ]
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000..e2bf1c7
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,49 @@
+[pytest]
+minversion = 7.0
+testpaths =
+ drms
+ docs
+norecursedirs =
+ .tox
+ build
+ docs/_build
+ docs/generated
+ *.egg-info
+ examples
+ drms/_dev
+ .history
+ drms/extern
+doctest_plus = enabled
+doctest_optionflags =
+ NORMALIZE_WHITESPACE
+ FLOAT_CMP
+ ELLIPSIS
+text_file_format = rst
+addopts =
+ --doctest-rst
+ -p no:unraisableexception
+ -p no:threadexception
+markers =
+ remote_data: marks this test function as needing remote data.
+ jsoc: marks the test function as needing a connection to JSOC.
+ kis: marks the test function as needing a connection to KIS.
+ flaky: from sunpy
+remote_data_strict = True
+log_cli=true
+log_level=INFO
+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
+ # This is due to dependencies building with a numpy version different from
+ # the local installed numpy version, but should be fine
+ # See https://github.com/numpy/numpy/issues/15748#issuecomment-598584838
+ ignore:numpy.ufunc size changed:RuntimeWarning
+ ignore:numpy.ndarray size changed:RuntimeWarning
+ # https://github.com/pytest-dev/pytest-cov/issues/557
+ ignore:The --rsyncdir command line argument and rsyncdirs config variable are deprecated.:DeprecationWarning
+ ignore:.*is deprecated and slated for removal in Python 3:DeprecationWarning
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 4b98710..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,92 +0,0 @@
-[metadata]
-name = drms
-provides = drms
-description = Access HMI, AIA and MDI data from the Standford JSOC DRMS
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = The SunPy Community
-author_email = sunpy@googlegroups.com
-license = BSD 2-Clause
-license_files = LICENSE.rst
-url = https://sunpy.org
-edit_on_github = True
-github_project = sunpy/drms
-platform = any
-keywords = solar physics, solar, science, data
-classifiers =
- Development Status :: 5 - Production/Stable
- Intended Audience :: Science/Research
- License :: OSI Approved :: BSD License
- Natural Language :: English
- Operating System :: OS Independent
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.10
- Programming Language :: Python :: 3.11
- Programming Language :: Python :: 3.12
- Topic :: Scientific/Engineering :: Astronomy
- Topic :: Scientific/Engineering :: Physics
-
-[options]
-zip_safe = False
-python_requires = >=3.10
-packages = find:
-include_package_data = True
-setup_requires =
- setuptools_scm
-install_requires=
- numpy
- pandas
- packaging
-
-[options.extras_require]
-tests =
- pytest-astropy
- tox
-docs =
- astropy
- matplotlib
- sphinx
- sphinx-automodapi
- sphinx-changelog
- sphinx-copybutton
- sphinx-gallery
- sphinx-hoverxref
- sphinxext-opengraph
- sunpy-sphinx-theme
- # Remove next line when fixed in towncrier; see https://github.com/twisted/towncrier/issues/528
- importlib-resources<6
-
-[options.packages.find]
-exclude = drms._dev
-
-[options.entry_points]
-console_scripts =
- drms = drms.main:main
-
-[tool:pytest]
-testpaths = "drms" "docs"
-norecursedirs = ".tox" "build" "docs[\/]_build" "docs[\/]generated" "*.egg-info" "examples" ".history" "paper" "drms[\/]_dev"
-log_cli=true
-log_level=INFO
-doctest_plus = enabled
-doctest_optionflags = NORMALIZE_WHITESPACE FLOAT_CMP ELLIPSIS
-addopts = --doctest-rst -p no:unraisableexception -p no:threadexception
-markers =
- remote_data: marks this test function as needing remote data.
- jsoc: marks the test function as needing a connection to JSOC.
- kis: marks the test function as needing a connection to KIS.
- flaky: from sunpy
-remote_data_strict = True
-filterwarnings =
- error
- # Do not fail on pytest config issues (i.e. missing plugins) but do show them
- always::pytest.PytestConfigWarning
- # This is due to dependencies building with a numpy version different from
- # the local installed numpy version, but should be fine
- # See https://github.com/numpy/numpy/issues/15748#issuecomment-598584838
- ignore:numpy.ufunc size changed:RuntimeWarning
- ignore:numpy.ndarray size changed:RuntimeWarning
- # https://github.com/pytest-dev/pytest-cov/issues/557
- ignore:The --rsyncdir command line argument and rsyncdirs config variable are deprecated.:DeprecationWarning
- ignore:.*is deprecated and slated for removal in Python 3:DeprecationWarning
diff --git a/setup.py b/setup.py
index 9bfacfa..c823345 100644
--- a/setup.py
+++ b/setup.py
@@ -1,29 +1,4 @@
#!/usr/bin/env python
-from pathlib import Path
-from itertools import chain
-
from setuptools import setup
-try:
- # Recommended for setuptools 61.0.0+
- # (though may disappear in the future)
- from setuptools.config.setupcfg import read_configuration
-except ImportError:
- from setuptools.config import read_configuration
-
-################################################################################
-# Programmatically generate some extras combos.
-################################################################################
-
-extras = read_configuration("setup.cfg")["options"]["extras_require"]
-# Dev is everything
-extras["dev"] = list(chain(*list(extras.values())))
-# All is everything but tests and docs
-exclude_keys = ("tests", "docs", "dev")
-ex_extras = dict([i for i in list(extras.items()) if i[0] not in exclude_keys])
-# Concatenate all the values together for 'all'
-extras["all"] = list(chain.from_iterable(list(ex_extras.values())))
-setup(
- extras_require=extras,
- use_scm_version={"write_to": Path("drms") / "_version.py"},
-)
+setup()
diff --git a/tox.ini b/tox.ini
index 6055f3e..f08d4b0 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,37 +1,53 @@
[tox]
min_version = 4.0
+requires =
+ tox-pypi-filter>=0.14
envlist =
- py{310,311,312}{,-online,-sunpy,-oldestdeps}
- build_docs
+ py{310,311,312}{,-online,-sunpy}
+ py312-devdeps
+ py310-oldestdeps
codestyle
-requires =
- tox-pypi-filter
+ build_docs
[testenv]
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 drms from the source tree
-changedir = .tmp/{envname}
+# 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
online: that require remote data
sunpy: run the sunpy jsoc tests to ensure we dont break them
+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
+ # HTTP Proxy
+ HTTP_PROXY
+ HTTPS_PROXY
+ NO_PROXY
setenv =
MPLBACKEND = agg
COLUMNS = 180
PYTEST_COMMAND = pytest -vvv -s -ra --pyargs drms --cov-report=xml --cov=drms --cov-config={toxinidir}/setup.cfg {toxinidir}/docs
build_docs,online: HOME = {envtmpdir}
JSOC_EMAIL = jsoc@sunpy.org
-passenv =
- HTTP_PROXY
- HTTPS_PROXY
- NO_PROXY
- CIRCLECI
deps =
+ # 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
+ # The following indicates which extras_require will be installed
pytest-xdist
pytest-timeout
- # Oldest deps we pin against
- oldestdeps: numpy<2.0
- oldestdeps: pandas<2.0
# These are specific extras we use to run the sunpy tests.
sunpy: git+https://github.com/sunpy/sunpy
sunpy: beautifulsoup4
@@ -43,21 +59,27 @@ deps =
sunpy: tqdm
sunpy: zeep
extras =
- dev
-commands =
+ tests
+commands_pre =
+ oldestdeps: minimum_dependencies drms --filename requirements-min.txt
+ oldestdeps: pip install -r requirements-min.txt
pip freeze --all --no-input
- sunpy: pytest -vvv -s -ra --pyargs sunpy.net.jsoc --timeout=120 --remote-data=any {posargs}
- !online: {env:PYTEST_COMMAND} {posargs}
- online: {env:PYTEST_COMMAND} --timeout=120 --remote-data=any {posargs}
-
-[testenv:build_docs]
-changedir = docs
-description = Invoke sphinx-build to build the HTML docs
-extras = dev
commands =
- pip freeze --all --no-input
- sphinx-build -j 1 --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" / "html"/ "index.html"))'
+ # To amend the pytest command for different factors you can add a line
+ # which starts with a factor like `online: --remote-data=any \`
+ # If you have no factors which require different commands this is all you need:
+ pytest \
+ -vvv \
+ -r fEs \
+ !sunpy: --pyargs drms \
+ sunpy: --pyargs sunpy.net.jsoc \
+ --cov-report=xml \
+ --cov=drms \
+ --cov-config={toxinidir}/.coveragerc \
+ online: --timeout=120 \
+ online,sunpy: --remote-data=any \
+ !sunpy: {toxinidir}/docs \
+ {posargs}
[testenv:codestyle]
pypi_filter =
@@ -67,4 +89,15 @@ deps =
pre-commit
commands =
pre-commit install-hooks
- pre-commit run --verbose --all-files --show-diff-on-failure
+ 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 -j 1 --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" / "html"/ "index.html"))'