Skip to content

Commit e6178a8

Browse files
timmarkhuffTim Huff
andauthored
Restore missing SDK client docs in API reference (#434)
## Summary The API reference docs page (`/api-reference-docs/`) was missing all content for `Groundlight` and `ExperimentalApi` -- only the API response object models were rendering. **Root cause:** PR #413 ("Migrate Edge Configuration to SDK") introduced `groundlight/edge/config.py`, which does `import yaml`. PR #419 ("SDK Configures Edge") then wired this into the import chain accessible from `groundlight/__init__.py`. When sphinx builds the docs, it installs only the `sphinx-deps` dependency group (via `poetry install --no-root --only sphinx-deps`). Since `pyyaml` was not in that group, sphinx's `autodoc` failed to import `groundlight.Groundlight` and `groundlight.ExperimentalApi` with `No module named 'yaml'`. Sphinx treated this as a non-fatal warning and silently omitted those sections from the built docs. The docs have been broken since the April 7 deploy. ## Changes - **`pyproject.toml`**: Removed duplicate dependencies from `sphinx-deps` that were already in the main deps group (`pillow`, `pydantic`, `python-dateutil`). The `sphinx-deps` group now only contains sphinx-specific packages. - **`Makefile`**: Changed `install-sphinx-deps` to install both the `main` and `sphinx-deps` groups (`--only main --only sphinx-deps`), so sphinx always has access to whatever the SDK imports. Also added `-W` to `SPHINXOPTS` so sphinx treats warnings as errors -- CI will now fail immediately if autodoc can't import a documented class, preventing this class of silent breakage in the future. - **`sphinx_docs/conf.py`**: Removed `html_static_path` entry referencing a non-existent `_static` directory. - **`sphinx_docs/models.rst`**: Added `EdgeEndpointApi` as a documented class under a new "Edge Endpoint API" section. - **`src/groundlight/edge/api.py`**: Improved `EdgeEndpointApi` class docstring to explain how it's accessed (`gl.edge`). - **`src/groundlight/client.py`** and **`src/groundlight/experimental_api.py`**: Fixed pre-existing RST docstring formatting issues (indentation errors, missing `::` on code block headers, trailing underscores interpreted as hyperlink references) that `-W` surfaced. --------- Co-authored-by: Tim Huff <thuff@axon.com>
1 parent ca6838a commit e6178a8

8 files changed

Lines changed: 34 additions & 19 deletions

File tree

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ format: install-lint ## Run standard python formatting
7979

8080
# Targets for building code.groundlight.ai and API reference documentation
8181

82-
install-sphinx-deps: ## Only install the sphinx dependencies
83-
poetry install --no-root --only sphinx-deps
82+
install-sphinx-deps: ## Install the main dependencies and sphinx-specific dependencies
83+
poetry install --no-root --only main --only sphinx-deps
8484

8585
# The following is auto-generated by sphinx-quickstart:
8686
# To test out doc changes locally, run
8787
# poetry run make html && open build/html/index.html
88-
SPHINXOPTS ?=
88+
SPHINXOPTS ?= -W
8989
SPHINXBUILD ?= sphinx-build
9090
SOURCEDIR = sphinx_docs
9191
BUILDDIR = build

generated/groundlight_openapi_client/api/image_queries_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ def list_image_queries(self, **kwargs):
425425

426426
def submit_image_query(self, detector_id, **kwargs):
427427
"""submit_image_query # noqa: E501
428-
428+
429429
Submit an image query against a detector. You must use `\"Content-Type: image/jpeg\"` or similar (image/png, image/webp, etc) for the image data. For example: ```Bash $ curl https://api.groundlight.ai/device-api/v1/image-queries?detector_id=det_abc123 \\ --header \"Content-Type: image/jpeg\" \\ --data-binary @path/to/filename.jpeg ``` # noqa: E501
430430
This method makes a synchronous HTTP request by default. To make an
431431
asynchronous HTTP request, please pass async_req=True

pyproject.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,8 @@ types-PyYAML = "^6.0.0"
4343
types-requests = "^2.28.11.17"
4444

4545
[tool.poetry.group.sphinx-deps.dependencies]
46-
# These are extra / stricter dependencies required to build the API reference docs
4746
Sphinx = {version = "^7.2.6", python = ">=3.9,<4.0"}
4847
autodoc-pydantic = {version = "^2.0.1", python = ">=3.9,<4.0"}
49-
pillow = "^11.0.0"
50-
pydantic = "^2.0.0"
51-
python = ">=3.9,<4.0"
52-
python-dateutil = "^2.8.2"
5348
sphinx-rtd-theme = {version = "^1.3.0", python = ">=3.9,<4.0"}
5449
toml = "^0.10.2"
5550

sphinx_docs/conf.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,3 @@ def get_version_name() -> str:
5151
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
5252

5353
html_theme = "sphinx_rtd_theme"
54-
html_static_path = ["_static"]

sphinx_docs/models.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ SDK Client
99
:members:
1010
:special-members: __init__
1111

12+
Edge Endpoint API
13+
=====================
14+
15+
.. autoclass:: groundlight.edge.api.EdgeEndpointApi
16+
:members:
17+
1218
API Response Objects
1319
=====================
1420

src/groundlight/client.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ def create_detector( # noqa: PLR0913
434434
group_name="parking-monitoring",
435435
patience_time=60.0
436436
)
437+
437438
:param name: A short, descriptive name for the detector. This name should be unique within your account
438439
and help identify the detector's purpose.
439440
:param query: The question that the detector will answer about images. For binary classification,
@@ -609,7 +610,7 @@ def get_image_query(self, id: str) -> ImageQuery: # pylint: disable=redefined-b
609610
Get an ImageQuery by its ID. This is useful for retrieving the status and results of a
610611
previously submitted query.
611612
612-
**Example Usage:**
613+
**Example usage**::
613614
614615
gl = Groundlight()
615616
@@ -753,12 +754,14 @@ def submit_image_query( # noqa: PLR0913 # pylint: disable=too-many-arguments, t
753754
754755
:param detector: the Detector object, or string id of a detector like `det_12345`
755756
:param image: The image, in several possible formats:
757+
756758
- filename (string) of a jpeg file
757759
- byte array or BytesIO or BufferedReader with jpeg bytes
758760
- numpy array with values 0-255 and dimensions (H,W,3) in BGR order
759-
(Note OpenCV uses BGR not RGB. `img[:, :, ::-1]` will reverse the channels)
761+
(Note OpenCV uses BGR not RGB. `img[:, :, ::-1]` will reverse the channels)
760762
- PIL Image: Any binary format must be JPEG-encoded already.
761-
Any pixel format will get converted to JPEG at high quality before sending to service.
763+
Any pixel format will get converted to JPEG at high quality before sending to service.
764+
762765
:param wait: How long to poll (in seconds) for a confident answer. This is a client-side timeout.
763766
Default is 30.0. Set to 0 for async operation.
764767
:param patience_time: How long to wait (in seconds) for a confident answer for this image query.
@@ -874,11 +877,13 @@ def ask_confident( # noqa: PLR0913 # pylint: disable=too-many-arguments
874877
875878
:param detector: the Detector object, or string id of a detector like `det_12345`
876879
:param image: The image, in several possible formats:
880+
877881
- filename (string) of a jpeg file
878882
- byte array or BytesIO or BufferedReader with jpeg bytes
879883
- numpy array with values 0-255 and dimensions (H,W,3) in BGR order
880884
(Note OpenCV uses BGR not RGB. `img[:, :, ::-1]` will reverse the channels)
881885
- PIL Image
886+
882887
Any binary format must be JPEG-encoded already. Any pixel format will get
883888
converted to JPEG at high quality before sending to service.
884889
:param confidence_threshold: The confidence threshold to wait for.
@@ -944,11 +949,13 @@ def ask_ml( # noqa: PLR0913 # pylint: disable=too-many-arguments, too-many-loca
944949
945950
:param detector: the Detector object, or string id of a detector like `det_12345`
946951
:param image: The image, in several possible formats:
952+
947953
- filename (string) of a jpeg file
948954
- byte array or BytesIO or BufferedReader with jpeg bytes
949955
- numpy array with values 0-255 and dimensions (H,W,3) in BGR order
950956
(Note OpenCV uses BGR not RGB. `img[:, :, ::-1]` will reverse the channels)
951957
- PIL Image
958+
952959
Any binary format must be JPEG-encoded already. Any pixel format will get
953960
converted to JPEG at high quality before sending to service.
954961
:param wait: How long to wait (in seconds) for any ML prediction.
@@ -1032,12 +1039,14 @@ def ask_async( # noqa: PLR0913 # pylint: disable=too-many-arguments
10321039
10331040
:param detector: the Detector object, or string id of a detector like `det_12345`
10341041
:param image: The image, in several possible formats:
1042+
10351043
- filename (string) of a jpeg file
10361044
- byte array or BytesIO or BufferedReader with jpeg bytes
10371045
- numpy array with values 0-255 and dimensions (H,W,3) in BGR order
10381046
(Note OpenCV uses BGR not RGB. `img[:, :, ::-1]` will reverse the channels)
10391047
- PIL Image: Any binary format must be JPEG-encoded already.
10401048
Any pixel format will get converted to JPEG at high quality before sending to service.
1049+
10411050
:param patience_time: How long to wait (in seconds) for a confident answer for this image query.
10421051
The longer the patience_time, the more likely Groundlight will arrive at a
10431052
confident answer. This is a soft server-side timeout. If not set, use the
@@ -1236,7 +1245,7 @@ def add_label(
12361245
Examples for other answer modes can be found in the documentation for each of the modes.
12371246
12381247
:param image_query: Either an ImageQuery object (returned from methods like
1239-
`ask_ml`) or an image query ID string starting with "iq_".
1248+
`ask_ml`) or an image query ID string starting with ``iq_``.
12401249
12411250
:param label: The label value to assign, typically "YES" or "NO" for binary
12421251
classification detectors. For multi-class detectors, use one of
@@ -1442,7 +1451,7 @@ def update_detector_status(self, detector: Union[str, Detector], enabled: bool)
14421451
# Using a detector ID string directly
14431452
gl.update_detector_status("det_abc123", enabled=True) # Enable the detector
14441453
1445-
:param detector: Either a Detector object or a detector ID string starting with "det_".
1454+
:param detector: Either a Detector object or a detector ID string starting with ``det_``.
14461455
The detector whose status should be updated.
14471456
:param enabled: Boolean indicating whether the detector should be enabled (True) or
14481457
disabled (False). When disabled, the detector will not process new queries.
@@ -1478,7 +1487,7 @@ def update_detector_escalation_type(self, detector: Union[str, Detector], escala
14781487
# Re-enable standard human labeling
14791488
gl.update_detector_escalation_type("det_abc123", "STANDARD")
14801489
1481-
:param detector: Either a Detector object or a detector ID string starting with "det_".
1490+
:param detector: Either a Detector object or a detector ID string starting with ``det_``.
14821491
The detector whose escalation type should be updated.
14831492
:param escalation_type: The new escalation type setting. Must be one of:
14841493
- "STANDARD": Allow human labeling for low-confidence queries
@@ -1516,7 +1525,7 @@ def delete_detector(self, detector: Union[str, Detector]) -> None:
15161525
# Using a detector ID string directly
15171526
gl.delete_detector("det_abc123")
15181527
1519-
:param detector: Either a Detector object or a detector ID string starting with "det_".
1528+
:param detector: Either a Detector object or a detector ID string starting with ``det_``.
15201529
The detector to delete.
15211530
15221531
:return: None

src/groundlight/edge/api.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ class EdgeEndpointApi:
1616
"""
1717
Namespace for operations that are specific to the Edge Endpoint,
1818
such as setting and getting the EdgeEndpoint configuration.
19+
20+
Currently only available through :class:`~groundlight.ExperimentalApi`. Accessed via the
21+
``edge`` attribute::
22+
23+
gl = ExperimentalApi()
24+
gl.edge.set_config(config)
1925
"""
2026

2127
def __init__(self, client) -> None:

src/groundlight/experimental_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def reset_detector(self, detector: Union[str, Detector]) -> None:
183183
# Using a detector ID string directly
184184
gl.reset_detector("det_abc123")
185185
186-
:param detector: Either a Detector object or a detector ID string starting with "det_".
186+
:param detector: Either a Detector object or a detector ID string starting with ``det_``.
187187
The detector whose data should be reset.
188188
189189
:return: None
@@ -207,7 +207,7 @@ def update_detector_name(self, detector: Union[str, Detector], name: str) -> Non
207207
# Using a detector ID string directly
208208
gl.update_detector_name("det_abc123", "new_detector_name")
209209
210-
:param detector: Either a Detector object or a detector ID string starting with "det_".
210+
:param detector: Either a Detector object or a detector ID string starting with ``det_``.
211211
The detector whose name should be updated.
212212
:param name: The new name to assign to the detector
213213

0 commit comments

Comments
 (0)