diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d9bbbaf --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,85 @@ +name: CI + +on: + push: + branches: + - '*' + - '!*backport*' + tags: + - 'v*' + - '!*dev*' + - '!*pre*' + - '!*post*' + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + core: + uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main + with: + submodules: false + coverage: codecov + toxdeps: tox-pypi-filter + posargs: -n auto + libraries: | + apt: + - libopenjp2-7 + envs: | + - linux: py310 + - linux: codestyle + test: + needs: [core] + uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main + with: + submodules: false + coverage: codecov + toxdeps: tox-pypi-filter + posargs: -n auto + libraries: | + apt: + - libopenjp2-7 + brew: + - openjpeg + envs: | + - macos: py38 + - windows: py39 + online: + needs: [core] + uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main + with: + default_python: '3.8' + submodules: false + coverage: codecov + toxdeps: tox-pypi-filter + libraries: | + apt: + - libopenjp2-7 + - linux: py39-online + - linux: build_docs + publish: + # Build wheels when pushing to any branch except main + # publish.yml will only publish if tagged ^v.* + if: | + ( + github.event_name != 'pull_request' && ( + github.ref_name != 'main' || + github.event_name == 'workflow_dispatch' + ) + ) || ( + github.event_name == 'pull_request' && + contains(github.event.pull_request.labels.*.name, 'Run publish') + ) + needs: [test] + uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish.yml@main + with: + test_extras: 'all tests' + test_command: 'pytest -p no:warnings --doctest-rst -m "not mpl_image_compare" --pyargs hvpy' + submodules: false + targets: | + - universal2 + secrets: + pypi_token: ${{ secrets.pypi_token }} diff --git a/.gitignore b/.gitignore index b6e4761..59293b7 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,11 @@ dmypy.json # Pyre type checker .pyre/ + +# vscode +.vscode +.history + +# Verison file is created at install, not to be commited. +version.py +docs/api/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..42b79ab --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +repos: + - repo: https://github.com/myint/docformatter + rev: v1.4 + hooks: + - id: docformatter + args: [--in-place, --pre-summary-newline, --make-summary-multi] + - repo: https://github.com/myint/autoflake + rev: v1.4 + hooks: + - id: autoflake + args: ['--in-place', '--remove-all-unused-imports', '--remove-unused-variable'] + exclude: ".*(.fits|.fts|.fit|.txt|tca.*|extern.*|.rst|.md|__init__.py|docs/conf.py)$" + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" + - repo: https://github.com/timothycrosley/isort + rev: 5.10.1 + hooks: + - id: isort + exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.2.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 diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..0aeaeee --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,18 @@ +version: 2 +build: + os: ubuntu-20.04 + tools: + python: "3.9" + +sphinx: + builder: html + configuration: docs/conf.py + fail_on_warning: false + +python: + install: + - method: pip + extra_requirements: + - all + - docs + path: . diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..6507979 --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,5 @@ +v0.0.1 (2022-11-11) +=================== + +Features +-------- diff --git a/LICENSE b/LICENSE index defc563..eec86db 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 2-Clause License -Copyright (c) 2022, Helioviewer-Project +Copyright (c) 2022, Helioviewer Project All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..09ac3e8 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,19 @@ +# 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 +prune .circleci +prune .github +prune .jupyter +prune binder + +# exclude a bunch of common hidden files, you probably want to add your own here +exclude .mailmap +exclude .gitignore +exclude .gitattributes +exclude .editorconfig +exclude .zenodo.json +exclude *.yml +exclude *.yaml diff --git a/README.md b/README.md deleted file mode 100644 index 81713c8..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# python-api -Python code that uses the Helioviewer API. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..e64a359 --- /dev/null +++ b/README.rst @@ -0,0 +1,4 @@ +Helioviewer Python API Wrapper +------------------------------ + +``hvpy`` is a Python API wrapper around the formal `Helioviewer API `__. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d4bb2cb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 0000000..1b63e0a --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,7 @@ +************* +API Reference +************* + +.. automodapi:: hvpy + :inherited-members: + :include-all-objects: diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..9dbc17b --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,59 @@ +""" +Configuration file for the Sphinx documentation builder. +""" +from datetime import datetime + +# -- Project information ----------------------------------------------------- +project = "hvpy" +author = "The Helioviewer Project" +copyright = f"{datetime.now().year}, {author}" +from hvpy import __version__ + +release = __version__ + +# -- General configuration --------------------------------------------------- +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.coverage", + "sphinx.ext.inheritance_diagram", + "sphinx.ext.viewcode", + "sphinx.ext.napoleon", + "sphinx.ext.doctest", + "sphinx.ext.mathjax", + "sphinx_automodapi.automodapi", + "sphinx_automodapi.smart_resolver", +] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +source_suffix = ".rst" +master_doc = "index" + +# Enable nitpicky mode, which forces links to be non-broken +nitpicky = True + +# -- Options for intersphinx extension ----------------------------------------- +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = { + "python": ( + "https://docs.python.org/3/", + (None, "http://www.astropy.org/astropy-data/intersphinx/python3.inv"), + ), + "numpy": ( + "https://numpy.org/doc/stable/", + (None, "http://www.astropy.org/astropy-data/intersphinx/numpy.inv"), + ), + "scipy": ( + "https://docs.scipy.org/doc/scipy/reference/", + (None, "http://www.astropy.org/astropy-data/intersphinx/scipy.inv"), + ), + "matplotlib": ("https://matplotlib.org/stable", None), + "aiapy": ("https://aiapy.readthedocs.io/en/stable/", None), + "astropy": ("https://docs.astropy.org/en/stable/", None), + "requests": ("https://requests.readthedocs.io/en/stable/", None), +} + +# -- Options for HTML output --------------------------------------------------- +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +from sunpy_sphinx_theme.conf import * # NOQA diff --git a/docs/guide.rst b/docs/guide.rst new file mode 100644 index 0000000..5105b85 --- /dev/null +++ b/docs/guide.rst @@ -0,0 +1,5 @@ +********** +User Guide +********** + +This is how you install and use ``hvpy``. diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..1bbaec2 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,11 @@ +****************** +hvpy Documentation +****************** + +This is the documentation for ``hvpy``. + +.. toctree:: + :maxdepth: 2 + + guide + api diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..922152e --- /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/hvpy/__init__.py b/hvpy/__init__.py new file mode 100644 index 0000000..327412a --- /dev/null +++ b/hvpy/__init__.py @@ -0,0 +1,2 @@ +from .api import * # NOQA +from .version import __version__ diff --git a/hvpy/api.py b/hvpy/api.py new file mode 100644 index 0000000..8388e3d --- /dev/null +++ b/hvpy/api.py @@ -0,0 +1,13 @@ +__all__ = ["fake_api_call"] + + +def fake_api_call(): + """ + _summary_ + + Returns + ------- + _type_ + _description_ + """ + return {} diff --git a/hvpy/tests/__init__.py b/hvpy/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hvpy/tests/test_fake.py b/hvpy/tests/test_fake.py new file mode 100644 index 0000000..c815117 --- /dev/null +++ b/hvpy/tests/test_fake.py @@ -0,0 +1,9 @@ +from hvpy import fake_api_call + + +def test_test_fake(): + assert True + + +def test_fake_api_call(): + assert fake_api_call() == {} diff --git a/licenses/LICENSE.rst b/licenses/LICENSE.rst new file mode 100644 index 0000000..c8a65a8 --- /dev/null +++ b/licenses/LICENSE.rst @@ -0,0 +1,9 @@ +Copyright 2022 Helioviewer Project + +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/licenses/TEMPLATE_LICENSE.rst b/licenses/TEMPLATE_LICENSE.rst new file mode 100644 index 0000000..f29177b --- /dev/null +++ b/licenses/TEMPLATE_LICENSE.rst @@ -0,0 +1,31 @@ +This project is based upon the Astropy package template +(https://github.com/astropy/package-template/) which is licenced under the terms +of the following licence. + +--- + +Copyright (c) 2018, Astropy Developers +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* 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. +* Neither the name of the Astropy Team nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +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/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..56653b3 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,28 @@ +[build-system] +requires = [ + "setuptools>=56,!=61.0.0", + "setuptools_scm[toml]>=6.2", + "wheel", + ] +build-backend = 'setuptools.build_meta' + +[tool.black] +line-length = 120 +include = '\.pyi?$' +exclude = ''' +( + /( + \.eggs + | \.git + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + | docs + | .history + )/ +) +''' diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..8711e67 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,110 @@ +[metadata] +name = hvpy +author = The Helioviewer Project +author_email = contact@helioviewer.org +license = BSD 2-Clause +license_file = licenses/LICENSE.rst +url = https://helioviewer.org/ +description = Helioviewer Python API Wrapper +long_description = file: README.rst +edit_on_github = True +github_project = Helioviewer-Project/python-api +platform = any +keywords = solar physics, solar, science, sun, data, helioviewer +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.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Topic :: Scientific/Engineering :: Physics + +[options] +zip_safe = True +packages = find: +include_package_data = True +python_requires = >=3.8 +setup_requires = + setuptools_scm +install_requires = + requests>=2.27.0 + +[options.extras_require] +tests = + pytest-astropy>=0.10 + pytest>=6.0 +docs = + sphinx + sphinx-automodapi + sunpy-sphinx-theme + +[tool:pytest] +testpaths = "hvpy" "docs" +norecursedirs = ".tox" "build" "docs[\/]_build" "docs[\/]generated" "*.egg-info" "examples" ".jupyter" ".history" +doctest_plus = enabled +doctest_optionflags = NORMALIZE_WHITESPACE FLOAT_CMP ELLIPSIS +addopts = --doctest-rst --doctest-ignore-import-errors -p no:unraisableexception -p no:threadexception +markers = + remote_data: marks this test function as needing remote data. +remote_data_strict = True +filterwarnings = + 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 + # + # + ignore:distutils Version classes are deprecated. Use packaging.version instead. + +[isort] +balanced_wrapping = True +default_section = THIRDPARTY +include_trailing_comma = True +known_first_party = hvpy +length_sort = False +length_sort_sections=stdlib +line_length = 120 +multi_line_output = 3 +no_lines_before = LOCALFOLDER +sections = STDLIB, THIRDPARTY, FIRSTPARTY, LOCALFOLDER + +[coverage:run] +omit = + hvpy/__init* + hvpy/conftest.py + hvpy/*setup_package* + hvpy/tests/* + hvpy/*/tests/* + hvpy/extern/* + hvpy/version* + */hvpy/__init* + */hvpy/conftest.py + */hvpy/*setup_package* + */hvpy/tests/* + */hvpy/*/tests/* + */hvpy/extern/* + */hvpy/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_ diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..eaa521f --- /dev/null +++ b/setup.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +import os + +from setuptools import setup + +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("hvpy", "version.py"), "write_to_template": VERSION_TEMPLATE}, +) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..b483cd6 --- /dev/null +++ b/tox.ini @@ -0,0 +1,50 @@ +[tox] +envlist = + py{38,39,310}{,-online} + build_docs + codestyle +requires = + setuptools >=56, !=61.0.0 + pip >= 19.3.1 +isolated_build = true + +[testenv] +passenv = HOME WINDIR LC_ALL LC_CTYPE CC CI TRAVIS +setenv = + PYTEST_COMMAND = pytest -vvv -r a --pyargs hvpy --cov-report=xml --cov=hvpy --cov-config={toxinidir}/setup.cfg {toxinidir}/docs + HIDE_PARFIVE_PROGESS = True +# Run the tests in a temporary directory to make sure that we don't import +# the package from the source tree +changedir = .tmp/{envname} +description = + run tests + online: that require remote data (as well as the offline ones) +deps = +extras = + all + tests +commands = + pip freeze --all --no-input + !online: {env:PYTEST_COMMAND} {posargs} + online: {env:PYTEST_COMMAND} --remote-data=any {posargs} + +[testenv:build_docs] +changedir = docs +description = invoke sphinx-build to build the HTML docs +extras = + all + docs +commands = + pip freeze --all --no-input + sphinx-build -j auto --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"))' + +[testenv:codestyle] +pypi_filter = +skip_install = true +description = Run all style and file checks with pre-commit +deps = + pre-commit +commands = + pre-commit install-hooks + pre-commit run --color always --all-files --show-diff-on-failure