diff --git a/.github/workflows/gh-pages.yaml b/.github/workflows/gh-pages.yaml new file mode 100644 index 0000000000..735fa1b916 --- /dev/null +++ b/.github/workflows/gh-pages.yaml @@ -0,0 +1,40 @@ +name: "Sphinx: Render docs" + +on: push + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Install poetry + run: pipx install poetry + + - name: Set up Python 3.12 + uses: actions/setup-python@v4 + with: + python-version: "3.12" + cache: "poetry" + + - name: Install dependencies + run: poetry install --no-interaction --with doc + + - name: Build doc + run: make -C docs html + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: html-docs + path: docs/_build/html/ + + - name: Deploy to GitHub pages + uses: peaceiris/actions-gh-pages@v3 + if: github.ref == 'refs/heads/main' || github.ref == 'ref/heads/add-sphinx-doc' + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: docs/_build/html diff --git a/.gitignore b/.gitignore index a6578a8e50..da6d18c3d3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ __pycache__ .DS_Store examples/**/*.trace +# Sphinx documentation +docs/_build/ diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000000..d4bb2cbb9e --- /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 0000000000..9d52fb265f --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,35 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = "PuyaPy" +copyright = "2024, Algorand Foundation" # noqa: A001 +author = "Algorand Foundation" + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + "sphinx.ext.githubpages", + "myst_parser", +] + +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = "sphinx_rtd_theme" +html_static_path = ["_static"] + +# -- Options for myst --- +myst_enable_extensions = [ + "colon_fence", + "fieldlist", +] diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000..79b746ed01 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,144 @@ +# PuyaPy - Python to TEAL compiler + + +```{warning} +PuyaPy is currently in alpha / developer preview. It is not recommended for production usage yet. +``` + +PuyaPy is an optimising TEAL compiler that allows you to write code to execute on the Algorand +Virtual Machine (AVM) with Python syntax. + +[Project background and guiding principles](principles.md). + +PuyaPy supports a statically-typed subset of valid Python syntax. Importantly, that subset has +identical semantics when comparing Python behaviour and behaviour of the executed TEAL. +For example, `foo = spam() or eggs()` will only execute `eggs()` if `bool(spam())` is `False`. + +## Installation + +The minimum supported Python version for running PuyaPy itself is 3.12. + +You can install the developer preview of PuyaPy from PyPI into your project virtualenv: +```shell +pip install puya +``` +If you're using poetry for dependency and virutalenv management, you can add it that way with +`poetry add puya`. + +Or if you just want to play with some examples, you can clone the repo and have a poke around. + +```shell +git clone https://github.com/algorandfoundation/puya.git +cd puya +poetry install +poetry shell +``` + +Note that with this method you'll need to activate the virtual environment created by poetry +before using the puyapy command in each new shell that you open - you can do this by running +`poetry shell` in the `puya` directory. + +## Compiler usage + +To check that you can run the `puyapy` command successfully after that, you can run the help command: + +`puyapy -h` + +To compile a contract or contracts, just supply the path(s) - either to the .py files themselves, +or the containing directories. In the case of containing directories, any contracts discovered +therein will be compiled, allowing you to compile multiple contracts at once. You can also supply +more than one path at a time to the compiler. + +e.g. `puyapy my_project/` or `puyapy my_project/contract.py` will work to compile a single contract. + +## Language fundamentals + +```{note} +A more comprehensive guide is coming soon! +``` + +### Contracts + +A smart contract is defined within a single class. You can extend other contracts (through inheritance), +and also define standalone functions and reference them. This also works across different Python +packages - in other words, you can have a Python library with common functions and re-use that +library across multiple projects! + +All contracts must inherit from the base class `puyapy.Contract` - either directly or indirectly, +which can include inheriting from `puyapy.ARC4Contract`. For a non-ARC4 contract, a contract class +must implement an `approval_program` and a `clear_state_program` method. For ARC4 contracts, these +methods will be implemented for you, although you can optionally provide a `clear_state_program` +(the default implementation just always approves). + +As an example, this is a valid contract that always approves: + +```python +import puyapy + +class Contract(puyapy.Contract): + def approval_program(self) -> bool: + return True + + def clear_state_program(self) -> bool: + return True +``` + +The return value of these methods can be either a `bool` that indicates whether the transaction +should approve or not, or a `puyapy.UInt64` value, where `UInt64(0)` indicates that the transaction +should be rejected and any other value indicates that it should be approved. + +And here is a valid ARC4 contract: + +```python +import puyapy + +class ABIContract(puyapy.ARC4Contract): + """This contract can be created, but otherwise does nothing""" + pass +``` + +### Primitive types + +The primitive types of the AVM, `uint64` and `bytes[]` are represented by `puyapy.UInt64` and +`puyapy.Bytes` respectively. `puyapy.BigUInt` is also available for AVM supported wide-math +(up to 512 bits). + +Note that Python builtin types such as `int` cannot be used as variables, for semantic compatibility +reasons - however you can define module level constants of this type, and integer literals are +permitted in expressions. + +For example: + +```python +from puyapy import UInt64, subroutine + +SCALE = 100000 +SCALED_PI = 314159 + +@subroutine +def circle_area(radius: UInt64) -> UInt64: + scaled_result = SCALED_PI * radius**2 + result = scaled_result // SCALE + return result + + +@subroutine +def circle_area_100() -> UInt64: + return circle_area(UInt64(100)) +``` + + +```{toctree} +--- +maxdepth: 2 +caption: Contents +--- + +language_guide +principles +``` + + +# Indices and tables + +- {ref}`genindex` diff --git a/docs/language_guide.md b/docs/language_guide.md new file mode 100644 index 0000000000..b46967391e --- /dev/null +++ b/docs/language_guide.md @@ -0,0 +1,2 @@ +# PuyaPy Language Guide + diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000000..954237b9b9 --- /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 + +%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 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/principles.md b/docs/principles.md index 0e199199b0..a3dc2e207c 100644 --- a/docs/principles.md +++ b/docs/principles.md @@ -1,5 +1,5 @@ - -# Background +# PuyaPy Principles +## Background **Smart contracts** on the Algorand blockchain run on the Algorand Virtual Machine ([AVM](https://developer.algorand.org/docs/get-details/dapps/avm/)). This is a stack based virtual machine, which executes AVM bytecode as part of an [Application Call transaction](https://developer.algorand.org/docs/get-details/transactions/#application-call-transaction). @@ -43,10 +43,10 @@ To most developers, the Python programming language needs no introduction. First grown steadily over the decades, and as of June 2023 it is consistently ranked as either the most popular langauge, or second most popular following JavaScript: -- https://octoverse.github.com/2022/top-programming-languages -- https://stackoverflow.blog/2023/06/13/developer-survey-results-are-in/ -- https://www.tiobe.com/tiobe-index/ -- https://pypl.github.io/PYPL.html +- [GitHub 2022](https://octoverse.github.com/2022/top-programming-languages) +- [StackOverflow 2023](https://stackoverflow.blog/2023/06/13/developer-survey-results-are-in/) +- [Tiobe](https://www.tiobe.com/tiobe-index/) +- [PYPL](https://pypl.github.io/PYPL.html) The AlgoKit project is an Algorand Foundation initiative to improve the developer experience on Algorand. Within this broad remit, two of the key [principles](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md#guiding-principles) @@ -58,16 +58,16 @@ Puya was the original internal code name for just such a compiler (now called Pu smart contracts. In line with the principle of meeting developers where they are, and recognising the popularity of JavaScript and TypeScript, a parallel initiative to build a TypeScript to TEAL compiler is [also underway](https://tealscript.netlify.app). -# Principles +## Principles The principles listed here should form the basis of our decision-making, both in the design and implementation. -## Inherited from AlgoKit +### Inherited from AlgoKit As a part of the AlgoKit project, the principles outlined [there](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md#guiding-principles) also apply - to the extent that this project is just one component of AlgoKit. -### "Leverage existing ecosystem" +#### "Leverage existing ecosystem" > AlgoKit functionality gets into the hands of Algorand developers quickly by building on top of the > existing ecosystem wherever possible and aligned to these principles. @@ -75,7 +75,7 @@ also apply - to the extent that this project is just one component of AlgoKit. In order to leverage as much existing Python tooling as possible, we should strive to maintain the highest level of compatibility with the Python language (and the reference implementation: CPython). -### "Meet developers where they are" +#### "Meet developers where they are" > Make Blockchain development mainstream by giving all developers an idiomatic development experience in the operating > system, IDE and language they are comfortable with so they can dive in quickly and have less they need to learn before @@ -84,7 +84,7 @@ compatibility with the Python language (and the reference implementation: CPytho Python is a very idiomatic language. We should embrace accepted patterns and practices as much as possible, such as those listed in [PEP-20](https://peps.python.org/pep-0020/) (aka "The Zen of Python"). -### "Extensible" +#### "Extensible" > Be extensible for community contribution rather than stifling innovation, bottle-necking all changes through the > Algorand Foundation and preventing the opportunity for other ecosystems being represented (e.g. Go, Rust, etc.). @@ -94,7 +94,7 @@ such as those listed in [PEP-20](https://peps.python.org/pep-0020/) (aka "The Ze One way to support this principle in the broader AlgoKit context is by building in a mechanism for reusing common code between smart contracts, to allow the community to build their own Python packages. -### "Sustainable" +#### "Sustainable" > AlgoKit should be built in a flexible fashion with long-term maintenance in mind. Updates to latest patches in > dependencies, Algorand protocol development updates, and community contributions and feedback will all feed in to the @@ -109,7 +109,7 @@ implementation too tightly to a current standard such as ARC-4 - although in tha aim for first class support, but it shouldn't be assumed as the only way to write smart contracts. -### "Modular components" +#### "Modular components" > Solution components should be modular and loosely coupled to facilitate efficient parallel development by small, > effective teams, reduced architectural complexity and allowing developers to pick and choose the specific tools and @@ -121,7 +121,7 @@ An example of a very useful feature, that is strongly related but could be imple is the ability to run the users code in a unit-testing context, without compilation+deployment first. This would require implementing in Python some level of simulation of Algorand Nodes / AVM behaviour. -### "Secure by default" +#### "Secure by default" > Include defaults, patterns and tooling that help developers write secure code and reduce the likelihood of security > incidents in the Algorand ecosystem. This solution should help Algorand be the most secure Blockchain ecosystem. @@ -130,7 +130,7 @@ Enforcing security (which is multi-faceted) at a compiler level is difficult, an The best application of this principle here is to support auditing, which is important and nuanced enough to be listed below as a separate principle. -### "Cohesive developer tool suite" + "Seamless onramp" +#### "Cohesive developer tool suite" + "Seamless onramp" > Cohesive developer tool suite: Using AlgoKit should feel professional and cohesive, like it was designed to work > together, for the developer; not against them. Developers are guided towards delivering end-to-end, high quality @@ -143,7 +143,7 @@ listed below as a separate principle. These principles relate more to AlgoKit as a whole, so we can respect them by considering the impacts of our decisions there more broadly. -## Abstraction without obfuscation +### Abstraction without obfuscation PuyaPy is a high level language (like Python), with support for things such as branching logic, operator precedence, etc., and not a set of "macros" for generating TEAL. As such, developers will not be able to directly influence specific TEAL @@ -155,7 +155,7 @@ cost-effective and unsurprising. Python mechanisms such as dynamic (runtime) dis functions on types such as `str` that are taken for granted, would require large amounts of ops compared to the Python code it represents. -## Support auditing +### Support auditing Auditing is a critical part of the security process for deploying smart contracts. We want to support this function, and can do so in two ways: @@ -168,7 +168,7 @@ auditing the lower level (ie TEAL) code is possible. 2. Although auditing the TEAL code should be possible, being able to easily identify and relate it back to the higher level code can make auditing the contract logic simpler and easier. -## Revolution, not evolution +### Revolution, not evolution This is a new and groundbreaking way of developing for Algorand, and not a continuation of the PyTEAL/Beaker approach. By allowing developers to write procedural code, as opposed to constructing an expression tree, diff --git a/poetry.lock b/poetry.lock index 06864b2f82..76501638ed 100644 --- a/poetry.lock +++ b/poetry.lock @@ -109,6 +109,17 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "alabaster" +version = "0.7.16" +description = "A light, configurable Sphinx theme" +optional = false +python-versions = ">=3.9" +files = [ + {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, + {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, +] + [[package]] name = "algokit" version = "1.9.3" @@ -233,6 +244,20 @@ pyopenssl = ">=23.2.0,<24.0.0" requests = ">=2.31.0,<3.0.0" urllib3 = ">=2.0.7,<3.0.0" +[[package]] +name = "babel" +version = "2.14.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + [[package]] name = "bases" version = "0.3.0" @@ -711,6 +736,17 @@ files = [ {file = "docstring_parser-0.15.tar.gz", hash = "sha256:48ddc093e8b1865899956fcc03b03e66bb7240c310fac5af81814580c55bf682"}, ] +[[package]] +name = "docutils" +version = "0.20.1" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, +] + [[package]] name = "dotty-dict" version = "1.3.1" @@ -958,6 +994,17 @@ files = [ {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + [[package]] name = "immutabledict" version = "4.0.0" @@ -1193,6 +1240,25 @@ files = [ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] +[[package]] +name = "mdit-py-plugins" +version = "0.4.0" +description = "Collection of plugins for markdown-it-py" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mdit_py_plugins-0.4.0-py3-none-any.whl", hash = "sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9"}, + {file = "mdit_py_plugins-0.4.0.tar.gz", hash = "sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b"}, +] + +[package.dependencies] +markdown-it-py = ">=1.0.0,<4.0.0" + +[package.extras] +code-style = ["pre-commit"] +rtd = ["myst-parser", "sphinx-book-theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "mdurl" version = "0.1.2" @@ -1469,6 +1535,32 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "myst-parser" +version = "2.0.0" +description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," +optional = false +python-versions = ">=3.8" +files = [ + {file = "myst_parser-2.0.0-py3-none-any.whl", hash = "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14"}, + {file = "myst_parser-2.0.0.tar.gz", hash = "sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead"}, +] + +[package.dependencies] +docutils = ">=0.16,<0.21" +jinja2 = "*" +markdown-it-py = ">=3.0,<4.0" +mdit-py-plugins = ">=0.4,<1.0" +pyyaml = "*" +sphinx = ">=6,<8" + +[package.extras] +code-style = ["pre-commit (>=3.0,<4.0)"] +linkify = ["linkify-it-py (>=2.0,<3.0)"] +rtd = ["ipython", "pydata-sphinx-theme (==v0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.8.2,<0.9.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] +testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=7,<8)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] +testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4,<0.4.0)"] + [[package]] name = "networkx" version = "3.2.1" @@ -2129,6 +2221,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2136,8 +2229,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -2154,6 +2254,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -2161,6 +2262,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -2381,6 +2483,178 @@ files = [ {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, ] +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "sphinx" +version = "7.2.6" +description = "Python documentation generator" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinx-7.2.6-py3-none-any.whl", hash = "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560"}, + {file = "sphinx-7.2.6.tar.gz", hash = "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.18.1,<0.21" +imagesize = ">=1.3" +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.14" +requests = ">=2.25.0" +snowballstemmer = ">=2.0" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.9" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools (>=67.0)"] + +[[package]] +name = "sphinx-rtd-theme" +version = "2.0.0" +description = "Read the Docs theme for Sphinx" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sphinx_rtd_theme-2.0.0-py2.py3-none-any.whl", hash = "sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586"}, + {file = "sphinx_rtd_theme-2.0.0.tar.gz", hash = "sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b"}, +] + +[package.dependencies] +docutils = "<0.21" +sphinx = ">=5,<8" +sphinxcontrib-jquery = ">=4,<5" + +[package.extras] +dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.8" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_applehelp-1.0.8-py3-none-any.whl", hash = "sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4"}, + {file = "sphinxcontrib_applehelp-1.0.8.tar.gz", hash = "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.6" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_devhelp-1.0.6-py3-none-any.whl", hash = "sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f"}, + {file = "sphinxcontrib_devhelp-1.0.6.tar.gz", hash = "sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.5" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_htmlhelp-2.0.5-py3-none-any.whl", hash = "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04"}, + {file = "sphinxcontrib_htmlhelp-2.0.5.tar.gz", hash = "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jquery" +version = "4.1" +description = "Extension to include jQuery on newer Sphinx releases" +optional = false +python-versions = ">=2.7" +files = [ + {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, + {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, +] + +[package.dependencies] +Sphinx = ">=1.8" + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.7" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_qthelp-1.0.7-py3-none-any.whl", hash = "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182"}, + {file = "sphinxcontrib_qthelp-1.0.7.tar.gz", hash = "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.10" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_serializinghtml-1.1.10-py3-none-any.whl", hash = "sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7"}, + {file = "sphinxcontrib_serializinghtml-1.1.10.tar.gz", hash = "sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + [[package]] name = "structlog" version = "23.2.0" @@ -2666,4 +2940,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "ec9bb4a0fd9320be1ec10712793f53173d36a77f68feb8b61b2a84355c8915fe" +content-hash = "e7460b3c1247410788a1d3a387d13c7de81fe2e639f1c7d4792f0ce6f91d68b7" diff --git a/pyproject.toml b/pyproject.toml index be0c262e7c..5c836b79a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,14 @@ pre-commit = "^3.3.3" cattrs = "^23.1.2" ruff-lsp = "^0.0.45" +[tool.poetry.group.doc] +optional = true + +[tool.poetry.group.doc.dependencies] +sphinx = "^7.2.6" +sphinx-rtd-theme = "^2.0.0" +myst-parser = "^2.0.0" + [tool.poetry.group.cicd] optional = true