[py] Publish a machine-readable API reference and ship guidance in the wheel - #17906
Open
AutomatedTester wants to merge 4 commits into
Open
AutomatedTester wants to merge 4 commits into
AutomatedTester wants to merge 4 commits into
Conversation
…achines A growing share of Selenium's documentation is read by models rather than people: during training, during retrieval, and live over HTTP when a coding agent is asked to write a Selenium test. When that reading goes badly the model falls back on stale priors and emits DesiredCapabilities, an executable_path, a third-party driver manager, and a sleep where a wait belongs — and users attribute that code to Selenium. Reviews what this repository publishes today across all five bindings and sets out six tracks of work to fix it, with the waves that can run in parallel. Findings include: the API reference has no machine-readable entry point and is unlinked from the site llms.txt; objects.inv, element-list and xrefmap.yml are generated and then discarded; the Python docs have three competing copies and no canonical URL; deprecation markers exist in every binding but the "gone, use this instead" mapping exists nowhere consumable; and nothing LLM-facing ships inside the wheel, gem, jar, npm package or nupkg.
…e wheel The Python API reference is increasingly read by machines — crawlers, retrieval pipelines, and coding agents fetching it live — and it offered them no entry point, no canonical URL, and no way to tell a current API from one removed several releases ago. Three copies of the Python docs compete for recall, none of them declaring which is authoritative. Canonical URL: sets html_baseurl so every page, including the per-commit Read the Docs preview, carries rel=canonical pointing at the released reference. Rewrites the index wording to name that build as canonical and Read the Docs as a preview of the next release. Machine-readable output: a new Sphinx extension writes llms.txt and sitemap.xml into the HTML root; objects.inv is documented at its stable URL; and generate_deprecations.py parses the sources with ast to emit deprecations.json, publishing 16 deprecated APIs with the replacement to use instead. Swaps viewcode for linkcode so source links point at GitHub at the release tag rather than at a second, non-canonical copy of the source rendered into the site. In-package guidance: selenium/llms.txt ships inside the wheel, so a tool with the package on disk finds the project's own guidance instead of inferring it. The published llms.txt reads its rules back out of that file, leaving one copy rather than two to drift apart. Implements the Python tracks of docs/plans/llm-facing-documentation.md.
The dataset is committed, so every field in it has to survive edits that have nothing to do with deprecations. A line number does not: inserting a line anywhere above a `warnings.warn` call invalidates it. CI made that concrete. Pull requests are evaluated as their merge with trunk, so the sync test compared a dataset generated on this branch against sources that included trunk's later commits, and failed on three entries in remote/webdriver.py whose warnings had shifted by one line. Nothing about the deprecations had changed. The same failure would hit any contributor whose change shifted a line in a file declaring a deprecation, and would hit this dataset again on the next such commit to trunk. `api` already addresses an entry, and does not go stale. Line numbers now only order the result, which is what they were useful for.
Rebasing onto trunk picked up a newer ruff pin that flags the equivalent list comprehension as C416. Also refreshes the version stamp in the published dataset; the deprecation set is unchanged.
AutomatedTester
force-pushed
the
copse/review-the-documentation-creation-in-this-f927d8
branch
from
September 16, 2026 16:03
428e8c5 to
a5c1828
Compare
Member
|
I don't understand, is this an ARD or something just for Python? |
Member
Author
|
This is something for python for now but happy to turn this into an ADR. At the moment it was more of a test to see how things would happen. Let me know your preference. |
Member
|
I don't think we need an ADR for this. As this one is about Python, it would be good to have an issue that tracks implementation for all of the languages. This makes sense to implement across languages. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 Related Issues
None yet. The review that motivated this is committed alongside it as
docs/plans/llm-facing-documentation.md; This will be removed before merging💥 What does this PR do?
A growing share of Selenium's documentation is read by machines rather than people — during training, during retrieval, and live over HTTP when a coding agent is asked to "write a Selenium test". When that reading goes badly the model falls back on stale priors and emits
DesiredCapabilities, anexecutable_path, a third-party driver manager, and asleepwhere a wait belongs. Users then attribute that code to Selenium.This implements the Python tracks of the attached plan. The plan itself covers all five bindings; nothing here changes any other binding.
Canonical URL. Three copies of the Python API docs compete for recall — the release build on selenium.dev, the per-commit Read the Docs preview, and unofficial mirrors that outrank both — and none of them declared which was authoritative. Sets
html_baseurl, so every page (including the Read the Docs build) carriesrel=canonicalpointing at the released reference. Rewrites the index wording to name that build as canonical and Read the Docs as a preview of the next release.Machine-readable output, all at stable URLs under
/selenium/docs/api/py/:llms.txtpy/docs/source/_ext/llm_assets.pysitemap.xmlobjects.invdeprecations.jsonpy/generate_deprecations.pydeprecations.jsoncurrently publishes 16 deprecated APIs, each with the replacement to use instead, parsed straight out of thewarnings.warnmessages. That mapping previously existed only as prose inside function bodies, where nothing but a running program could read it.In-package guidance.
selenium/llms.txtnow ships inside the wheel, so a tool with the package on disk finds the project's own guidance instead of inferring it. The publishedllms.txtreads its rules back out of that same file, so there is one copy rather than two to drift apart.🔧 Implementation Notes
deprecations.jsonis committed, not just generated. It lives inpy/docs/source/_extra/and is published verbatim viahtml_extra_path. Committing it means a PR that deprecates something shows the deprecation in its diff, and it meansbazel build //py:docsworks on a clean checkout. A unit test fails if it stops matching the source. This needed narrow negations in.gitignore, which otherwise ignores everything underpy/docs/source/to keep the autosummary stubs out.The dataset deliberately records no line numbers. CI evaluates a pull request as its merge with trunk, so a published line number goes stale when trunk moves, not only when the branch changes — any PR inserting a line above a
warnings.warnwould fail the sync test.apialready addresses each entry. A regression test pins this.viewcodeis replaced bylinkcode— the two conflict, so this is a choice rather than an addition.viewcoderendered ~140 modules of source into the site as a second, non-canonical copy of what is already on GitHub, which is the same duplicate-content problem this PR is otherwise trying to fix.linkcode_resolvelinks each object to GitHub at the release tag with a line anchor. This does delete published pages (_modules/**) — nothing in the repo references them, but it is the one change here that removes rather than adds, and it is easy to revert on its own if maintainers disagree.intersphinxadds a network fetch to the docs build. Inventories for the stdlib, trio and urllib3 are fetched at build time. Timeout is 5s and a failure degrades to plain literals rather than erroring, but it is a new network dependency forbazel build //py:docsand worth a maintainer's opinion.The guidance rules themselves are deliberately versioned — each says which release the old form stopped being correct in (
executable_path4.10,find_element_by_*4.3,options.headless4.9), because a reader that has absorbed a decade of blog posts needs the version to know which memory to discard.🤖 AI assistance
docs/plans/llm-facing-documentation.md, and a first pass at all of the Python changes — the Sphinx extension, the deprecation extractor, theconf.pychanges, the unit tests, and the prose inpy/selenium/llms.txt.💡 Additional Considerations
Verification. Rebased onto trunk and verified locally with Bazel:
bazel build //py:docs— build succeeded. The extension reportswrote llms.txt and sitemap.xml (138 pages);llms.txt,sitemap.xml,objects.invanddeprecations.jsonare all present in the HTML root, the publisheddeprecations.jsonis byte-identical to the committed one,rel=canonicalis emitted,_modules/is correctly absent, and spot-checkedlinkcodeanchors land on the right lines. No new Sphinx warnings come from any of the added code.bazel test //py:unit --test_size_filters=small— 34 tests pass, including both new files.bazel run //py:ruff-check -- --no-fixand//py:ruff-format— clean.An earlier revision of this PR could not run any of the above locally (a TLS failure fetching
mocha), so the description previously said the Sphinx build was unverified. That no longer holds — it has now been built and its output inspected.Follow-up work, from the plan:
deprecations.jsonfiles need merging into one cross-binding dataset (D1).docs/api/llms.txtand a real landing page at/selenium/docs/api/(A1, A2) need all five bindings first.llms.txt, and aSitemap:reference for/selenium/docs/api/, are changes inSeleniumHQ/seleniumhq.github.io(B2, A4).🔄 Types of changes