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
19 changes: 13 additions & 6 deletions .agents/skills/python-codestyle/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ default baseline on first-party code (a repo may instead run mypy with its stric
and keep pyright editor-only via Pylance, per the next paragraph): `[tool.pyright]`
`strict = ["src"]`, or the integration package for a Home Assistant repo, with tests run in
standard mode. pyright is the anchor because Pylance embeds it, so where CI runs pyright, the
editor and the CLI/CI (`uv run pyright` in the uv form, `uvx pyright@latest` in the pip form,
pointed at the environment in a declared directory) run the same engine and never disagree.
editor and the CLI/CI run the same engine. A pyright the requirements pin can lag the one Pylance
bundles, though. The CLI/CI form is `uv run pyright` in the uv form. In the pip form a declared
directory runs the environment's own pyright, or `uvx pyright@latest` pointed at the environment
where it installs none.
The standalone `ms-pyright.pyright` extension stays in
`unwantedRecommendations` because Pylance covers it. Relax strictness on third-party code only
when a dependency has no usable types and no alternative (e.g. `pandas`): a targeted, commented
Expand Down Expand Up @@ -124,6 +126,7 @@ carries a `[project]` table it then installs the directory itself as editable, w
uv venv --clear # creates .venv, replacing an existing one
uv pip install -r requirements.txt -r requirements-dev.txt # one -r per requirements*.txt
uv pip install -e . # only where pyproject.toml has a [project] table
# in a declared directory whose .venv installs ruff, .venv/bin/python -m ruff replaces uvx ruff@latest
uvx ruff@latest format # auto-format
uvx ruff@latest check --fix # auto-fix lint
uvx ruff@latest check # verify lint clean
Expand All @@ -134,10 +137,14 @@ uvx ruff@latest format --check # verify format clean
Its type checker runs against that environment. mypy runs as `.venv/bin/python -m mypy` where the
environment installs it, and otherwise as `uvx mypy@latest --python-executable .venv/bin/python`,
adding `--python-version` with the environment's version unless the mypy config pins one. pyright
runs as `uvx pyright@latest --pythonpath .venv/bin/python`. Where the config sits in the project
directory, CI runs the checker there with no path, as in the uv form. A declared subdirectory with
no config of its own uses the repository root's instead. CI then runs the checker from the root
with the directory as its path and the interpreter as `<dir>/.venv/bin/python`. Run it the same
runs as `.venv/bin/python -m pyright --pythonpath .venv/bin/python` where the environment installs
it, and otherwise as `uvx pyright@latest --pythonpath .venv/bin/python`. ruff follows the same
precedence, as `.venv/bin/python -m ruff` where the environment installs it, in place of the
`uvx ruff@latest` above. In a directory the validator's `python-directories` input declares, a tool
the requirements pin is then the version CI runs. Where the config
sits in the project directory, CI runs the checker there with no path, as in the uv form. A
declared subdirectory with no config of its own uses the repository root's instead. CI then runs
the checker from the root with the directory as its path and the interpreter as `<dir>/.venv/bin/python`. Run it the same
way, as in `<dir>/.venv/bin/python -m mypy <dir>`. On Windows each interpreter path ends in
`.venv\Scripts\python.exe` instead. Those ruff commands and that type checker are the pip form's
clean-compile, run with pytest before committing.
Expand Down
12 changes: 6 additions & 6 deletions .agents/skills/python-codestyle/references/profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ configuration alone marks the lint-only one:
`[project.optional-dependencies]` extra. The pip form is a `pyproject.toml` beside a
`requirements*.txt`, installed with pip, whether or not it carries a `[project]` table. A
committed `uv.lock` makes a directory the uv form even where a `requirements*.txt` sits beside it.
In the pip form CI builds the environment as `SKILL.md` "Local development loop" shows, runs
pytest from it as `.venv/bin/python -m pytest`, and runs ruff through `uvx`. In a directory
declared in the hub validator's `python-directories` input it runs the type checker through
`uvx` pointed at that environment, or runs mypy from the environment where it is installed
there, while the undeclared default root runs a bare `uvx <checker>@latest` with nothing
installed.
In the pip form CI builds the environment as `SKILL.md` "Local development loop" shows, and runs
pytest from it as `.venv/bin/python -m pytest`. A directory declared in the hub validator's
`python-directories` input runs ruff and the type checker from that environment where it
installs them. It otherwise runs them through `uvx`, with the checker pointed at that
environment. The undeclared default root runs `uvx ruff@latest` and a bare
`uvx <checker>@latest`, with nothing installed.
- **Scripts** (the `lint-only` profile): stdlib-only utility scripts embedded in a non-Python repo
(e.g. a Python tooling subtree of a `csharp` app). Run the tools with `uvx` (no project install,
no lockfile): the `pyproject.toml` carries only tool config (`[tool.ruff]`, `[tool.mypy]`, and
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7bbaad0be74556f3
78b687fa4e03cda7
19 changes: 13 additions & 6 deletions .claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ default baseline on first-party code (a repo may instead run mypy with its stric
and keep pyright editor-only via Pylance, per the next paragraph): `[tool.pyright]`
`strict = ["src"]`, or the integration package for a Home Assistant repo, with tests run in
standard mode. pyright is the anchor because Pylance embeds it, so where CI runs pyright, the
editor and the CLI/CI (`uv run pyright` in the uv form, `uvx pyright@latest` in the pip form,
pointed at the environment in a declared directory) run the same engine and never disagree.
editor and the CLI/CI run the same engine. A pyright the requirements pin can lag the one Pylance
bundles, though. The CLI/CI form is `uv run pyright` in the uv form. In the pip form a declared
directory runs the environment's own pyright, or `uvx pyright@latest` pointed at the environment
where it installs none.
The standalone `ms-pyright.pyright` extension stays in
`unwantedRecommendations` because Pylance covers it. Relax strictness on third-party code only
when a dependency has no usable types and no alternative (e.g. `pandas`): a targeted, commented
Expand Down Expand Up @@ -124,6 +126,7 @@ carries a `[project]` table it then installs the directory itself as editable, w
uv venv --clear # creates .venv, replacing an existing one
uv pip install -r requirements.txt -r requirements-dev.txt # one -r per requirements*.txt
uv pip install -e . # only where pyproject.toml has a [project] table
# in a declared directory whose .venv installs ruff, .venv/bin/python -m ruff replaces uvx ruff@latest
uvx ruff@latest format # auto-format
uvx ruff@latest check --fix # auto-fix lint
uvx ruff@latest check # verify lint clean
Expand All @@ -134,10 +137,14 @@ uvx ruff@latest format --check # verify format clean
Its type checker runs against that environment. mypy runs as `.venv/bin/python -m mypy` where the
environment installs it, and otherwise as `uvx mypy@latest --python-executable .venv/bin/python`,
adding `--python-version` with the environment's version unless the mypy config pins one. pyright
runs as `uvx pyright@latest --pythonpath .venv/bin/python`. Where the config sits in the project
directory, CI runs the checker there with no path, as in the uv form. A declared subdirectory with
no config of its own uses the repository root's instead. CI then runs the checker from the root
with the directory as its path and the interpreter as `<dir>/.venv/bin/python`. Run it the same
runs as `.venv/bin/python -m pyright --pythonpath .venv/bin/python` where the environment installs
it, and otherwise as `uvx pyright@latest --pythonpath .venv/bin/python`. ruff follows the same
precedence, as `.venv/bin/python -m ruff` where the environment installs it, in place of the
`uvx ruff@latest` above. In a directory the validator's `python-directories` input declares, a tool
the requirements pin is then the version CI runs. Where the config
sits in the project directory, CI runs the checker there with no path, as in the uv form. A
declared subdirectory with no config of its own uses the repository root's instead. CI then runs
the checker from the root with the directory as its path and the interpreter as `<dir>/.venv/bin/python`. Run it the same
way, as in `<dir>/.venv/bin/python -m mypy <dir>`. On Windows each interpreter path ends in
`.venv\Scripts\python.exe` instead. Those ruff commands and that type checker are the pip form's
clean-compile, run with pytest before committing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ configuration alone marks the lint-only one:
`[project.optional-dependencies]` extra. The pip form is a `pyproject.toml` beside a
`requirements*.txt`, installed with pip, whether or not it carries a `[project]` table. A
committed `uv.lock` makes a directory the uv form even where a `requirements*.txt` sits beside it.
In the pip form CI builds the environment as `SKILL.md` "Local development loop" shows, runs
pytest from it as `.venv/bin/python -m pytest`, and runs ruff through `uvx`. In a directory
declared in the hub validator's `python-directories` input it runs the type checker through
`uvx` pointed at that environment, or runs mypy from the environment where it is installed
there, while the undeclared default root runs a bare `uvx <checker>@latest` with nothing
installed.
In the pip form CI builds the environment as `SKILL.md` "Local development loop" shows, and runs
pytest from it as `.venv/bin/python -m pytest`. A directory declared in the hub validator's
`python-directories` input runs ruff and the type checker from that environment where it
installs them. It otherwise runs them through `uvx`, with the checker pointed at that
environment. The undeclared default root runs `uvx ruff@latest` and a bare
`uvx <checker>@latest`, with nothing installed.
- **Scripts** (the `lint-only` profile): stdlib-only utility scripts embedded in a non-Python repo
(e.g. a Python tooling subtree of a `csharp` app). Run the tools with `uvx` (no project install,
no lockfile): the `pyproject.toml` carries only tool config (`[tool.ruff]`, `[tool.mypy]`, and
Expand Down
19 changes: 13 additions & 6 deletions .github/skills/python-codestyle/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ default baseline on first-party code (a repo may instead run mypy with its stric
and keep pyright editor-only via Pylance, per the next paragraph): `[tool.pyright]`
`strict = ["src"]`, or the integration package for a Home Assistant repo, with tests run in
standard mode. pyright is the anchor because Pylance embeds it, so where CI runs pyright, the
editor and the CLI/CI (`uv run pyright` in the uv form, `uvx pyright@latest` in the pip form,
pointed at the environment in a declared directory) run the same engine and never disagree.
editor and the CLI/CI run the same engine. A pyright the requirements pin can lag the one Pylance
bundles, though. The CLI/CI form is `uv run pyright` in the uv form. In the pip form a declared
directory runs the environment's own pyright, or `uvx pyright@latest` pointed at the environment
where it installs none.
The standalone `ms-pyright.pyright` extension stays in
`unwantedRecommendations` because Pylance covers it. Relax strictness on third-party code only
when a dependency has no usable types and no alternative (e.g. `pandas`): a targeted, commented
Expand Down Expand Up @@ -124,6 +126,7 @@ carries a `[project]` table it then installs the directory itself as editable, w
uv venv --clear # creates .venv, replacing an existing one
uv pip install -r requirements.txt -r requirements-dev.txt # one -r per requirements*.txt
uv pip install -e . # only where pyproject.toml has a [project] table
# in a declared directory whose .venv installs ruff, .venv/bin/python -m ruff replaces uvx ruff@latest
uvx ruff@latest format # auto-format
uvx ruff@latest check --fix # auto-fix lint
uvx ruff@latest check # verify lint clean
Expand All @@ -134,10 +137,14 @@ uvx ruff@latest format --check # verify format clean
Its type checker runs against that environment. mypy runs as `.venv/bin/python -m mypy` where the
environment installs it, and otherwise as `uvx mypy@latest --python-executable .venv/bin/python`,
adding `--python-version` with the environment's version unless the mypy config pins one. pyright
runs as `uvx pyright@latest --pythonpath .venv/bin/python`. Where the config sits in the project
directory, CI runs the checker there with no path, as in the uv form. A declared subdirectory with
no config of its own uses the repository root's instead. CI then runs the checker from the root
with the directory as its path and the interpreter as `<dir>/.venv/bin/python`. Run it the same
runs as `.venv/bin/python -m pyright --pythonpath .venv/bin/python` where the environment installs
it, and otherwise as `uvx pyright@latest --pythonpath .venv/bin/python`. ruff follows the same
precedence, as `.venv/bin/python -m ruff` where the environment installs it, in place of the
`uvx ruff@latest` above. In a directory the validator's `python-directories` input declares, a tool
the requirements pin is then the version CI runs. Where the config
sits in the project directory, CI runs the checker there with no path, as in the uv form. A
declared subdirectory with no config of its own uses the repository root's instead. CI then runs
the checker from the root with the directory as its path and the interpreter as `<dir>/.venv/bin/python`. Run it the same
way, as in `<dir>/.venv/bin/python -m mypy <dir>`. On Windows each interpreter path ends in
`.venv\Scripts\python.exe` instead. Those ruff commands and that type checker are the pip form's
clean-compile, run with pytest before committing.
Expand Down
12 changes: 6 additions & 6 deletions .github/skills/python-codestyle/references/profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ configuration alone marks the lint-only one:
`[project.optional-dependencies]` extra. The pip form is a `pyproject.toml` beside a
`requirements*.txt`, installed with pip, whether or not it carries a `[project]` table. A
committed `uv.lock` makes a directory the uv form even where a `requirements*.txt` sits beside it.
In the pip form CI builds the environment as `SKILL.md` "Local development loop" shows, runs
pytest from it as `.venv/bin/python -m pytest`, and runs ruff through `uvx`. In a directory
declared in the hub validator's `python-directories` input it runs the type checker through
`uvx` pointed at that environment, or runs mypy from the environment where it is installed
there, while the undeclared default root runs a bare `uvx <checker>@latest` with nothing
installed.
In the pip form CI builds the environment as `SKILL.md` "Local development loop" shows, and runs
pytest from it as `.venv/bin/python -m pytest`. A directory declared in the hub validator's
`python-directories` input runs ruff and the type checker from that environment where it
installs them. It otherwise runs them through `uvx`, with the checker pointed at that
environment. The undeclared default root runs `uvx ruff@latest` and a bare
`uvx <checker>@latest`, with nothing installed.
- **Scripts** (the `lint-only` profile): stdlib-only utility scripts embedded in a non-Python repo
(e.g. a Python tooling subtree of a `csharp` app). Run the tools with `uvx` (no project install,
no lockfile): the `pyproject.toml` carries only tool config (`[tool.ruff]`, `[tool.mypy]`, and
Expand Down
15 changes: 14 additions & 1 deletion .github/workflows/validate-task.yml
Original file line number Diff line number Diff line change
Expand Up @@ -337,17 +337,22 @@ jobs:
fi
done <<< "$PYTHON_PROJECTS"

# A declared pip directory runs the ruff its venv installs, so a version its requirements pin is the one CI runs.
# It falls back to uvx only where the venv holds none.
- name: Lint Python step
if: steps.python.outputs.any == 'true'
env:
PYTHON_PROJECTS: ${{ steps.python.outputs.projects }}
DECLARED: ${{ steps.python.outputs.declared }}
run: |
set -Eeuo pipefail
while IFS=$'\t' read -r kind dir; do
[ -n "$dir" ] || continue
echo "ruff check in $dir"
if [ "$kind" = uv ]; then
(cd "$dir" && uv run ruff check .) < /dev/null
elif [ "$kind" = pip ] && [ "$DECLARED" = "true" ] && "$dir/.venv/bin/python" -c 'import importlib.util, sys; sys.exit(importlib.util.find_spec("ruff") is None)' < /dev/null; then
(cd "$dir" && .venv/bin/python -m ruff check .) < /dev/null
else
(cd "$dir" && uvx ruff@latest check .) < /dev/null
fi
Expand All @@ -357,13 +362,16 @@ jobs:
if: steps.python.outputs.any == 'true'
env:
PYTHON_PROJECTS: ${{ steps.python.outputs.projects }}
DECLARED: ${{ steps.python.outputs.declared }}
run: |
set -Eeuo pipefail
while IFS=$'\t' read -r kind dir; do
[ -n "$dir" ] || continue
echo "ruff format --check in $dir"
if [ "$kind" = uv ]; then
(cd "$dir" && uv run ruff format --check .) < /dev/null
elif [ "$kind" = pip ] && [ "$DECLARED" = "true" ] && "$dir/.venv/bin/python" -c 'import importlib.util, sys; sys.exit(importlib.util.find_spec("ruff") is None)' < /dev/null; then
(cd "$dir" && .venv/bin/python -m ruff format --check .) < /dev/null
else
(cd "$dir" && uvx ruff@latest format --check .) < /dev/null
fi
Expand Down Expand Up @@ -446,7 +454,12 @@ jobs:
(cd "$config_dir" && uvx mypy@latest --python-executable "$venv_python" "${version_args[@]}" "${targets[@]}") < /dev/null
fi
elif [ "$kind" = pip ] && [ "$DECLARED" = "true" ]; then
(cd "$config_dir" && uvx pyright@latest --pythonpath "$venv_python" "${targets[@]}") < /dev/null
if "$venv_python" -c 'import importlib.util, sys; sys.exit(importlib.util.find_spec("pyright") is None)'; then
# The venv's own pyright is the version its requirements pin, as with ruff, and the flag still names the interpreter whose packages it reads.
(cd "$config_dir" && "$venv_python" -m pyright --pythonpath "$venv_python" "${targets[@]}") < /dev/null
else
(cd "$config_dir" && uvx pyright@latest --pythonpath "$venv_python" "${targets[@]}") < /dev/null
fi
else
(cd "$config_dir" && uvx "$checker@latest" "${targets[@]}") < /dev/null
fi
Expand Down
4 changes: 3 additions & 1 deletion catalog/snippets/configs/vscode-tasks-python.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
// The aggregator then runs one `uv pip install` taking every `requirements*.txt` as a `-r` argument.
// It ends with `uv pip install -e .` where the directory's pyproject.toml has a [project] table.
// The directory also adapts or drops "uv Upgrade", which runs `uv sync` too.
// The directory runs ruff as `uvx ruff@latest`, pytest as `.venv/bin/python -m pytest` (`.venv\Scripts\python.exe` on Windows), and the type checker against `.venv`, per the python-codestyle Skill "Local development loop".
// A pip-form directory declared in the validator's `python-directories` input runs ruff as `.venv/bin/python -m ruff` (`.venv\Scripts\python.exe` on Windows) where its environment installs ruff, matching CI.
// Any other pip-form directory runs ruff as `uvx ruff@latest`.
// Every pip-form directory runs pytest as `.venv/bin/python -m pytest` (`.venv\Scripts\python.exe` on Windows), and the type checker against `.venv`, per the python-codestyle Skill "Local development loop".
// A lint-only Scripts-profile subtree, with no [project], no [build-system], no `uv.lock`, and no `requirements*.txt`, runs every tool via `uvx <tool>` rather than `uv run <tool>`.
// The type-checker swap composes with it: `uvx mypy@latest` for a mypy repo, `uvx pyright@latest` otherwise.
// It omits "uv Sync" and "uv Upgrade", and "Python Test" runs the unittest command the repository's OPERATIONS.md gives rather than pytest, per the python-codestyle Skill "Two profiles".
Expand Down
Loading
Loading