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
2 changes: 1 addition & 1 deletion .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The Medoc TCP client is a **subpackage** at `src/heat_task/medoc/` (console scri
- `models.py` — protocol enums/dataclasses (`Command`, `ReturnCode`, `MedocResponse`, …)
- `cli/` — the `medoc` command line (`parser.py`, `commands.py`, `formatting.py`, `__init__.py` wires `main`)

Task-agnostic experiment plumbing — screen/VSYNC setup, run manifest, CSV writers, setup-wizard primitives, instruction pager, keyboard abstraction — comes from the separate **`psyexp-core`** package. `pyproject.toml` pins it to a git tag (`[tool.uv.sources]`) so clones reproduce exactly. For local co-development, set `UV_NO_SYNC=1` (export it in your shell, or use `uv run --no-sync`) and overlay `uv pip install -e ../psyexp-core` — that stops `uv run`'s auto-sync from reverting the editable install (and from removing the manually-installed Apple Silicon psychtoolbox). See README "Co-developing `psyexp-core` locally".
Task-agnostic experiment plumbing — screen/VSYNC setup, run manifest, CSV writers, setup-wizard primitives, instruction pager, keyboard abstraction — comes from the separate **`psyexp-core`** package, declared as a published PyPI dependency (`psyexp-core>=X.Y`) and pinned exactly in `uv.lock` so clones reproduce. For local co-development overlay an editable sibling checkout (`uv pip install -e ../psyexp-core`) and run with `uv run --no-sync` (or `UV_NO_SYNC=1`, or the `just core-*` recipes). The two overlays behave differently under sync: `uv sync --inexact` keeps the manually-installed Apple Silicon psychtoolbox (it is *not* in the lock), but it does **not** keep the editable `psyexp-core` (it *is* in the lock, so a sync reverts it) — only skipping the sync preserves that. See README "Co-developing `psyexp-core` locally".

## Terminology

Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## v1.0.0-rc.2

### Changed

- Bumped `psyexp-core` to `v0.8.0`

## v1.0.0-rc.1

First release candidate for 1.0.0.
Expand Down
33 changes: 21 additions & 12 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ Silicon, install it manually from the lab build, e.g.
uv pip install ../Psychtoolbox-3/dist/psychtoolbox-3.0.22.2-cp311-cp311-macosx_10_9_universal2.whl
```

Because `uv sync`/`uv run` are exact by default and will remove the manual install, run them as
`uv sync --inexact` and `uv run --no-sync …` (or set `UV_NO_SYNC=1`) to keep it. On Windows the lab
build is needed similarly; otherwise PsychoPy's own transitive `psychtoolbox` (`<3.0.20`,
non-arm64) applies.
Because `uv sync` is exact by default it removes the manual install — run it as `uv sync --inexact`
to keep psychtoolbox. (`uv run`'s implicit sync is *inexact*, so it leaves the manual install alone;
pass `--no-sync` only when you are also overlaying an editable `psyexp-core`, which *is* in the lock
and would otherwise be reverted.) On Windows the lab build is needed similarly; otherwise PsychoPy's
own transitive `psychtoolbox` (`<3.0.20`, non-arm64) applies.

## Quick Start

Expand Down Expand Up @@ -71,11 +72,11 @@ are ignored by pip/conda, so the conda install resolves dependencies fresh from
from the lockfile. `psychtoolbox` is still not pulled in automatically (see below) — install the lab
build manually after creating the environment.

> **Heads up — `uv run` auto-syncs the venv from `uv.lock` on every launch.** That sync will
> (a) revert a local editable `psyexp-core` back to the pinned git tag and (b) remove the manually
> installed Apple Silicon psychtoolbox wheel. Disable it by setting `UV_NO_SYNC=1` — either
> `export UV_NO_SYNC=1` in your shell session or prefix individual commands with
> `uv run --no-sync …`.
> **Heads up — `uv run` auto-syncs the venv from `uv.lock` on every launch** (inexactly: it won't
> remove your manually-installed psychtoolbox, but it *will* revert a local editable `psyexp-core`
> back to the locked PyPI version, since the core is in the lock). While co-developing the core,
> skip that sync with `UV_NO_SYNC=1` — `export` it in your shell, prefix commands with
> `uv run --no-sync …`, or use the `just core-*` recipes.

## Co-developing `psyexp-core` locally

Expand All @@ -93,8 +94,16 @@ uv pip install -e ../psyexp-core # one time
uv run heat-task # uses your local core, edits are live
```

After changing *other* dependencies you'll need a manual `uv sync` (auto-sync is off) — that
re-clobbers psyexp-core, so re-run the editable install above.
The `just core-dev` / `just core-run` / `just core-test` recipes wrap this — they overlay the
editable checkout and run with `--no-sync`. Note `uv sync --inexact` does **not** preserve the
editable core: `--inexact` only spares packages absent from the lock (that's what keeps
psychtoolbox), and the core *is* in the lock, so only skipping the sync keeps it. After changing
*other* dependencies you'll need a manual `uv sync --inexact` — that reverts psyexp-core, so re-run
the editable install (or `just core-dev`) afterward.

For a setup that survives sync, declare the path source in `pyproject.toml`
(`[tool.uv.sources] psyexp-core = { path = "../psyexp-core", editable = true }`) and keep that edit
local with `git update-index --skip-worktree pyproject.toml uv.lock`.

## Updating `psyexp-core`

Expand All @@ -107,7 +116,7 @@ uv lock --upgrade-package psyexp-core # rewrite uv.lock to the newest version
uv sync --inexact # apply it; --inexact keeps the manual psychtoolbox install
```

Then commit the updated `uv.lock`. Raise the `>=` floor in `pyproject.toml` first if you want to
(`just core-upgrade` runs both commands.) Then commit the updated `uv.lock`. Raise the `>=` floor in `pyproject.toml` first if you want to
require a new minimum. CI (`.github/workflows/tests.yml`) reads the pinned version straight from
`uv.lock` via `uv export --frozen`, so it tracks the upgrade automatically once the lock is
committed.
Expand Down
51 changes: 51 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# heat-task dev tasks. Run `just` to list recipes.
# Requires `just` (https://github.com/casey/just): `brew install just`.

# Show available recipes
default:
@just --list

# Install/refresh the venv (--inexact keeps the manual psychtoolbox install)
sync:
uv sync --inexact

# Run the task (locked PyPI core)
run *args:
uv run heat-task {{args}}

# Talk to the thermode via the vendored medoc CLI
medoc *args:
uv run medoc {{args}}

# Run the test suite
test *args:
uv run pytest {{args}}

# --- Co-developing psyexp-core from ../psyexp-core ---------------------------
# Two overlays, two rules:
# * psychtoolbox (NOT in the lock) -> kept by `uv sync --inexact`
# * editable psyexp-core (IN the lock) -> only kept by skipping the sync;
# `--inexact` does NOT save it.
# Co-development runs with --no-sync, which preserves both at once.

# Overlay an editable sibling checkout of ../psyexp-core
core-dev:
uv pip install -e ../psyexp-core
@echo "Editable psyexp-core overlaid. Use 'just core-run' / 'just core-test' so it isn't reverted."

# Run the task against the editable overlay (no sync; keeps core + psychtoolbox)
core-run *args:
uv run --no-sync heat-task {{args}}

# Run the tests against the editable overlay
core-test *args:
uv run --no-sync pytest {{args}}

# Drop the editable core, restore the locked PyPI version (keeps psychtoolbox)
core-release:
uv sync --inexact

# Upgrade to the newest published psyexp-core and update the lock
core-upgrade:
uv lock --upgrade-package psyexp-core
uv sync --inexact
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ dependencies = [
# Note: psychtoolbox is NOT declared here. PyPI has no arm64 wheel for it, so on
# Apple Silicon install it manually from the lab build, e.g.
# uv pip install ../Psychtoolbox-3/dist/psychtoolbox-3.0.22.2-cp311-cp311-macosx_10_9_universal2.whl
# Because `uv sync`/`uv run` are exact by default and will remove it, run them as
# `uv sync --inexact` and `uv run --no-sync ...` (or set UV_NO_SYNC=1) to keep the
# manual install. On Windows the lab build is needed similarly; PsychoPy's own
# transitive psychtoolbox (<3.0.20, non-arm64) otherwise applies.
# Because `uv sync` is exact by default it removes the manual install — run it as
# `uv sync --inexact` to keep psychtoolbox. (`uv run`'s implicit sync is inexact,
# so it leaves the manual install alone.) On Windows the lab build is needed
# similarly; PsychoPy's own transitive psychtoolbox (<3.0.20, non-arm64) otherwise applies.

[project.scripts]
heat-task = "heat_task.__main__:run"
Expand Down