Skip to content

[cli] Add uv.lock, .python-version, and uv.toml to inited Python apps #29

Description

@manish-wekan

Context

After nitrostack-py init, the generated app folder has no uv project files:

  • no uv.lock
  • no .python-version
  • no uv.toml

The only dependency file today is requirements.txt (nitrostack). TypeScript init is npm-shaped (package.json; install refreshes package-lock.json — see nitrostack CLI docs). Python init has no equivalent lock or interpreter pin.

nitrostack-py install always uses python -m venv + python -m pip (nitrostack/cli/install.py ensure_project_venv / _run_pip). It never calls uv.

PEP 621 pyproject.toml for templates is a separate issue and should land first (or in the same PR if you do both). uv needs a pyproject to lock.

Do not make uv a required runtime dependency of the nitrostack package. If uv is on PATH, use it; otherwise keep the existing venv+pip path.

Work from develop. Do not dirty unrelated SDK protocol files.

Goal

A freshly inited Python app is a uv-ready project:

File Role
.python-version Interpreter pin for uv/pyenv (must satisfy SDK requires-python = ">=3.10"). Recommend 3.12 or 3.11, not a floating 3.
uv.toml uv tool config for the app (not the SDK). Keep it small: e.g. python-preference / default index. If you prefer [tool.uv] in pyproject instead of a standalone file, still ship uv.toml or document why pyproject [tool.uv] is the chosen equivalent — the report asked for uv.toml explicitly, so default to a real uv.toml.
uv.lock Locked deps. Do not check a stale lock into the SDK templates if nitrostack on PyPI will drift. Generate at init: uv lock in the new directory when uv is available. If uv is missing, skip lock, print one line telling the user to run uv lock, and still write .python-version + uv.toml.

nitrostack-py install / init “Install dependencies (Y/n)”: if uv is on PATH and pyproject.toml exists, prefer uv sync (creates .venv, respects .python-version / lock). If not, existing pip+venv behavior.

Probe

ls nitrostack/templates/starter
cat nitrostack/templates/starter/requirements.txt
rg -n "ensure_project_venv|_run_pip|uv " nitrostack/cli/install.py nitrostack/cli/main.py
which uv || true
uv --help | head

Read:

  • nitrostack/cli/install.py — entire file
  • nitrostack/cli/main.pyinit_project install step (~1346 comment: requirements/pyproject then widgets npm)
  • tests/test_cli_install.py
  • uv.toml schema: https://docs.astral.sh/uv/reference/settings/ (do not copy a huge config)

Confirm widgets still install via npm when src/widgets / widgets exists; uv must not swallow that step.

Implementation

  1. Land pyproject in templates if the pyproject issue is not merged yet (dependency). Without pyproject, uv lock has nothing to lock.
  2. Add .python-version to all three templates (same pin).
  3. Add a short uv.toml to all three templates (shared content is fine).
  4. After copytree in init_project, if shutil.which("uv"): run uv lock in the project dir (network). Tests must not hit the network: mock uv / skip lock when UV is absent. Optional: os.environ.get("NITROSTACK_SKIP_UV_LOCK") for CI.
  5. install_dependencies: if uv available and pyproject present → uv sync (and uv sync --no-dev when production=True if that maps cleanly). Else pip path unchanged.
  6. .gitignore in templates: keep ignoring .venv; do not ignore uv.lock. If templates have no .gitignore, add one (venv, __pycache__, .env but not .env.example).
  7. Do not add uv to the SDK’s pyproject.toml dependencies.

Test / verify

pytest tests/test_cli.py tests/test_cli_install.py tests/test_cli_skills.py -q

Add:

  1. Fresh template tree (unit, no init TTY): .python-version and uv.toml exist after copy; contents non-empty; python pin is >=3.10 compatible.
  2. install_dependencies with uv patched as missing → still calls pip (existing tests).
  3. install_dependencies with uv patched as present + pyproject present → invokes uv sync, does not also pip-install the same deps (one installer).
  4. Init lock: when uv is mocked, assert uv lock cwd is the new project; when mocked missing, init still succeeds.
  5. All three templates get the uv files.
  6. No test clones PyPI unless marked and optional.

Manual (if uv installed): nitrostack-py init /tmp/ns-uv --template python-starter, then ls shows pyproject.toml, .python-version, uv.toml, uv.lock; uv sync / nitrostack-py install creates .venv.

Review

  • Pip fallback still works on machines without uv (Windows included; venv_python already has Scripts vs bin).
  • Lock is generated or skipped, never a committed lie in the SDK repo unless CI regenerates it.
  • Widget npm path unchanged.

Success

  • Init project contains .python-version and uv.toml
  • uv.lock created at init when uv exists; init does not fail when uv is missing
  • nitrostack-py install uses uv sync when uv+pyproject exist
  • Pip+venv path remains for uv-less environments
  • Tests mocked; three templates covered

Related

Depends on #28 (pyproject.toml in init templates). Independent of mcp-2026 #22#27.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions