Add CI lint for Python code examples#364
Conversation
- Add lint-code-examples.py script that extracts Python blocks from MDX files and validates them: runner hash pinning, deprecated API detection, AST lint via genvm-lint, and syntax checks for snippets - Add CI workflow (lint-code-examples.yml) triggered on PRs and pushes to main when pages/ or the lint script change - Fix deprecated APIs across 20 MDX files: gl.get_webpage -> gl.nondet.web.get, gl.eq_principle_strict_eq -> gl.eq_principle.strict_eq, gl.eq_principle_prompt_comparative -> gl.eq_principle.prompt_comparative, gl.eq_principle_prompt_non_comparative -> gl.eq_principle.prompt_non_comparative, gl.exec_prompt -> gl.nondet.exec_prompt - Pin all runner hashes from "test" to specific version
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
✅ Deploy Preview for genlayer-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughThis PR updates documentation examples to adopt the latest GenLayer API naming conventions, pins specific dependency versions across code samples, adds GitHub Actions CI workflow for linting code examples, and introduces a comprehensive Python linting script that validates code blocks within MDX documentation for correctness and API compliance. Changes
Sequence DiagramsequenceDiagram
participant GH as GitHub Actions
participant WF as lint-code-examples.yml
participant PY as lint-code-examples.py
participant MDX as MDX Files
participant Linter as genvm-lint
GH->>WF: trigger on PR/push
WF->>WF: checkout code
WF->>WF: setup Python 3.12
WF->>WF: install genvm-linter
WF->>PY: execute script
PY->>MDX: extract_python_blocks()
MDX-->>PY: block metadata (code, type, depends)
PY->>PY: check_runner_versions()
PY->>PY: check_deprecated_apis()
PY->>PY: identify complete contracts
PY->>Linter: lint_contract() via genvm-lint
Linter-->>PY: lint results (JSON)
PY->>PY: classify_snippet()
PY->>PY: syntax_check() via AST
PY->>PY: wrap_snippet() if needed
PY->>Linter: lint_snippet() via genvm-lint
Linter-->>PY: lint results
PY-->>GH: aggregated results
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan for PR comments
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pages/developers/intelligent-contracts/features/vector-storage.mdx (1)
40-65:⚠️ Potential issue | 🟠 MajorAdd the missing
import typingto this snippet.This example uses
typing.Literalon lines 55 and 65, buttypingis never imported. In Python 3.12+, this causes aNameErrorat definition time, making the docs example non-executable as written.Proposed fix
from genlayer import * import genlayermodelwrappers import numpy as np from dataclasses import dataclass +import typing🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pages/developers/intelligent-contracts/features/vector-storage.mdx` around lines 40 - 65, The snippet uses typing.Literal in the StoreValue dataclass and LogIndexer (VecDB and get_embedding signatures) but never imports typing; add an import typing at the top of the file so typing.Literal is defined (ensuring references in StoreValue, LogIndexer.vector_store, and LogIndexer.get_embedding resolve correctly).
🧹 Nitpick comments (2)
pages/developers/intelligent-contracts/examples/user-storage.mdx (1)
38-38: Documentation references outdated API name.The prose mentions
contract_runner.from_addressbut the code usesgl.message.sender_address. Since this PR is updating deprecated APIs across documentation, consider fixing these references for consistency.📝 Suggested documentation fix
Line 38:
-- **Write Method**: `update_storage(new_storage)` allows updating the stored value for the user who called the contract (identified by `contract_runner.from_address`). +- **Write Method**: `update_storage(new_storage)` allows updating the stored value for the user who called the contract (identified by `gl.message.sender_address`).Line 61:
-- The contract updates the `self.storage` dictionary, associating the new value with the address of the user who called the function (`contract_runner.from_address`). +- The contract updates the `self.storage` dictionary, associating the new value with the address of the user who called the function (`gl.message.sender_address`).Also applies to: 61-61
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pages/developers/intelligent-contracts/examples/user-storage.mdx` at line 38, Update the documentation prose to use the current API name: replace references to contract_runner.from_address with gl.message.sender_address in the description of the Write Method and any other occurrences (e.g., near the mention of update_storage(new_storage)) so the docs match the code that uses gl.message.sender_address..github/workflows/lint-code-examples.yml (1)
22-23: Pin the linter version to prevent unexpected CI failures.The workflow installs an unpinned
genvm-linterpackage (line 22) and relies on thegenvm-lintCLI command, which is called at line 123 inscripts/lint-code-examples.py. If a new release changes the CLI interface or removes the console script, CI will fail without any changes to the repository code.The
genvm-linterpackage does export agenvm-lintconsole script. Pin a tested version in the workflow (e.g.,pip install genvm-linter==0.8.0).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/lint-code-examples.yml around lines 22 - 23, Pin the genvm-linter package in the workflow by changing the pip install step that currently installs "genvm-linter" to install a specific tested version (for example "genvm-linter==0.8.0"); update the run step that installs genvm-linter so CI uses the pinned version, ensuring the subsequent use of the genvm-lint console script (invoked by scripts/lint-code-examples.py) remains stable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/lint-code-examples.yml:
- Around line 4-12: Add the workflow file itself to the path filters so changes
to .github/workflows/lint-code-examples.yml will trigger the job; specifically
update the pull_request.paths and push.paths lists in the workflow to include
'.github/workflows/lint-code-examples.yml' alongside 'pages/**/*.mdx' and
'scripts/lint-code-examples.py' (edit the paths section around the existing
entries in the lint-code-examples job).
In `@pages/developers/intelligent-contracts/crafting-prompts.mdx`:
- Around line 58-60: The output from gl.nondet.exec_prompt stored in res must
have only the surrounding code-fence removed before calling json.loads; update
the handling around res (after the call to gl.nondet.exec_prompt and before
json.loads) to robustly strip a leading fence line (any line that starts with
"```" optionally followed by a language tag, case-insensitive, and optional
spaces) and a trailing fence line (a line that after stripping whitespace equals
"```"), by splitting res into lines, dropping the first line if it startswith
"```" (case-insensitive check) and dropping the last line if its stripped form
is "```", then rejoin and strip the result before passing to json.loads; keep
references to res, gl.nondet.exec_prompt, and json.loads so the change is easy
to locate.
In `@pages/developers/intelligent-contracts/examples/fetch-github-profile.mdx`:
- Around line 39-46: Update the page to complete the terminology change from the
"comparative equivalence principle" to the current API name
gl.eq_principle.strict_eq(): replace any text mentions of the old phrase with
gl.eq_principle.strict_eq() and adjust surrounding wording to match the
deterministic-equivalence framing used elsewhere; remove the stale mention of
the removed parameter mode="text" (and any example calls to gl.nondet.web.get()
that include it) and ensure examples and the show_github_profile() read method
description consistently reference gl.nondet.web.get() +
gl.eq_principle.strict_eq() semantics only.
In `@pages/developers/intelligent-contracts/examples/fetch-web-content.mdx`:
- Line 105: Update the docs to state that mode parameters apply only to
gl.nondet.web.render(), not gl.nondet.web.get(); clarify that
gl.nondet.web.get() returns plain text by default and remove the misleading
reference to mode="text" for the get() examples, and make both occurrences
describing mode="html" (the ones referencing mode="html" and the "full HTML
document") consistent by saying mode="html" for gl.nondet.web.render() returns
the page's HTML <body> (not the entire document or other scope).
In `@pages/developers/intelligent-contracts/examples/prediction.mdx`:
- Around line 52-53: Replace the raw HTTP fetch with the LLM-friendly renderer:
instead of calling gl.nondet.web.get(self.resolution_url) and decoding bytes
into web_data, call gl.nondet.web.render(self.resolution_url, mode='text') and
assign its returned text directly to web_data so the prompt receives plain-text
rendered content; update any references to response to use web_data and remove
the .body.decode(...) flow.
In `@pages/developers/intelligent-contracts/first-contract.mdx`:
- Around line 10-12: Update the explanatory sentence so it matches the code
example that pins a specific release hash: replace the phrase saying "`test`
after a colon is a version" with wording that the value after the colon (e.g.
"py-genlayer:1jb45aa8...") is a version hash identifying a specific frozen
GenVM/GenLayer release—e.g., "It is similar to Solidity's `pragma solidity`, and
the value after the colon is a version hash that identifies a specific frozen
GenVM release."
In `@scripts/lint-code-examples.py`:
- Around line 309-310: The check `"/_" in mdx_file.name` never matches because
Path.name never contains slashes; update the condition to use
mdx_file.name.startswith("_") (and keep the existing "/_advanced/" in
str(mdx_file) check) so it skips underscore-prefixed files: change the
conditional to `if "/_advanced/" in str(mdx_file) or
mdx_file.name.startswith("_"): continue`, and apply this same fix to the other
two occurrences of the same pattern in the file.
- Around line 159-175: classify_snippet() currently examines the first nonblank
line only, which misclassifies snippets with leading imports or comments; update
the logic that builds stripped/lines/first_line to first skip any leading blank
lines, import statements (lines starting with "import" or "from "), and comment
lines (starting with "#" or triple-quote blocks) so that first_line and the
subsequent scans examine the first meaningful line; keep the existing checks for
decorator prefixes ("@gl.public", "@gl.evm", "@") and for "def " with "(self"
unchanged, and ensure the detection loop that looks for any "def " in lines also
operates on the trimmed list of meaningful lines so wrap_snippet() no longer
wraps class-method examples incorrectly.
---
Outside diff comments:
In `@pages/developers/intelligent-contracts/features/vector-storage.mdx`:
- Around line 40-65: The snippet uses typing.Literal in the StoreValue dataclass
and LogIndexer (VecDB and get_embedding signatures) but never imports typing;
add an import typing at the top of the file so typing.Literal is defined
(ensuring references in StoreValue, LogIndexer.vector_store, and
LogIndexer.get_embedding resolve correctly).
---
Nitpick comments:
In @.github/workflows/lint-code-examples.yml:
- Around line 22-23: Pin the genvm-linter package in the workflow by changing
the pip install step that currently installs "genvm-linter" to install a
specific tested version (for example "genvm-linter==0.8.0"); update the run step
that installs genvm-linter so CI uses the pinned version, ensuring the
subsequent use of the genvm-lint console script (invoked by
scripts/lint-code-examples.py) remains stable.
In `@pages/developers/intelligent-contracts/examples/user-storage.mdx`:
- Line 38: Update the documentation prose to use the current API name: replace
references to contract_runner.from_address with gl.message.sender_address in the
description of the Write Method and any other occurrences (e.g., near the
mention of update_storage(new_storage)) so the docs match the code that uses
gl.message.sender_address.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1b674ddc-2347-41c7-8e9b-cd18e16c5a17
📒 Files selected for processing (23)
.github/workflows/lint-code-examples.ymlpages/api-references/genlayer-test.mdxpages/developers/intelligent-contracts/crafting-prompts.mdxpages/developers/intelligent-contracts/examples/fetch-github-profile.mdxpages/developers/intelligent-contracts/examples/fetch-web-content.mdxpages/developers/intelligent-contracts/examples/github-profile-projects.mdxpages/developers/intelligent-contracts/examples/github-profile-summary.mdxpages/developers/intelligent-contracts/examples/llm-hello-world-non-comparative.mdxpages/developers/intelligent-contracts/examples/llm-hello-world.mdxpages/developers/intelligent-contracts/examples/prediction.mdxpages/developers/intelligent-contracts/examples/storage.mdxpages/developers/intelligent-contracts/examples/user-storage.mdxpages/developers/intelligent-contracts/examples/vector-store-log-indexer.mdxpages/developers/intelligent-contracts/examples/wizard-of-coin.mdxpages/developers/intelligent-contracts/features/debugging.mdxpages/developers/intelligent-contracts/features/upgradability.mdxpages/developers/intelligent-contracts/features/vector-storage.mdxpages/developers/intelligent-contracts/first-contract.mdxpages/developers/intelligent-contracts/first-intelligent-contract.mdxpages/developers/intelligent-contracts/introduction.mdxpages/developers/intelligent-contracts/storage.mdxpages/validators/setup-guide.mdxscripts/lint-code-examples.py
💤 Files with no reviewable changes (1)
- pages/validators/setup-guide.mdx
| pull_request: | ||
| paths: | ||
| - 'pages/**/*.mdx' | ||
| - 'scripts/lint-code-examples.py' | ||
| push: | ||
| branches: [main] | ||
| paths: | ||
| - 'pages/**/*.mdx' | ||
| - 'scripts/lint-code-examples.py' |
There was a problem hiding this comment.
Include this workflow file in its own path filters.
A PR that only changes .github/workflows/lint-code-examples.yml will not run this job today, so workflow regressions can merge without ever exercising the updated definition.
Suggested fix
on:
pull_request:
paths:
+ - '.github/workflows/lint-code-examples.yml'
- 'pages/**/*.mdx'
- 'scripts/lint-code-examples.py'
push:
branches: [main]
paths:
+ - '.github/workflows/lint-code-examples.yml'
- 'pages/**/*.mdx'
- 'scripts/lint-code-examples.py'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| pull_request: | |
| paths: | |
| - 'pages/**/*.mdx' | |
| - 'scripts/lint-code-examples.py' | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'pages/**/*.mdx' | |
| - 'scripts/lint-code-examples.py' | |
| on: | |
| pull_request: | |
| paths: | |
| - '.github/workflows/lint-code-examples.yml' | |
| - 'pages/**/*.mdx' | |
| - 'scripts/lint-code-examples.py' | |
| push: | |
| branches: [main] | |
| paths: | |
| - '.github/workflows/lint-code-examples.yml' | |
| - 'pages/**/*.mdx' | |
| - 'scripts/lint-code-examples.py' |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/lint-code-examples.yml around lines 4 - 12, Add the
workflow file itself to the path filters so changes to
.github/workflows/lint-code-examples.yml will trigger the job; specifically
update the pull_request.paths and push.paths lists in the workflow to include
'.github/workflows/lint-code-examples.yml' alongside 'pages/**/*.mdx' and
'scripts/lint-code-examples.py' (edit the paths section around the existing
entries in the lint-code-examples job).
| res = gl.nondet.exec_prompt(prompt) | ||
| backticks = "``" + "`" | ||
| res = res.replace(backticks + "json", "").replace(backticks, "") |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
python - <<'PY'
import json
def current(res: str) -> str:
backticks = "``" + "`"
return res.replace(backticks + "json", "").replace(backticks, "")
samples = {
"lowercase json": "```json\n{\"give_coin\": false}\n```",
"uppercase JSON": "```JSON\n{\"give_coin\": false}\n```",
"space after fence": "``` json\n{\"give_coin\": false}\n```",
"bare fence": "```\n{\"give_coin\": false}\n```",
}
for name, sample in samples.items():
cleaned = current(sample)
try:
json.loads(cleaned)
verdict = "parses"
except Exception as exc:
verdict = f"fails: {exc}"
print(f"{name}: {verdict}")
PYRepository: genlayerlabs/genlayer-docs
Length of output: 244
🏁 Script executed:
fd crafting-prompts.mdx --type fRepository: genlayerlabs/genlayer-docs
Length of output: 129
🏁 Script executed:
cat -n pages/developers/intelligent-contracts/crafting-prompts.mdx | sed -n '50,70p'Repository: genlayerlabs/genlayer-docs
Length of output: 953
Strip only surrounding code fences before json.loads.
The current implementation only handles the exact lowercase ```json case. Testing against common LLM output variants shows:
uppercase JSON: fails withExpecting value: line 1 column 1space after fence(``` json): fails withExpecting value: line 1 column 2bare fence: parses (only by accident)lowercase json: parses
This will cause the documented example to fail at runtime on typical LLM outputs.
Proposed fix
def nondet():
res = gl.nondet.exec_prompt(prompt)
- backticks = "``" + "`"
- res = res.replace(backticks + "json", "").replace(backticks, "")
+ res = res.strip()
+ if res.startswith("```"):
+ lines = res.splitlines()
+ if lines:
+ lines = lines[1:]
+ if lines and lines[-1].strip() == "```":
+ lines = lines[:-1]
+ res = "\n".join(lines).strip()
print(res)
dat = json.loads(res)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pages/developers/intelligent-contracts/crafting-prompts.mdx` around lines 58
- 60, The output from gl.nondet.exec_prompt stored in res must have only the
surrounding code-fence removed before calling json.loads; update the handling
around res (after the call to gl.nondet.exec_prompt and before json.loads) to
robustly strip a leading fence line (any line that starts with "```" optionally
followed by a language tag, case-insensitive, and optional spaces) and a
trailing fence line (a line that after stripping whitespace equals "```"), by
splitting res into lines, dropping the first line if it startswith "```"
(case-insensitive check) and dropping the last line if its stripped form is
"```", then rejoin and strip the result before passing to json.loads; keep
references to res, gl.nondet.exec_prompt, and json.loads so the change is easy
to locate.
| - Uses `gl.eq_principle.strict_eq()` to ensure all nodes agree on the same profile content. | ||
| - **Read Method**: | ||
| - `show_github_profile()` returns the stored profile content. | ||
|
|
||
| ## Key Components | ||
|
|
||
| 1. **GitHub Integration**: The contract uses `gl.get_webpage()` to fetch content from GitHub profiles. | ||
| 2. **Deterministic Execution**: `gl.eq_principle_strict_eq()` ensures that all nodes in the network arrive at the same exact content. | ||
| 1. **GitHub Integration**: The contract uses `gl.nondet.web.get()` to fetch content from GitHub profiles. | ||
| 2. **Deterministic Execution**: `gl.eq_principle.strict_eq()` ensures that all nodes in the network arrive at the same exact content. |
There was a problem hiding this comment.
Finish the terminology update across the whole page.
This section now documents gl.eq_principle.strict_eq(), but the page still has stale references to the old behavior: Line 3 says the example uses the comparative equivalence principle, and Line 95 still mentions the removed mode="text" parameter. That leaves the example internally inconsistent for readers.
🧰 Tools
🪛 LanguageTool
[style] ~46-~46: This phrase is redundant. Consider writing “same”.
Context: ... all nodes in the network arrive at the same exact content. 3. State Management: The c...
(SAME_EXACT)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pages/developers/intelligent-contracts/examples/fetch-github-profile.mdx`
around lines 39 - 46, Update the page to complete the terminology change from
the "comparative equivalence principle" to the current API name
gl.eq_principle.strict_eq(): replace any text mentions of the old phrase with
gl.eq_principle.strict_eq() and adjust surrounding wording to match the
deterministic-equivalence framing used elsewhere; remove the stale mention of
the removed parameter mode="text" (and any example calls to gl.nondet.web.get()
that include it) and ensure examples and the show_github_profile() read method
description consistently reference gl.nondet.web.get() +
gl.eq_principle.strict_eq() semantics only.
| ## HTML Mode for Web Content | ||
|
|
||
| The `gl.get_webpage()` function supports different modes for retrieving web content. While `mode="text"` returns the plain text content, `mode="html"` allows you to retrieve the complete HTML `<body>` of the webpage. | ||
| The `gl.nondet.web.get()` function supports different modes for retrieving web content. While the default mode returns the plain text content, `gl.nondet.web.render()` with `mode="html"` allows you to retrieve the complete HTML `<body>` of the webpage. |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
According to the latest GenLayer documentation, does gl.nondet.web.render(..., mode="html")return the full HTML document or only the rendered, and is mode="text"still a supported parameter forgl.nondet.web.get()?
💡 Result:
-
gl.nondet.web.render(..., mode="html"): The latest GenLayer SDK docs describe this as returning the rendered webpage “HTML content” as astr, but they do not specify that it’s only the rendered<body>(vs. a full serialized HTML document). In the current SDK implementation, bothmode="html"andmode="text"return a string from the same decodedtextfield, without any documented/visible “body-only” extraction step. [1], [2] -
mode="text"ongl.nondet.web.get(): No—gl.nondet.web.get(url, headers=...)does not take amodeparameter in the latest SDK; it only returns aResponse(status/headers/body). The"text"/"html"modes apply togl.nondet.web.render(), notget(). [1], [2]
Sources:
[1] GenLayer SDK API docs (gl.nondet.web.get, gl.nondet.web.render) — https://sdk.genlayer.com/main/api/genlayer.html
[2] GenLayer SDK source for genlayer.gl.nondet.web — https://sdk.genlayer.com/main/_modules/genlayer/gl/nondet/web.html
🏁 Script executed:
cat -n pages/developers/intelligent-contracts/examples/fetch-web-content.mdx | sed -n '85,135p'Repository: genlayerlabs/genlayer-docs
Length of output: 2433
Fix conflicting API documentation about mode parameters and HTML output scope.
The file contains two contradictory statements:
- Line 92 mentions
mode="text"as a parameter for the preceding examples, but according to GenLayer SDK documentation,modeparameters apply only togl.nondet.web.render(), notgl.nondet.web.get(), making this note misleading. - Line 105 states
mode="html"returns the<body>, but Line 130 states it returns the "full HTML document"—these descriptions are incompatible.
Update Line 92 to accurately reflect which functions support mode parameters, and align Lines 105 and 130 to consistently describe what mode="html" actually returns.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pages/developers/intelligent-contracts/examples/fetch-web-content.mdx` at
line 105, Update the docs to state that mode parameters apply only to
gl.nondet.web.render(), not gl.nondet.web.get(); clarify that
gl.nondet.web.get() returns plain text by default and remove the misleading
reference to mode="text" for the get() examples, and make both occurrences
describing mode="html" (the ones referencing mode="html" and the "full HTML
document") consistent by saying mode="html" for gl.nondet.web.render() returns
the page's HTML <body> (not the entire document or other scope).
| response = gl.nondet.web.get(self.resolution_url) | ||
| web_data = response.body.decode("utf-8") |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In the current GenLayer Python API/docs, what does gl.nondet.web.get() return, and which API is recommended when an LLM prompt needs rendered or plain-text webpage content instead of raw HTML bytes?
💡 Result:
-
gl.nondet.web.get(url, *, headers={})returns agl.nondet.web.Responseobject with fields:status: intheaders: dict[str, bytes]body: bytes | None(i.e., the response payload is raw bytes, not a decoded string) [1]
-
If you need webpage content suitable for an LLM prompt (rendered page + plain text or HTML string), the recommended API is
gl.nondet.web.render()(browser-like rendering), using:mode='text'for plain-text content, ormode='html'for rendered HTML as astr[1]
(As opposed togl.nondet.web.get(), which gives you raw bytes inResponse.body.) [1]
Sources: [1]
Use gl.nondet.web.render() for LLM-suitable webpage content.
Lines 52-53 use gl.nondet.web.get(), which returns raw HTTP body bytes. For an LLM extraction prompt, use gl.nondet.web.render(mode='text') instead to feed plain-text rendered content rather than raw HTML noise:
Suggested change:
response = gl.nondet.web.render(self.resolution_url, mode='text')
web_data = response🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pages/developers/intelligent-contracts/examples/prediction.mdx` around lines
52 - 53, Replace the raw HTTP fetch with the LLM-friendly renderer: instead of
calling gl.nondet.web.get(self.resolution_url) and decoding bytes into web_data,
call gl.nondet.web.render(self.resolution_url, mode='text') and assign its
returned text directly to web_data so the prompt receives plain-text rendered
content; update any references to response to use web_data and remove the
.body.decode(...) flow.
| # { "Depends": "py-genlayer:1jb45aa8ynh2a9c9xn3b7qqh8sm5q93hwfp7jqmwsfhh8jpz09h6" } | ||
| ``` | ||
| It is similar to Solidity's `pragma solidity`, and `test` after a colon is a version. When GenLayer releases, it will be changed to some exact hash of a version, which will be frozen forever. |
There was a problem hiding this comment.
Documentation text is now inconsistent with the code example.
Line 12 states "test" after a colon is a version, but the code example on line 10 now shows the pinned hash. Consider updating the explanatory text to reflect the new format, e.g.:
"It is similar to Solidity's
pragma solidity, and the value after the colon is a version hash that identifies a specific frozen GenVM release."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pages/developers/intelligent-contracts/first-contract.mdx` around lines 10 -
12, Update the explanatory sentence so it matches the code example that pins a
specific release hash: replace the phrase saying "`test` after a colon is a
version" with wording that the value after the colon (e.g.
"py-genlayer:1jb45aa8...") is a version hash identifying a specific frozen
GenVM/GenLayer release—e.g., "It is similar to Solidity's `pragma solidity`, and
the value after the colon is a version hash that identifies a specific frozen
GenVM release."
| stripped = code.strip() | ||
| lines = stripped.split("\n") | ||
| first_line = lines[0].strip() | ||
|
|
||
| # Method: has @gl.public decorator or def with self | ||
| if first_line.startswith("@gl.public") or first_line.startswith("@gl.evm"): | ||
| return "method" | ||
| for line in lines: | ||
| line_s = line.strip() | ||
| if line_s.startswith("def ") and "(self" in line_s: | ||
| return "method" | ||
|
|
||
| # Function: starts with def | ||
| if first_line.startswith("def ") or ( | ||
| first_line.startswith("@") and any(l.strip().startswith("def ") for l in lines) | ||
| ): | ||
| return "function" |
There was a problem hiding this comment.
Ignore leading imports/comments before classifying snippets.
classify_snippet() keys off the first nonblank line only. A snippet like from genlayer import * followed by @gl.public... is classified as "statement", and wrap_snippet() then nests it inside _check(). In --lint-snippets mode that turns valid examples into false failures.
Suggested fix
def classify_snippet(code: str) -> str:
"""Classify a GenLayer snippet as 'method', 'function', or 'statement'."""
stripped = code.strip()
- lines = stripped.split("\n")
- first_line = lines[0].strip()
+ lines = stripped.split("\n")
+ meaningful_lines = [
+ line.strip()
+ for line in lines
+ if line.strip() and not line.strip().startswith(("from ", "import ", "#"))
+ ]
+ first_line = meaningful_lines[0] if meaningful_lines else ""🧰 Tools
🪛 Ruff (0.15.5)
[error] 173-173: Ambiguous variable name: l
(E741)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/lint-code-examples.py` around lines 159 - 175, classify_snippet()
currently examines the first nonblank line only, which misclassifies snippets
with leading imports or comments; update the logic that builds
stripped/lines/first_line to first skip any leading blank lines, import
statements (lines starting with "import" or "from "), and comment lines
(starting with "#" or triple-quote blocks) so that first_line and the subsequent
scans examine the first meaningful line; keep the existing checks for decorator
prefixes ("@gl.public", "@gl.evm", "@") and for "def " with "(self" unchanged,
and ensure the detection loop that looks for any "def " in lines also operates
on the trimmed list of meaningful lines so wrap_snippet() no longer wraps
class-method examples incorrectly.
| if "/_advanced/" in str(mdx_file) or "/_" in mdx_file.name: | ||
| continue |
There was a problem hiding this comment.
The underscore-prefixed path filter never matches.
Path.name never contains /, so "/_" in mdx_file.name is always false. If the intent is to skip _foo files/directories, these three scans currently still lint them.
Suggested fix
- if "/_advanced/" in str(mdx_file) or "/_" in mdx_file.name:
+ if any(part.startswith("_") for part in mdx_file.relative_to(DOCS_ROOT).parts):
continue
...
- if "/_advanced/" in str(mdx_file) or "/_" in mdx_file.name:
+ if any(part.startswith("_") for part in mdx_file.relative_to(DOCS_ROOT).parts):
continue
...
- if "/_advanced/" in str(mdx_file) or "/_" in mdx_file.name:
+ if any(part.startswith("_") for part in mdx_file.relative_to(DOCS_ROOT).parts):
continueAlso applies to: 337-338, 359-360
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/lint-code-examples.py` around lines 309 - 310, The check `"/_" in
mdx_file.name` never matches because Path.name never contains slashes; update
the condition to use mdx_file.name.startswith("_") (and keep the existing
"/_advanced/" in str(mdx_file) check) so it skips underscore-prefixed files:
change the conditional to `if "/_advanced/" in str(mdx_file) or
mdx_file.name.startswith("_"): continue`, and apply this same fix to the other
two occurrences of the same pattern in the file.
Summary
scripts/lint-code-examples.py): extracts Python code blocks from MDX files and validates them — checks runner hash pinning, deprecated API usage, AST lint viagenvm-lint, and syntax correctness for GenLayer snippetsgl.get_webpage,gl.eq_principle_strict_eq,gl.eq_principle_prompt_comparative,gl.eq_principle_prompt_non_comparative, andgl.exec_promptto their current replacements"test"runner hashes with specific version hashes.github/workflows/lint-code-examples.yml): runs on PRs and pushes to main whenpages/**/*.mdxor the lint script change; uses Python 3.12 +genvm-linterfrom PyPITest plan
gl.get_webpage,gl.eq_principle_strict_eq, etc. remain)"test"or"latest")python scripts/lint-code-examples.pylocally to validateSummary by CodeRabbit
Documentation
Chores