From 2ef02f2854edb6c22e9d5ac7fe1172fbb4e5f746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Villase=C3=B1or?= Date: Fri, 26 Jan 2024 14:10:26 +0100 Subject: [PATCH] Initial commit --- .github/workflows/ci.yml | 38 +++++++ .github/workflows/docs.yml | 56 +++++++++++ .gitignore | 132 ++++++++++++++++++++++++ CITATION.cff | 26 +++++ CODE_OF_CONDUCT.md | 37 +++++++ LICENSE | 29 ++++++ README.md | 201 +++++++++++++++++++++++++++++++++++++ docs/Makefile | 20 ++++ docs/conf.py | 53 ++++++++++ docs/index.rst | 67 +++++++++++++ docs/make.bat | 35 +++++++ pyproject.toml | 65 ++++++++++++ src/my_package/__init__.py | 7 ++ src/my_package/example.py | 21 ++++ tests/test_example.py | 20 ++++ 15 files changed, 807 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/docs.yml create mode 100644 .gitignore create mode 100644 CITATION.cff create mode 100644 CODE_OF_CONDUCT.md create mode 100644 LICENSE create mode 100644 README.md 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 pyproject.toml create mode 100644 src/my_package/__init__.py create mode 100644 src/my_package/example.py create mode 100644 tests/test_example.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..af9c741 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,38 @@ +name: ci + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11"] + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install ".[test]" + + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + + - name: Test with pytest + run: | + pytest tests diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..92c8323 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,56 @@ +name: sphinxdocumentation + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + + + - name: Install docs dependencies + run: | + pip install --upgrade pip + pip install -e ".[docs]" + + - name: Build docs + working-directory: ./docs + run: | + make html +# uses: ammaraskar/sphinx-action@master +# with: +# docs-folder: "docs/" + + # Publish built docs to gh-pages branch. + # =============================== + - name: Commit documentation changes + run: | + git clone https://github.com/ammaraskar/sphinx-action-test.git --branch gh-pages --single-branch gh-pages + cp -r docs/_build/html/* gh-pages/ + cd gh-pages + touch .nojekyll + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add . + git commit -m "Update documentation" -a || true + # The above command will fail if no changes were present, so we ignore + # that. + - name: Push changes + uses: ad-m/github-push-action@master + with: + branch: gh-pages + directory: gh-pages + github_token: ${{ secrets.GITHUB_TOKEN }} + force: true + # =============================== diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5a19920 --- /dev/null +++ b/.gitignore @@ -0,0 +1,132 @@ +.DS_Store +# 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/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*_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/ + +# 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/ +docs/api/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.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 + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__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/ diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..54a7345 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,26 @@ +cff-version: 1.2.0 +title: my_package +message: If you use this software, please cite as below. +date-released: 2022-03-29 +url: 'https://github.com/mpi-astronomy/mpia-python-template' +version: 0.0.1 +type: software +authors: + - family-names: Name + given-names: Author + email: author.name@email.com + affiliation: MPIA + orcid: 'https://orcid.org/0000-0003-1665-2073' + +# For citing software, see: + +# http://journals.aas.org/authors/references.html + +# GitHub has Zenodo DOI integration: +# https://guides.github.com/activities/citable-code/ + +# What is a CITATION.cff file: +# https://citation-file-format.github.io/ + +# This CITATION.cff file was generated with cffinit. +# Visit https://bit.ly/cffinit to generate yours today! diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..3aa21fb --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,37 @@ +We are committed to providing a strong and +enforced code of conduct and expect everyone in our community to follow these +guidelines when interacting with others in all forums. Our goal is to keep ours +a positive, inclusive, successful, and growing community. + +[ All Max Planck Institute for Astronomy (MPIA) researchers are bound to adhere to the +[Max Plack Society Code of Conduct](https://www.mpg.de/14172230/code-of-conduct.pdf) and the [MPIA Work Agreement](https://intranet.mpia.de/4404342/03-Works-agreement-code-of-conduct.pdf) (intranet link). All MPIA employees should attach importance to creating a respectful and healthy atmosphere +and a level playing field for research and work. Their goal is to ensure good working conditions +for everyone and to provide the basis for individual job satisfaction, personal development, +motivation, collegiality and positive interpersonal relations. ] + +[ Interactions on GitHub are not limited to those between MPIA employees.] The community of +participants in open source astronomy projects is made up of members from +around the globe with a diverse set of skills, personalities, and experiences. +It is through these differences that our community experiences success and +continued growth. As members of this global community: + +1. We pledge to treat all people with respect and provide a harassment- and bullying-free environment, regardless of sex, sexual orientation and/or gender identity, disability, physical appearance, body size, race, nationality, ethnicity, and religion. In particular, sexual language and imagery, sexist, racist, or otherwise exclusionary jokes are not appropriate. +2. We pledge to respect the work of others by recognizing acknowledgment/citation requests of original authors. As authors, we pledge to be explicit about how we want our own work to be cited or acknowledged. +3. We pledge to welcome those interested in joining the community, and realize that including people with a variety of opinions and backgrounds will only serve to enrich our community. In particular, discussions relating to pros/cons of various technologies, programming languages, and so on are welcome, but these should be done with respect, taking proactive measure to ensure that all participants are heard and feel confident that they can freely express their opinions. +4. We pledge to welcome questions and answer them respectfully, paying particular attention to those new to the community. We pledge to provide respectful criticisms and feedback in forums, especially in discussion threads resulting from code contributions. +5. We pledge to be conscientious of the perceptions of the wider community and to respond to criticism respectfully. We will strive to model behaviors that encourage productive debate and disagreement, both within our community and where we are criticized. We will treat those outside our community with the same respect as people within our community. +6. We pledge to help the entire community follow the code of conduct, and to not remain silent when we see violations of the code of conduct. + +**This code of conduct applies to all community situations online and offline, including mailing lists, forums, social media, conferences, meetings, associated social events, and one-to-one interactions.** + +**Reporting**: Please report any violations of the Code of Conduct to the owners of the [`mpi-astronomy` [GitHub organization](https://github.com/orgs/mpi-astronomy/people)]. As community leaders we are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +**Enforcement**: We follow the enforcement guidelines of the [Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/). [For MPIA employees, the matter will be referred to the contacts listed in Section 7 of the [MPIA Work Agreement](https://intranet.mpia.de/4404342/03-Works-agreement-code-of-conduct.pdf) (intranet link). +For external people, the owners of the GitHub organization will decide in consultation with the MPIA directorate.] + +Parts of this code of conduct have been adapted from the Astropy and NumFOCUS codes of conduct: + +https://www.astropy.org/code_of_conduct.html + +https://www.numfocus.org/about/code-of-conduct/ + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..294cfe3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2024, Max Planck Institute for Astronomy +All rights reserved. + +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. + +3. Neither the name of the copyright holder 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/README.md b/README.md new file mode 100644 index 0000000..b6f76a1 --- /dev/null +++ b/README.md @@ -0,0 +1,201 @@ +[![DOI](https://zenodo.org/badge/472725375.svg)](https://zenodo.org/badge/latestdoi/472725375) + +# mpia-python-template + +This repository contains a Python template suitable for starting new projects. This template has three main goals: +- To create a properly +packaged Python project which requires minimal set-up effort for the user. Following the seven steps below you will have the structure of a python package in ~15 minutes. +- To encourage proper testing. This template includes a GitHub actions workflow, `.github/workflows/ci.yml`, that will run continuous integration on the `tests` directory at every push or pull request. +- To encourage code and package documentation. This template includes pre-configured documentation in the `docs` directory which will automatically pull the information from the code docstrings. A GitHub actions workflow, `.github/workflows/docs.yml`, also publishes the documentation to a GitHub Pages webpage at every push or pull request. + +This template does not assume GitHub tags, it is not set up for PyPi releases and it does not produce ReadTheDocs documentation, however such extensions can be easily added on to the template by motivated users. Please contact the template authors if you need help with these tasks. + +There is a lot of (sometimes contradictory) information on how to package a Python project. Here we have generally followed the [current recommendations](https://packaging.python.org/en/latest/tutorials/packaging-projects/) of the Python Packaging Authority. + +# How to Use This Template + +Click on the green "Use This Template" button in the upper right corner of the screen to make a copy of the template. + +Select location for the new repository. For projects led by MPIA staff and/or with an MPIA advisor, we encourage you to create your copy within the `mpi-astronomy` organization but you can also create a copy under your own account. + +Select a name for your repository, select if it should be Public (recommended) or Private. Here as an example we will use `new_project` as the name of your new repository. + +Click on the `Create Repository from Template` button. + +# Customize the Template in 7 Easy Steps + +1. We recommend creating a new environment for your project. This will allow you to track dependencies a lot easier. There are several different ways to do this (`virtualenv`, `pipenv`). Here we show an example with `conda`: + + conda create --name new_environment python + conda activate new_environment + + Do not install dependencies that are necessary for your code with `conda`. All dependencies should be specified in the `setup.cfg` files (see step 2). If you need some libraries to do diagnostic work, you can install them now (e.g., `pip install numpy matplotlib ipython`) but make sure that they are included in `setup.cfg` if your package needs them. We recommend using `pip` for installation rather than `conda` (see some notes on the differences [here](https://www.anaconda.com/blog/understanding-conda-and-pip)), unless you need the binaries for a given library. Note: if you do not have `conda` installed, we recommend [`miniconda`](https://docs.conda.io/en/latest/miniconda.html). + +2. Make a copy of the repository on your computer. Click on the green `Code` button and copy the HTTPS or SSH link, depending on how you authenticate with GitHub. + + git clone https://github.com/mpi-astronomy/new_project.git + + or + + git clone git@github.com:mpi-astronomy/new_project.git + + If you have not set up HTTPS or SSH authentication for GitHub on your computer, then follow the instructions [here for HTTPS](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) or [here for SSH](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent). + +3. Edit the `pyproject.toml` file. + + Specifically change the following lines: + + [project] + name = "new_package_name" + authors = [{name = "Example Author", email = "author@mpia.de"}] + description = "An example package" + + [project.urls] + "Bug Tracker" = "https://github.com/mpi-astronomy/new_project/issues" + "Source Code" = "https://github.com/mpi-astronomy/new_project" + + [tool.setuptools_scm] + write_to = "src/new_package_name/_version.py" + + + The `my_package_name` here will be the name of your package, it does not have to be the same as the name of the repository (as shown here). This will be the name used to import your package once installed. See the Python style guide [here](https://peps.python.org/pep-0008/#:~:text=Modules%20should%20have%20short%2C%20all,use%20of%20underscores%20is%20discouraged.) for package naming conventions (tl;dr: use lower case letters and underscores only). + + As you develop your code, you will need to specify any dependencies, i.e. packages from which you have direct imports. Add any new dependencies here (you get numpy for free): + + dependencies = [ + "numpy", + ] + + Test and documentation dependencies can be specified here: + + [project.optional-dependencies] + docs = [ + "sphinx", + "sphinx-automodapi", + "numpydoc", + ] + test = [ + "pytest", + "pytest-doctestplus", + "flake8", + "flake8-pyproject", + "codecov", + "pytest-cov", + ] + + Edit as needed. + +4. Rename your package. + + If you chose a different name for your package in `name` you should now rename your directory name as well. For example, in the previous step I changed the name of this package from the default `my_package` to `new_package_name`. Here we rename the directory too: + + cd src/ + git mv my_package new_package_name + +5. Edit the `README.md`. Add a short description of your package instead of this text. + +6. Edit the `CITATION.cff` file to specify how you want your code cited. The `CITATION.cff` file allows you to generate a `BibTeX` citation directly from the repository page (see `Cite this repository` in the upper right corner of this page). The fields we include here are the minimum recommended in the [AstroBetter post](https://www.astrobetter.com/blog/2019/07/01/citing-astronomy-software-inline-text-examples/) on citing astronomical software with no DOI. Please review the recommendations therein if you would like to add more information to the citation. Additional information about `CITATION.cff` files can be found [here](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files). + +7. Add your code to the `src/new_package_name/` directory. All your code should be `*.py` files in this directory. Do not add other directories inside `src/` unless you know what you are doing. Add your tests to the `tests/` directory. Edit the `docs/index.rst` file to create documentation for your project. + +🎉 You have a package. + +# What not to Change + +1. Do not change the `LICENSE` file and definitely do not delete it. For more information, see [this article](https://www.astrobetter.com/blog/2014/03/10/the-whys-and-hows-of-licensing-scientific-code/). + +2. If the copy is within the `mpi-astronomy` GitHub organization, do not edit the `CODE_OF_CONDUCT.md` file. If the copy is under your personal account, please customize the `CODE_OF_CONDUCT.md` file. One easy way to do that is to remove the text in square braces and to edit the reporting section to read "Any violations of the Code of Conduct should be reported to the owners of this repository." + +3. Using this Python packaging template gives you the most up-to-date way to package your Python code. You do not need to have `setup.py`, `setup.cfg` or `requirements.txt` files. The `setup.*` files are legacy formats that are now deprecated for most use cases. All your requirements should be listed in the `pyproject.toml` file. If you have a more complex package with C or Fortran code that needs to be compiled during install, you may also need to create a `setup.py` file, but we are going to keep things here simple. + +# Then What? + +Once you have made a local copy of the repository, you can install the package and start developing, testing and documenting it. + +# Versioning Your Package + +This package template does versioning for your package automatically using `setuptools-scm` which generates a version based on git tags in the standard semantic versioning format A.B.c. For more information see [setuptools-scm]() and Python packaging [Version specifiers](https://packaging.python.org/en/latest/specifications/version-specifiers/#version-specifiers). + +This means that when you have version of your package that you want to tag and release, make sure HEAD is pointing the the commit where you want to tag, and use `git tag A.B.c` to tag it with a proper semantic version. The next time you install the package, it should show you the updated version based on your tag. + +**Installation** + +With the package structure used here, you do not have to point Python to the location of your package. You absolutely SHOULD NOT be adding the package directory to your `$PYTHONPATH`. Instead, you can use `pip` to install it locally: +``` +cd ~/path/to/new_project +pip install -e . +``` +`pip` will install all the dependencies specified in the `pyproject.toml` file. The `-e` flag makes the install editable which means that you do not have to install the package again and again after each change. Changes to your files inside the project folder will automatically reflect in changes on your installed package. If you are working in an interactive environment (`ipython`, `Jupyter`) you will need to re-import any modules that have changed. For example, after editing `module_x.py` you will need to do the following to have the changes available in the Python interpreter: + +``` +import importlib +importlib.reload(module_x) +``` + +An accessible description of `pip install` can be found [here](https://www.reddit.com/r/learnpython/comments/ayx7za/how_does_pip_install_e_work_is_there_a_specific/). + +To install a non-editable version, do: +``` +cd ~/path/to/new_project +pip install . +``` +This is how you can use your package once you are no longer developing it. Any users who are not contributing code can installing your package with: +``` +pip install git+https://github.com/mpi-astronomy/new_project +``` + +**Commit early and often** + +As you make changes to your package, get into the habit of committing changes early and often. Every time you add a new function, a new test, edit the docstring: +``` +git add new_module.py +git commit -m "Added a function to reverse the sprocket of the whoosle." +``` +And every few commits: +``` +git push +``` + +**Testing your code** + +Ideally, you should be writing tests along with the new code. To test your code, first install the package in editable mode with the optional test dependencies: +``` +pip install -e ".[test]" +``` + +Then run the tests from the git repo root directory: +``` +pytest --cov=src/ tests +``` + +changing to whatever your package name is. This generates a report on how much of your code is covered by tests. Ideally this should be >80%. + +**Checking Code Style** + +To check for compliance with the Python style guide, run `flake8`: +``` +flake8 +``` + +This will do basic linting of your code, making sure you following best coding practices and will often also find bugs. + +**Continuous Integration** + +This repository come pre-set with continuous integration using GitHub Actions. Every time you push a commit or make a pull request, all tests will be automatically run by GitHub. On the GitHub page for your repository you should have an `Action` tab (forth from the left). This tab will show you the test results. While you can (and should) run the test suite locally, these runs are usually only on your operating system against one version of python. The advantage of CI is that you can test your code against different versions of python, different versions of key libraries and different operating systems. Here we have set up a simple test matrix which runs against 3 different versions of python. You can make the CI more complex if you need. You can disable/enable actions as shown [here](https://docs.github.com/en/actions/managing-workflow-runs/disabling-and-enabling-a-workflow) or by deleting the `.github/workflows/ci.yml` file (use `git rm`). + +**Creating documentation** + +If/when you want to update the auto-generated `sphinx` documentation, you can edit the `docs/index.rst` file. This file is in reStructuredText format. More information on making your docs pretty is available in the `sphinx` [docs](https://www.sphinx-doc.org/en/master/tutorial/index.html). + +To generate the documentation, you need to first install the dependencies and then make the pages: +``` +pip install -e ".[docs]" +cd docs/ +make html +open _build/html/index.html +``` +`sphinx` can also generate a PDF of your docs, but this is left as an exercise for the user. + +This repository is also set to auto-generate an HTML page with the documentation and creates a GitHub pages webpage. While the files are auto-generated, the page must be made visible in the first place. Go to the `Settings` tab in GitHub and in the left-hand menu navigate to the `Pages` option. Select the `gh-pages` branch in the drop down `Source` menu. This is a one-time setting. The URL for your documentation will be displayed in the green banner. The example documentation page for this repository can be found at [https://mpi-astronomy.github.io/mpia-python-template/](https://mpi-astronomy.github.io/mpia-python-template/). + +You can disable/enable the auto-generated documentation builds as shown [here](https://docs.github.com/en/actions/managing-workflow-runs/disabling-and-enabling-a-workflow) or by deleting the `.github/workflows/docs.yml` file (use `git rm`). To unpublish the documentation page, you also need to delete the `gh-pages` branch, see instructions [here](https://docs.github.com/en/pages/getting-started-with-github-pages/unpublishing-a-github-pages-site#unpublishing-a-project-site). 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..3d05e35 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,53 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'my_package' +copyright = '2022, Author Name' +author = 'Author Name' + + +# -- 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_automodapi.automodapi' +] +numpydoc_show_class_members = False + +# 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'] + + +# -- 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'] diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..97f48f9 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,67 @@ +.. my_package documentation master file, created by + sphinx-quickstart on Tue Mar 22 13:13:41 2022. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to my_package's documentation! +====================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + +Here is where you can write the documentation for your package. + + +Usage +===== + +.. _installation: + +Installation +------------ + +To use `my_package` you need to install X, Y and Z. + + +.. _code: + +Code +---- + +Here is an example of describing the use of your function. + +To add one to a number you can use the ``my_package.add_one()`` function: + +.. py:function:: my_package.add_one(number) + + + :param number: Should be integer, floating point number or a string. + + If ``number`` is not one of these types, an exception will be raised: + + .. py:exception:: TypeError + + Raised if the input is invalid. + +More about how to describe code can be hound +`here `_ + + +.. + The following section creates an index, a list of modules and a + search page. + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +.. + The following will add the signature of the individual functions and pull + their docstrings. + +.. automodapi:: my_package.example diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..153be5e --- /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.https://www.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/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..33d4c16 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,65 @@ +[project] +name = "my_package" +authors = [{name = "Example Author", email = "author@mpia.de"}] +description = "An example package" +readme = "README.md" +license = { file = 'LICENSE' } +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", +] +requires-python = ">=3.9" +dependencies = [ + "numpy", +] +dynamic = ['version'] + +[project.optional-dependencies] +docs = [ + "sphinx", + "sphinx-automodapi", + "numpydoc", +] +test = [ + "pytest", + "pytest-doctestplus", + "flake8", + "flake8-pyproject", + "codecov", + "pytest-cov", +] + +[project.urls] +"Bug Tracker" = "https://github.com/mpi-astronomy/snowblind/issues" +"Source Code" = "https://github.com/mpi-astronomy/snowblind" + + +[build-system] +requires = [ + "setuptools>=60", + "setuptools_scm>=8.0", + "wheel", +] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] +write_to = "src/my_package/_version.py" + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.flake8] +max-line-length = 130 +exclude = [ + 'docs', + '.tox', + '.eggs', + 'build', + '*_version.py', +] + +[tool.coverage.run] +omit = [ + "_version.py", +] diff --git a/src/my_package/__init__.py b/src/my_package/__init__.py new file mode 100644 index 0000000..0a97904 --- /dev/null +++ b/src/my_package/__init__.py @@ -0,0 +1,7 @@ +from . import _version + + +try: + __version__ = _version.version +except Exception: + __version__ = "dev" diff --git a/src/my_package/example.py b/src/my_package/example.py new file mode 100644 index 0000000..3887c04 --- /dev/null +++ b/src/my_package/example.py @@ -0,0 +1,21 @@ +def add_one(number): + """ + Example of a simple function. + + Parameters + ---------- + number: int, float, str + + Returns + ------- + out: int, float, str + The input value plus one. Raises TypeError if the input is not + the expected type + """ + + if isinstance(number, (float, int)): + return number + 1 + elif isinstance(number, (str)): + return number + '1' + else: + raise TypeError('Expecting an int, float or string.') diff --git a/tests/test_example.py b/tests/test_example.py new file mode 100644 index 0000000..ee5ab42 --- /dev/null +++ b/tests/test_example.py @@ -0,0 +1,20 @@ +import pytest + +from my_package.example import add_one + + +def test_type(): + """ + Test addition with float, int and strung. + """ + assert add_one(1) == 2 + assert add_one(1.1) == 2.1 + assert add_one('1') == '11' + + +def test_error(): + """ + Test addition with list. + """ + with pytest.raises(TypeError): + add_one([1])