From 8c9c13a5cc71c6fa78dda89a2d96b61a8324c18d Mon Sep 17 00:00:00 2001 From: Paul Wright Date: Tue, 17 Sep 2024 14:54:20 +0100 Subject: [PATCH] Initial templating (#2) Co-authored-by: Shane Maloney --- .cruft.json | 31 +++++ .flake8 | 27 ++++ .github/workflows/ci.yml | 102 +++++++++++++++ .github/workflows/sub_package_update.yml | 84 ++++++++++++ .gitignore | 160 +++++++++++++++++++++++ .pre-commit-config.yaml | 29 ++++ .readthedocs.yaml | 29 ++++ .rtd-environment.yaml | 6 + .ruff.toml | 35 +++++ MANIFEST.in | 11 ++ README.rst | 44 ++++++- docs/Makefile | 20 +++ docs/conf.py | 83 ++++++++++++ docs/index.rst | 15 +++ docs/make.bat | 35 +++++ licenses/LICENSE.rst | 25 ++++ licenses/README.rst | 9 ++ licenses/TEMPLATE_LICENSE.rst | 31 +++++ magiepy/__init__.py | 3 + magiepy/_dev/__init__.py | 6 + magiepy/_dev/scm_version.py | 12 ++ magiepy/data/README.rst | 6 + magiepy/tests/__init__.py | 3 + magiepy/tests/test_example.py | 2 + magiepy/version.py | 17 +++ pyproject.toml | 87 ++++++++++++ setup.py | 4 + tox.ini | 64 +++++++++ 28 files changed, 979 insertions(+), 1 deletion(-) create mode 100644 .cruft.json create mode 100644 .flake8 create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/sub_package_update.yml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 .readthedocs.yaml create mode 100644 .rtd-environment.yaml create mode 100644 .ruff.toml create mode 100644 MANIFEST.in create mode 100644 docs/Makefile create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/make.bat create mode 100644 licenses/LICENSE.rst create mode 100644 licenses/README.rst create mode 100644 licenses/TEMPLATE_LICENSE.rst create mode 100644 magiepy/__init__.py create mode 100644 magiepy/_dev/__init__.py create mode 100644 magiepy/_dev/scm_version.py create mode 100644 magiepy/data/README.rst create mode 100644 magiepy/tests/__init__.py create mode 100644 magiepy/tests/test_example.py create mode 100644 magiepy/version.py create mode 100644 pyproject.toml create mode 100755 setup.py create mode 100644 tox.ini diff --git a/.cruft.json b/.cruft.json new file mode 100644 index 0000000..7340b2d --- /dev/null +++ b/.cruft.json @@ -0,0 +1,31 @@ +{ + "template": "https://github.com/OpenAstronomy/packaging-guide", + "commit": "ad6da17e1d8fd96456566abed30b510bf8b5f8c8", + "checkout": null, + "context": { + "cookiecutter": { + "package_name": "MagIEpy", + "module_name": "magiepy", + "short_description": "Python utilities for the Magnetometer Network of Ireland (MagIE)", + "author_name": "DIAS Solar", + "author_email": "", + "project_url": "magie.ie", + "license": "BSD 3-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/OpenAstronomy/packaging-guide" + } + }, + "directory": null +} diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..8dc28c3 --- /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 + MagIEpy/__init__.py, +rst-directives = + plot diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a96351e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,102 @@ + +name: CI + +on: + push: + branches: + - 'main' + - '*.*' + - '!*backport*' + tags: + - 'v*' + - '!*dev*' + - '!*pre*' + - '!*post*' + pull_request: + # Allow manual runs through the web UI + 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 + 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.10' + - 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, sdist_verify] + uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main + with: + submodules: false + coverage: codecov + toxdeps: tox-pypi-filter + posargs: + envs: | + - windows: py311 + - macos: py310 + - 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.10' + submodules: false + pytest: false + toxdeps: tox-pypi-filter + libraries: | + apt: + - graphviz + envs: | + - linux: build_docs + + 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: + default_python: '3.10' + submodules: false + coverage: codecov + toxdeps: tox-pypi-filter + envs: | + - linux: py311-devdeps + secrets: + 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.10' + test_extras: 'test' + test_command: 'pytest -p no:warnings --doctest-rst --pyargs magiepy' + 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 new file mode 100644 index 0000000..9e7a5f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +magiepy/_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/ + +# 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 + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.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/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..3ee38be --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,29 @@ +repos: + # This should be before any formatting hooks like isort + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.4.8" + hooks: + - id: ruff + args: ["--fix"] + # Run the formatter. + - id: ruff-format + - repo: https://github.com/PyCQA/isort + rev: 5.13.2 + hooks: + - id: isort + exclude: ".*(.fits|.fts|.fit|.header|.txt|tca.*|extern.*)$" + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-ast + - id: check-case-conflict + - id: trailing-whitespace + 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.*)$" diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..790abab --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,29 @@ +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "mambaforge-4.10" + 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.yaml b/.rtd-environment.yaml new file mode 100644 index 0000000..b651cf0 --- /dev/null +++ b/.rtd-environment.yaml @@ -0,0 +1,6 @@ +name: magie +channels: + - conda-forge +dependencies: + - python=3.10 + - pip diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 0000000..3feeab2 --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,35 @@ +target-version = "py310" +line-length = 110 +exclude = [ + ".git,", + "__pycache__", + "build", + "MagIEpy/version.py", +] + +[lint] +select = ["E", "F", "W", "UP", "PT"] +extend-ignore = [ + # pytest (PT) + "PT001", # Always use pytest.fixture() + "PT004", # Fixtures which don't return anything should have leading _ + "PT023", # Always use () on pytest decorators +] + +[lint.flake8-tidy-imports] +[lint.flake8-tidy-imports.banned-api] +"warnings.warn".msg = "Use sunpy specific warning helpers warn_* from sunpy.utils.exceptions" + +[lint.per-file-ignores] +# Part of configuration, not a package. +"setup.py" = ["INP001"] +"conftest.py" = ["INP001"] +# Implicit-namespace-package. The examples are not a package. +"docs/*.py" = ["INP001", "E402"] +"__init__.py" = ["E402", "F401", "F403"] +"test_*.py" = ["B011", "D", "E402", "PGH001", "S101"] +# Need to import clients to register them, but don't use them in file +"MagIEpy/net/__init__.py" = ["F811"] + +[lint.pydocstyle] +convention = "numpy" diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..bfdccd7 --- /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 magiepy/_dev diff --git a/README.rst b/README.rst index 355d5c9..a299e35 100644 --- a/README.rst +++ b/README.rst @@ -1 +1,43 @@ -# MagIEpy +Python utilities for the Magnetometer Network of Ireland (MagIE) +---------------------------------------------------------------- + +License +------- + +This project is Copyright (c) DIAS Solar and licensed under +the terms of the BSD 3-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 +------------ + +We love contributions! MagIEpy 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 +MagIEpy based on its use in the README file for the +`MetPy project `_. 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/conf.py b/docs/conf.py new file mode 100644 index 0000000..09f7309 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,83 @@ +# 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 datetime + +# The full version, including alpha/beta/rc tags +from magiepy import __version__ + +# -- Project information ----------------------------------------------------- + + +release = __version__ + +project = "MagIEpy" +author = "DIAS Solar" +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 = [ + "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", +] + +# Add any paths that contain templates here, relative to this directory. +# templates_path = ["_templates"] + +# 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. +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" + +# Treat everything in single ` as a Python reference. +default_role = "py:obj" + +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {"python": ("https://docs.python.org/", None)} + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = "alabaster" + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = ["_static"] + +# By default, when rendering docstrings for classes, sphinx.ext.autodoc will +# make docs with the class-level docstring and the class-method docstrings, +# but not the __init__ docstring, which often contains the parameters to +# class constructors across the scientific Python ecosystem. The option below +# will append the __init__ docstring to the class-level docstring when rendering +# the docs. For more options, see: +# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autoclass_content +autoclass_content = "both" + +# -- Other options ---------------------------------------------------------- diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..5d7054f --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,15 @@ +MagIEpy Documentation +--------------------- + +This is the documentation for MagIEpy. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` 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/licenses/LICENSE.rst b/licenses/LICENSE.rst new file mode 100644 index 0000000..c0bae65 --- /dev/null +++ b/licenses/LICENSE.rst @@ -0,0 +1,25 @@ +Copyright (c) 2024, DIAS Solar +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/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/magiepy/__init__.py b/magiepy/__init__.py new file mode 100644 index 0000000..20b38d5 --- /dev/null +++ b/magiepy/__init__.py @@ -0,0 +1,3 @@ +from .version import version as __version__ + +__all__ = [] diff --git a/magiepy/_dev/__init__.py b/magiepy/_dev/__init__.py new file mode 100644 index 0000000..72583c0 --- /dev/null +++ b/magiepy/_dev/__init__.py @@ -0,0 +1,6 @@ +""" +This package contains utilities that are only used when developing drms in a +copy of the source repository. +These files are not installed, and should not be assumed to exist at +runtime. +""" diff --git a/magiepy/_dev/scm_version.py b/magiepy/_dev/scm_version.py new file mode 100644 index 0000000..b9afb1d --- /dev/null +++ b/magiepy/_dev/scm_version.py @@ -0,0 +1,12 @@ +# Try to use setuptools_scm to get the current version; this is only used +# in development installations from the git repository. +import os.path + +try: + from setuptools_scm import get_version + + version = get_version(root=os.path.join("..", ".."), relative_to=__file__) +except ImportError: + raise +except Exception as e: + raise ValueError("setuptools_scm can not determine version.") from e diff --git a/magiepy/data/README.rst b/magiepy/data/README.rst new file mode 100644 index 0000000..382f6e7 --- /dev/null +++ b/magiepy/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/magiepy/tests/__init__.py b/magiepy/tests/__init__.py new file mode 100644 index 0000000..92ea707 --- /dev/null +++ b/magiepy/tests/__init__.py @@ -0,0 +1,3 @@ +""" +This module contains package tests. +""" diff --git a/magiepy/tests/test_example.py b/magiepy/tests/test_example.py new file mode 100644 index 0000000..ca4655d --- /dev/null +++ b/magiepy/tests/test_example.py @@ -0,0 +1,2 @@ +def test_addition(): + assert 1 + 1 == 2 diff --git a/magiepy/version.py b/magiepy/version.py new file mode 100644 index 0000000..90d4111 --- /dev/null +++ b/magiepy/version.py @@ -0,0 +1,17 @@ +# NOTE: First try _dev.scm_version if it exists and setuptools_scm is installed +# This file is not included in wheels/tarballs, so otherwise it will +# fall back on the generated _version module. +try: + try: + from ._dev.scm_version import version + except ImportError: + from ._version import version +except Exception: + import warnings + + warnings.warn( + f'could not determine {__name__.split(".")[0]} package version; this indicates a broken installation' + ) + del warnings + + version = "0.0.0" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a7cef73 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,87 @@ +[build-system] +requires = [ + "setuptools>=62.1", + "setuptools_scm[toml]>=6.2", + "wheel",] +build-backend = "setuptools.build_meta" + +[project] +name = "magiepy" +description = "Python utilities for the Magnetometer Network of Ireland (MagIE)" +requires-python = ">=3.10" +readme = { file = "README.rst", content-type = "text/x-rst" } +license = { file = "licenses/LICENSE.rst" } +dependencies = [] +dynamic = ["version"] + +[project.optional-dependencies] +test = [ + "pytest", + "pytest-doctestplus", + "pytest-cov" +] +docs = [ + "sphinx", + "sphinx-automodapi", +] + +[project.urls] +repository = "magiepy.readthedocs.io" + +[tool.setuptools] +zip-safe = false +include-package-data = true + +[tool.setuptools.packages.find] +exclude = ["magiepy._dev*"] + +[tool.setuptools_scm] +write_to = "magiepy/_version.py" + +[tool.pytest.ini_options] +testpaths = [ + "magiepy", + "docs", +] +doctest_plus = "enabled" +text_file_format = "rst" +addopts = "--doctest-rst" + +[tool.coverage.run] +omit = [ + "magiepy/__init*", + "magiepy/conftest.py", + "magiepy/*setup_package*", + "magiepy/tests/*", + "magiepy/*/tests/*", + "magiepy/extern/*", + "magiepy/version*", + "*/magiepy/__init*", + "*/magiepy/conftest.py", + "*/magiepy/*setup_package*", + "*/magiepy/tests/*", + "*/magiepy/*/tests/*", + "*/magiepy/extern/*", + "*/magiepy/version*", +] + +[tool.coverage.report] +exclude_lines = [ + # Have to re-enable the standard pragma + "pragma: no cover", + # Don't complain about packages we have installed + "except ImportError", + # Don't complain if tests don't hit assertions + "raise AssertionError", + "raise NotImplementedError", + # Don't complain about script hooks + "def main(.*):", + # Ignore branches that don't pertain to this version of Python + "pragma: py{ignore_python_version}", + # Don't complain about IPython completion helper + "def _ipython_key_completions_", + # typing.TYPE_CHECKING is False at runtime + "if TYPE_CHECKING:", + # Ignore typing overloads + "@overload", +] diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..c823345 --- /dev/null +++ b/setup.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python +from setuptools import setup + +setup() diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..2501d1c --- /dev/null +++ b/tox.ini @@ -0,0 +1,64 @@ +[tox] +min_version = 4.0 +envlist = + py{310,311,312}-test + py10-test-oldestdeps + build_docs + +[testenv] +# tox environments are constructed with so-called 'factors' (or terms) +# separated by hyphens, e.g. test-devdeps-cov. Lines below starting with factor: +# will only take effect if that factor is included in the environment name. To +# see a list of example environments that can be run, along with a description, +# run: +# +# tox -l -v +# +description = + run tests + oldestdeps: with the oldest supported version of key dependencies + +# Pass through the following environment variables which may be needed for the CI +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 + # (note LANG is automatically passed through by tox) + LC_ALL + +# Suppress display of matplotlib plots generated during docs build +set_env = + MPLBACKEND = agg + +# 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} + +deps = + oldestdeps: minimum_dependencies + pytest-cov + +# The following indicates which extras_require from setup.cfg will be installed +extras = + test + +commands_pre = + oldestdeps: minimum_dependencies magiepy --filename requirements-min.txt + oldestdeps: pip install -r requirements-min.txt + pip freeze + +commands = + pytest --pyargs magiepy --cov magiepy --cov-report xml:coverage.xml --cov-report term-missing {posargs} + +[testenv:build_docs] +description = invoke sphinx-build to build the HTML docs +change_dir = + docs +extras = + docs +commands = + sphinx-build -j auto --color -W --keep-going -b html -d _build/.doctrees . _build/html {posargs}