Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ The repo also ships a self-contained **reference bridge demo** (`mqtt_demo/`) th

## Documentation

- **[`docs/api.md`](docs/api.md)** — the supported API: every name downstream code may import, with its signature. Generated from the code, so it cannot drift.
- [`docs/ocf-pki-laundry.md`](docs/ocf-pki-laundry.md) — the newer OCF-PKI appliance generation, and why an AC14K_M certificate is refused there.
- [`docs/ocf-vd-devices.md`](docs/ocf-vd-devices.md) — server-authenticated findings from Samsung VD hardware.
- **[`docs/api.md`](https://github.com/QuiteYellow/SmartThings-Local/blob/main/docs/api.md)** — the supported API: every name downstream code may import, with its signature. Generated from the code, so it cannot drift.
- [`docs/ocf-pki-laundry.md`](https://github.com/QuiteYellow/SmartThings-Local/blob/main/docs/ocf-pki-laundry.md) — the newer OCF-PKI appliance generation, and why an AC14K_M certificate is refused there.
- [`docs/ocf-vd-devices.md`](https://github.com/QuiteYellow/SmartThings-Local/blob/main/docs/ocf-vd-devices.md) — server-authenticated findings from Samsung VD hardware.

## Quick start (library)

Expand Down Expand Up @@ -217,7 +217,7 @@ The public API is organized by responsibility rather than re-exported through
one large root namespace. Explicit imports from these modules are intentional
and covered by the downstream compatibility contract.

**[`docs/api.md`](docs/api.md) is the full reference**: every supported name, with its signature read off the code. It is generated from `tools/api_contract.py` by `tools/generate_api_docs.py`, and the test suite fails if the page and the code disagree. A public name absent from it is reachable but incidental, and may move. The table below is the map; that page is the inventory.
**[`docs/api.md`](https://github.com/QuiteYellow/SmartThings-Local/blob/main/docs/api.md) is the full reference**: every supported name, with its signature read off the code. It is generated from `tools/api_contract.py` by `tools/generate_api_docs.py`, and the test suite fails if the page and the code disagree. A public name absent from it is reachable but incidental, and may move. The table below is the map; that page is the inventory.

| Module | Supported responsibility |
| --- | --- |
Expand Down Expand Up @@ -1185,4 +1185,4 @@ This is an independent, unofficial project. It is **not affiliated with, authori

"Samsung", "SmartThings", and any related names, marks, and logos are trademarks of Samsung Electronics Co., Ltd. They are used in this project **only nominatively** — to identify the hardware and protocols this software interoperates with — and no claim is made to any right in them. Use of these marks does not imply any affiliation with or endorsement by their owner.

The software is provided under the [MIT License](LICENSE) for interoperability with hardware you own, without warranty of any kind.
The software is provided under the [MIT License](https://github.com/QuiteYellow/SmartThings-Local/blob/main/LICENSE) for interoperability with hardware you own, without warranty of any kind.
34 changes: 34 additions & 0 deletions tests/test_public_api_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,37 @@ def test_contents_links_resolve_to_a_heading_on_the_page():
assert anchors, "the page should carry a table of contents"
for anchor in anchors:
assert anchor in headings, anchor


_REPO_ROOT = Path(__file__).resolve().parent.parent
_REPO_BLOB = "https://github.com/QuiteYellow/SmartThings-Local/blob/main/"


def test_readme_links_render_on_pypi_and_on_github():
"""pyproject sets `readme = "README.md"`, so this file is also the
package's PyPI description.

PyPI renders it standalone with no base URL, so a relative path resolves
against pypi.org and 404s. GitHub resolves the same path against the
repository, which is why a relative link looks fine in review and is
dead on the package page. Links are therefore either absolute or an
intra-document anchor.
"""
readme = (_REPO_ROOT / "README.md").read_text()
headings = {
generate_api_docs._slug(line)
for line in readme.splitlines()
if line.startswith("#")
}

for target in re.findall(r"\]\(([^)]+)\)", readme):
if target.startswith("#"):
assert target[1:] in headings, f"README anchor goes nowhere: {target}"
continue
assert target.startswith(("https://", "http://")), (
f"relative README link will not render on PyPI: {target}. "
f"Use {_REPO_BLOB}{target}"
)
if target.startswith(_REPO_BLOB):
path = _REPO_ROOT / target[len(_REPO_BLOB):].split("#", 1)[0]
assert path.exists(), f"README links to a missing file: {target}"