diff --git a/.gitignore b/.gitignore index 69103ae..fecbf78 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,12 @@ build/ dist/ **.egg-info +# Sphinx documenter creates these +_build +_static +_templates +/docs/reference + # MacOS automatically creates these files .DS_Store diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..75f0fc0 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,35 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + # You can also specify other tool versions: + # nodejs: "19" + # rust: "1.64" + # golang: "1.19" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Optionally build your docs in additional formats such as PDF and ePub +# formats: +# - pdf +# - epub + +# Optional but recommended, declare the Python requirements required +# to build your documentation +# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - method: pip + path: . + extra_requirements: + - docs diff --git a/README.md b/README.md index 00ed322..e7488a2 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,20 @@ Install package so that new code is picked up in a restared python interpreter: pip install -e . ``` +## TestPyPI + +Install vom [TestPyPI](https://test.pypi.org/project/rasmussenlab-mockup): + +``` +pip install -i https://test.pypi.org/simple/ rasmussenlab-mockup +``` + +> The package on PyPI is call `rasmussenlab-mockup` and not `mockup` as the package name is already taken. The import is still `import mockup`. + +## Readthedocs + +The documentation is build using readthedocs automatically. See +[project on Readthedocs](https://readthedocs.org/projects/rasmussenlab-python-package/). + +- make sure to enable build from PRs in the settings (advanded settings) +- checkout configuration file: [`.readthedocs.yaml`](.readthedocs.yaml) \ No newline at end of file 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/README.md b/docs/README.md new file mode 100644 index 0000000..cbce8fe --- /dev/null +++ b/docs/README.md @@ -0,0 +1,31 @@ +# Docs creation + +In order to build the docs you need to + + 1. install sphinx and additional support packages + 2. build the package reference files + 3. run sphinx to create a local html version + +The documentation is build using readthedocs automatically. + +Install the docs dependencies of the package (as speciefied in toml): + +```bash +# in main folder +pip install .[docs] +``` + +## Build docs using Sphinx command line tools + +Command to be run from `path/to/docs`, i.e. from within the `docs` package folder: + +Options: + - `--separate` to build separate pages for each (sub-)module + +```bash +# pwd: docs +# apidoc +sphinx-apidoc --force --implicit-namespaces --module-first -o reference ../src/mockup +# build docs +sphinx-build -n -W --keep-going -b html ./ ./_build/ +``` \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..2bf9101 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,140 @@ +# 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 +from importlib import metadata + + +# -- Project information ----------------------------------------------------- + +project = "mockup" +copyright = "2024, Jakob Nybo Nissen, Henry Webel" +author = "Jakob Nybo Nissen, Henry Webel" +PACKAGE_VERSION = metadata.version("rasmussenlab-mockup") +version = PACKAGE_VERSION +release = PACKAGE_VERSION + + +# -- 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.autodoc.typehints", + "sphinx.ext.viewcode", + "sphinx.ext.napoleon", + "sphinx.ext.intersphinx", + "sphinx_new_tab_link", + "myst_nb", +] + +# https://myst-nb.readthedocs.io/en/latest/computation/execute.html +nb_execution_mode = "auto" + +myst_enable_extensions = ["dollarmath", "amsmath"] + +# Plolty support through require javascript library +# https://myst-nb.readthedocs.io/en/latest/render/interactive.html#plotly +html_js_files = [ + "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" +] + +# https://myst-nb.readthedocs.io/en/latest/configuration.html +# Execution +nb_execution_raise_on_error = True +# Rendering +nb_merge_streams = True + +# 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"] + + +# Intersphinx options +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + # "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), + # "scikit-learn": ("https://scikit-learn.org/stable/", None), + # "matplotlib": ("https://matplotlib.org/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. +# See: +# https://github.com/executablebooks/MyST-NB/blob/master/docs/conf.py +# html_title = "" +html_theme = "sphinx_book_theme" +# html_logo = "_static/logo-wide.svg" +# html_favicon = "_static/logo-square.svg" +html_theme_options = { + "github_url": "https://github.com/RasmussenLab/python_package", + "repository_url": "https://github.com/RasmussenLab/python_package", + "repository_branch": "main", + "home_page_in_toc": True, + "path_to_docs": "docs", + "show_navbar_depth": 1, + "use_edit_page_button": True, + "use_repository_button": True, + "use_download_button": True, + "launch_buttons": { + "colab_url": "https://colab.research.google.com" + # "binderhub_url": "https://mybinder.org", + # "notebook_interface": "jupyterlab", + }, + "navigation_with_keys": False, +} + +# 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"] + + +# -- Setup for sphinx-apidoc ------------------------------------------------- + +# Read the Docs doesn't support running arbitrary commands like tox. +# sphinx-apidoc needs to be called manually if Sphinx is running there. +# https://github.com/readthedocs/readthedocs.org/issues/1139 + +if os.environ.get("READTHEDOCS") == "True": + from pathlib import Path + + PROJECT_ROOT = Path(__file__).parent.parent + PACKAGE_ROOT = PROJECT_ROOT / "src" / "mockup" + + def run_apidoc(_): + from sphinx.ext import apidoc + + apidoc.main( + [ + "--force", + "--implicit-namespaces", + "--module-first", + "--separate", + "-o", + str(PROJECT_ROOT / "docs" / "reference"), + str(PACKAGE_ROOT), + str(PACKAGE_ROOT / "*.c"), + str(PACKAGE_ROOT / "*.so"), + ] + ) + + def setup(app): + app.connect("builder-inited", run_apidoc) diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..7fac169 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,39 @@ +.. mockup documentation master file, created by + sphinx-quickstart on Mon Aug 28 14:09:15 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +The mockup package +================================== + +Mockup is a Python package with some simple example code. +To get started, explore the :class:`mockup.Circle` class. + + + +.. toctree:: + :maxdepth: 2 + :caption: Tutorial + + tutorial/tutorial + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + reference/modules + +.. toctree:: + :hidden: + :caption: Technical notes + + README.md + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/tutorial/tutorial.ipynb b/docs/tutorial/tutorial.ipynb new file mode 100644 index 0000000..2cb608a --- /dev/null +++ b/docs/tutorial/tutorial.ipynb @@ -0,0 +1,83 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Mockup tutorial" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from mockup import mockup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mockup.add_one(-11)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "list(mockup.flatten_ints([[9, 11], [12], [4, 5]]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "c2 = mockup.Circle.from_circumference(100)\n", + "round(c2.radius, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "c2 # repr" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "pathways", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/pyproject.toml b/pyproject.toml index 74d3014..9639479 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,9 @@ [project] -name = "mockup" authors = [ - { name="Jakob Nybo Nissen", email="jakobnybonissen@gmail.com" }, + {name = "Jakob Nybo Nissen", email = "jakobnybonissen@gmail.com"}, ] description = "A small example package" +name = "rasmussenlab-mockup" # This means: Load the version from the package itself. # See the section below: [tools.setuptools.dynamic] dynamic = ["version"] @@ -12,19 +12,33 @@ readme = "README.md" requires-python = ">=3.11" # These are keywords classifiers = [ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", ] [project.urls] -"Homepage" = "https://github.com/RasmussenLab/python_package" "Bug Tracker" = "https://github.com/RasmussenLab/python_package/issues" +"Homepage" = "https://github.com/RasmussenLab/python_package" -[tool.setuptools.dynamic] -version = {attr = "mockup.__version__"} +[project.optional-dependencies] +docs = [ + "sphinx", + "sphinx-book-theme", + "myst-nb", + "ipywidgets", + "sphinx-new-tab-link!=0.2.2", +] # Configure the Ruff linter: Ignore error number 501 [tool.ruff] ignore = ["E501"] + +[build-system] +build-backend = "setuptools.build_meta" +requires = ["setuptools>=64", "setuptools_scm>=8"] + +[tool.setuptools_scm] +# https://setuptools-scm.readthedocs.io/ +# used to pick up the version from the git tags or the latest commit. diff --git a/setup.py b/setup.py index 8bf1ba9..6068493 100644 --- a/setup.py +++ b/setup.py @@ -1,2 +1,3 @@ from setuptools import setup + setup() diff --git a/mockup/__init__.py b/src/mockup/__init__.py similarity index 79% rename from mockup/__init__.py rename to src/mockup/__init__.py index 392eb9a..d517e4a 100644 --- a/mockup/__init__.py +++ b/src/mockup/__init__.py @@ -1,7 +1,9 @@ # The __init__.py file is loaded when the package is loaded. # It is used to indicate that the directory in which it resides is a Python package -__version__ = (0, 1, 0) + +from importlib import metadata +__version__ = metadata.version("rasmussenlab-mockup") from .mockup import add_one, Circle diff --git a/mockup/mockup.py b/src/mockup/mockup.py similarity index 97% rename from mockup/mockup.py rename to src/mockup/mockup.py index f92d591..58f2bcb 100644 --- a/mockup/mockup.py +++ b/src/mockup/mockup.py @@ -92,3 +92,6 @@ def diameter(self): @classmethod def from_circumference(cls, circumference: Union[int, float]) -> Self: return cls(circumference / (2 * cls.PI)) + + def __repr__(self): + return f"Circle({self.radius})"