Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ dependency-check:
run-example-env:
$(PYTHON) flask --app "goodmap.goodmap:create_app(config_path='$(CONFIG_PATH)')" --debug run

# TODO verify-json-data is broken: goodmap.data_validator does not exist
# The target always fails with "No module named goodmap.data_validator". Either restore
# the module or reimplement it: build a model with
# data_models.location.create_location_model(location_obligatory_fields, categories)
# from the file's own "map" section and model_validate() every point, exiting non-zero
# on the first failure. Docs (docs/data-source.rst) currently ship a standalone script
# as a workaround - fold it back in here once this works.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
verify-json-data:
ifndef JSON_DATA_FILE
$(error "Missing required argument JSON_DATA_FILE: make verify-json-data JSON_DATA_FILE=path/to/json")
Expand Down
121 changes: 121 additions & 0 deletions docs/api-reference.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
Python API reference
====================

Generated from the source. This is the reference for code you *import* — writing a
plugin, embedding the app, or working on Goodmap itself. If you are calling Goodmap over
HTTP instead, you want :doc:`http-api`; if you are configuring an instance, you want
:doc:`configuration`.

Nothing here is a substitute for the task pages: use those to find out *which* thing to
reach for, and this page for its exact signature.

.. note::

Only the ``goodmap`` package is covered. Everything a Goodmap deployment inherits from
platzky — the engine, blog, plugin loader — is documented in
:doc:`platzky's own reference <platzky:index>`.

Creating the application
------------------------

The documented way to build an app is the factory, given a path to ``config.yml``. It is
what ``flask --app`` and ``gunicorn`` take as their target string (:doc:`deployment`).

.. autofunction:: goodmap.goodmap.create_app

.. autoclass:: goodmap.config.GoodmapConfig
:members:
:show-inheritance:

``GoodmapConfig`` is a platzky ``Config`` with Goodmap's extra keys, and it is what
``create_app`` parses the YAML into. The prose description of every key is in
:doc:`configuration`.

Plugins
-------

The capability base classes a plugin subclasses. Which capability does what, and how a
plugin is packaged and activated, is covered in :doc:`plugins`.

.. automodule:: goodmap.plugin
:members:
:show-inheritance:

Location data
-------------

The models every point is validated against — both points already in the data source and
points arriving through ``/api/suggest-new-point``. ``create_location_model`` is the one
to know: it builds a model from your data source's ``location_obligatory_fields`` and
``categories`` at startup, which is why those keys are validation rules and not just
documentation (:doc:`data-source`).

.. automodule:: goodmap.data_models.location
:members:
:show-inheritance:

Request and response models
---------------------------

Pydantic models for the HTTP layer. These are what generate the OpenAPI document served
at ``/api/doc/openapi.json``, so they and the schema endpoint never disagree.

.. automodule:: goodmap.api_models
:members:
:show-inheritance:

Data access
-----------

The data-source layer: one implementation per ``DB.TYPE``, plus the query functions the
API blueprint calls. Backend trade-offs and the MongoDB layout are in
:ref:`data-source-backends`.

.. automodule:: goodmap.db
:members:
:show-inheritance:

Querying, filtering and clustering
----------------------------------

How a request's query parameters become a list of points: filter combination, distance
sorting and limiting, then optional server-side clustering.

.. automodule:: goodmap.core
:members:

.. automodule:: goodmap.filtering
:members:

.. automodule:: goodmap.clustering
:members:

Formatting
----------

Translation of category keys, option values and field names on the way out
(:ref:`config-translations`).

.. automodule:: goodmap.formatter
:members:

Errors
------

Exceptions raised by the data layer, and the helpers that turn them into the deliberately
generic ``{"message": "..."}`` responses described in :doc:`http-api`.

.. automodule:: goodmap.exceptions
:members:
:show-inheritance:

Input hardening
---------------

Limits applied to JSON arriving from the network before it is parsed into a point. The
concrete numbers, and the response you get for exceeding them, are in
:doc:`http-api`.

.. automodule:: goodmap.json_security
:members:
:show-inheritance:
60 changes: 0 additions & 60 deletions docs/api.rst

This file was deleted.

41 changes: 31 additions & 10 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
"""Sphinx configuration for Goodmap documentation."""
"""Sphinx configuration for Goodmap documentation.

Most of these docs are task-oriented prose: how to run, configure and extend Goodmap.
The API reference page is generated from docstrings instead, so autodoc imports the
package - hence the sys.path entry below, which makes a source checkout importable
without installing it.
"""

import importlib.metadata
import sys
from pathlib import Path

# Add project to path
# Autodoc imports goodmap, so a source checkout has to be on the path
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

Expand All @@ -24,8 +30,8 @@
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
"sphinx.ext.viewcode",
"myst_parser",
]

Expand Down Expand Up @@ -53,23 +59,38 @@
]
}

# Autodoc settings
# Autodoc settings. Source order reads better than alphabetical for these modules, and
# annotations go in the description so signatures stay readable.
autodoc_member_order = "bysource"
autodoc_typehints = "description"

# Intersphinx mapping
# Napoleon settings: docstrings in this project are Google style.
napoleon_google_docstring = True
napoleon_numpy_docstring = False
napoleon_include_init_with_doc = True

# The docs build with -n (nitpicky), so every unresolved cross-reference is a warning.
# These come out of third-party annotations autodoc copies into the signatures and have
# nothing to link to: pydantic and pymongo publish no intersphinx inventory, platzky's
# does not cover its classes, and annotated_types constraints render as their repr
# ("ge=-180"), which is not a target at all. Ignoring them keeps -n meaningful for the
# references we actually control.
nitpick_ignore_regex = [
("py:.*", r"ConfigDict|callable"),

Check failure on line 79 in docs/conf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "py:.*" 3 times.

See more on https://sonarcloud.io/project/issues?id=Problematy_goodmap&issues=AaAOxjEGTV2yRQvmw8w5&open=AaAOxjEGTV2yRQvmw8w5&pullRequest=391
("py:.*", r"(annotated_types|pymongo|platzky)\..*"),
("py:.*", r"[gl]e=-?\d+"),
]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

# Intersphinx mapping. platzky is linked from the config and plugin pages, since a
# Goodmap deployment is a platzky site and inherits its configuration; python, flask and
# pydantic resolve the types autodoc pulls out of the signatures.
intersphinx_mapping = {
"python": ("https://docs.python.org/3/", None),
"flask": ("https://flask.palletsprojects.com/en/stable/", None),
"pydantic": ("https://docs.pydantic.dev/latest/", None),
"platzky": ("https://platzky.readthedocs.io/en/latest/", None),
}

# Napoleon settings for Google/NumPy style docstrings
napoleon_google_docstring = True
napoleon_numpy_docstring = False
napoleon_include_init_with_doc = True

# Make version available as substitution in RST files
rst_epilog = f"""
.. |version| replace:: {version}
Expand Down
Loading
Loading