Skip to content

Commit

Permalink
📝 Add library documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
sergei-maertens committed Oct 6, 2023
1 parent 04b27bb commit e2d6e34
Show file tree
Hide file tree
Showing 13 changed files with 380 additions and 2 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
=========
Changelog
=========

0.1.0 (2023-10-06)
==================

Extacted the code from Open Forms and published it on PyPI under "ape-pie".
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -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)
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. include:: ../CHANGELOG.rst
17 changes: 17 additions & 0 deletions docs/check_sphinx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import subprocess


def test_linkcheck(tmpdir):
doctrees = tmpdir.join("doctrees")
htmldir = tmpdir.join("html")
subprocess.check_call(
["sphinx-build", "-W", "-blinkcheck", "-d", str(doctrees), ".", str(htmldir)],
)


def test_build_docs(tmpdir):
doctrees = tmpdir.join("doctrees")
htmldir = tmpdir.join("html")
subprocess.check_call(
["sphinx-build", "-W", "-bhtml", "-d", str(doctrees), ".", str(htmldir)],
)
38 changes: 38 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 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 = "ape-pie"
copyright = "2023, Maykin Media"
author = "Maykin Media"
release = "0.1.0"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
]

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"]

# -- Intersphinx configuration -----------------------------------------------
intersphinx_mapping = {
"requests": (
"https://docs.python-requests.org/en/latest/",
None,
)
}
23 changes: 23 additions & 0 deletions docs/contributing.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
============
Contributing
============

Release flow
============

Bump the version number using tbump:

.. code-block:: bash
tbumb --only-patch <new-version>
Update ``CHANGELOG.rst`` with the new version, release date and included changes.

Then, to actually release to PyPI, tag the release commit and push it:

.. code-block:: bash
git tag <new-version>
git push origin <new-version>
The CI pipeline will publish it if all checks pass.
63 changes: 63 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Welcome to ape-pie's documentation!
===================================

.. pull-quote:: Monkey see, monkey GET.

|build-status| |code-quality| |black| |coverage| |docs|

|python-versions| |pypi-version|

Ape-pie is a small API client abstraction layer on top of requests_.

Features
========

* No leaky abstraction - use the familiar ``requests`` Python interfaces.
* Modular configuration adapters for your project's domain(s).
* Highly customizable for your needs.


.. toctree::
:maxdepth: 2
:caption: Contents:

quickstart
reference
changelog
contributing



Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

.. |build-status| image:: https://github.com/maykinmedia/ape-pie/workflows/Tests%20and%20PyPI%20publishing/badge.svg
:alt: Build status
:target: https://github.com/maykinmedia/ape-pie/actions?query=workflow%3A%22Tests+and+PyPI+publishing%22

.. |code-quality| image:: https://github.com/maykinmedia/ape-pie/workflows/Linting%20and%20code%20quality/badge.svg
:alt: Code quality checks
:target: https://github.com/maykinmedia/ape-pie/actions?query=workflow%3A%22Linting+and+code+quality%22

.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black

.. |coverage| image:: https://codecov.io/gh/maykinmedia/ape-pie/branch/main/graph/badge.svg
:target: https://codecov.io/gh/maykinmedia/ape-pie
:alt: Coverage status

.. |docs| image:: https://readthedocs.org/projects/ape-pie/badge/?version=latest
:target: https://ape-pie.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status

.. |python-versions| image:: https://img.shields.io/pypi/pyversions/ape-pie.svg

.. |pypi-version| image:: https://img.shields.io/pypi/v/ape-pie.svg
:target: https://pypi.org/project/ape-pie/

.. _requests: https://docs.python-requests.org/en/latest/index.html
.. _ReadTheDocs: https://ape-pie.readthedocs.io/en/latest/
35 changes: 35 additions & 0 deletions docs/make.bat
Original file line number Diff line number Diff line change
@@ -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
120 changes: 120 additions & 0 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
==========
Quickstart
==========

Installation
============

Install from PyPI with pip:

.. code-block:: bash
pip install ape-pie
Usage
=====

The recommended usage is to instantiate a client (a :class:`requests.Session`, we'll
call them clients from here on) from a configuration adapter in your domain:

.. code-block:: python
from ape_pie import APIClient
from .adapters import my_adapter
client = APIClient.configure_from(my_adapter)
with client:
# ⚡️ context manager -> uses connection pooling and is recommended!
response1 = client.get("some-relative-path", params={"foo": ["bar"]})
response2 = client.post("other-path", json={...})
The ``my_adapter`` object is a "special" :ref:`configuration source <config_adapter>`,
which feeds the relevant initialization parameters to the :class:`ape_pie.client.APIClient`
instance.

.. note:: You can (and should) use the client/session in a context manager to benefit
from connection pooling and thus better performance when multiple requests are made.

You can also instantiate clients directly:

.. code-block::
from ape_pie import APIClient
from requests.auth import HTTPBasicAuth
# You can pass most attributes available on requests.Session, like auth/verify/cert...
client = APIClient(
"https://example.com/api/v1/",
auth=HTTPBasicAuth("superuser", "letmein"),
verify="/path/to/custom/ca-bundle.pem",
)
with client:
# ⚡️ context manager -> uses connection pooling and is recommended!
response1 = client.get("some-relative-path", params={"foo": ["bar"]})
response2 = client.post("other-path", json={...})
...
Configuration adapter example
-----------------------------

Suppose you are keeping your client parameters in a TOML file:

.. code-block:: toml
api-root = "https://example.com"
[auth]
type = "basic"
username = "admin"
password = "letmein"
[headers]
Accept = "application/json"
You could then implement a configuration adapter grabbing the root, auth and headers
configuration:

.. code-block:: python
import tomllib
from typing import Any
from requests.auth import HTTPBasicAuth
class TOMLConfigAdapter:
def __init__(self, config_file: str):
with open(config_file, "rb") as f:
self.config = tomllib.load(f)
def get_client_base_url(self) -> str:
return self.config["api-root"]
def get_client_session_kwargs(self) -> dict[str, Any]:
auth = None
if (auth := self.config["auth"])["type"] == "basic":
auth = HTTPBasicAuth(auth["username"], auth["password"])
return {
"auth": auth,
"headers": self.config["headers"],
}
and use it as:

.. code-block:: python
toml_adapter = TOMLConfigAdapter("/tmp/config.toml")
client = APIClient.configure_from(toml_adapter)
with client:
r = client.get("foo")
...
26 changes: 26 additions & 0 deletions docs/reference.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
=============
API reference
=============

``APIClient`` class
===================

The ``APIClient`` class extends requests' :class:`requests.Session`, requiring you
to provide a ``base_url``.

.. autoclass:: ape_pie.APIClient
:members:

.. _config_adapter:

Configuration adapters
======================

Configuration adapters need to be implemented by your project, so that a client instance
can be configured from your configuration source. It essentially acts as a translation
from your domain-specific configuration to :class:`ape_pie.APIClient` arguments.

Configuration adapters must implement our protocol:

.. autoclass:: ape_pie.ConfigAdapter
:members:
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "ape-pie"
version = "1.0.0"
version = "0.1.0"
authors = [
{ name="Maykin Media", email="[email protected]" },
{ name="Sergei Maertens", email="[email protected]" },
Expand Down
Loading

0 comments on commit e2d6e34

Please sign in to comment.