Skip to content

uv workspace reorganization - #50

Open
micahwoodard wants to merge 12 commits into
mainfrom
feat-uv-workspace-reorg
Open

uv workspace reorganization#50
micahwoodard wants to merge 12 commits into
mainfrom
feat-uv-workspace-reorg

Conversation

@micahwoodard

@micahwoodard micahwoodard commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Updates

  • reorganizes repo to have individual repos be separate packages managed by uv workspaces
  • renames project to mixology
  • updates and fixes imports

Fixed Issues

Merge Checklist

  • update the changelog
  • bump the version

@micahwoodard
micahwoodard requested review from a team, Poofjunior and hannalee2 April 30, 2026 21:32
@micahwoodard

Copy link
Copy Markdown
Contributor Author

Also we should probably rename the repo? This will need to be done in a coordinated way to not break brainslosher-instrument deployment

@hannalee2 hannalee2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love the code separation in mixology for common fluidic control code.

After digging a little bit into uv workspaces, it seems that using brainslosher, brainwasher, and seqflow as workspace members is not suitable. We can simply use mixology as a common source code library via path dependencies.

The uv documentation says: "Workspaces are not suited for cases in which members have conflicting requirements, or desire a separate virtual environment for each member. In this case, path dependencies are often preferable."

A workspace creates one giant virtual environment (.venv) at the root of the repo. This would cause brainslosher to install brainwasher's Raspberry Pi hardware libraries, which could lead to crashes. Also, if brainwasher and brainslosher have different dependencies (such as one needing pydantic v2.11 and the other needing v2.0), resolving these conflicting requirements will not work. This becomes especially problematic as we expand to include more instruments.

We keep the instant code-sharing of mixology. If you update mixology's code, brainslosher and brainwasher will instantly see the changes.
Each instrument should get its own isolated .venv an uv.lock files.

I approve since we can change only few lines in pyproject.toml to use path.

Comment thread pyproject.toml Outdated
"pydantic-settings>=2.12.0",
"email-validator>=2.3.0",
"pandas>=2.0.3",
"pyharp>=0.1.0",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a piece of hardware is only ever going to be used by one instrument, I think its driver does not belong in mixology.

For example, if brainwasher uses a very specific Raspberry Pi that brainslosher and seqflow will never use, it would be better to remove those dependencies from mixology and put them directly into brainwasher's pyproject.toml

Comment thread instruments/brainwasher/pyproject.toml Outdated
pythonpath = ["src", "tests"]

[tool.uv.sources]
mixology = { workspace = true }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than using workspace, we can define as a path. mixlology = { path = "...."}

Comment thread instruments/brainslosher/pyproject.toml Outdated
pythonpath = ["src", "tests"]

[tool.uv.sources]
mixology = { workspace = true }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than using workspace, we can define as a path. mixlology = { path = "...."}

Comment thread pyproject.toml Outdated
brainwasher = "brainwasher.scripts.main:main"
brainslosher = "brainwasher.scripts.brainslosher_main:main"
[tool.uv.workspace]
members = ["instruments/*"]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After digging some uv workspace usage, maybe we should not use the workspace for sperate instruments.

@micahwoodard

Copy link
Copy Markdown
Contributor Author

@hannalee2 okay sounds good! I will try and make changes later this week

Comment thread pyproject.toml Outdated
Comment on lines 19 to 25
"vicivalve>=0.0.13",
"rpi-hardware-pwm>=0.3.1",
"SM16inpind>=1.0.1",
"SM8mosind>=1.0.1",
"SM16univin>=1.0.3",
"smbus2>=0.5.0",
]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think optional dependacies woud be better :)

Example)
[project.optional-dependencies]
custom_something = ["vicivalve", "sambus2"... ]

I will add barseq specific drivers under optional dependacies. :)

* Monorepo workspaces -> path dependencies for Mixology

* Decouple hardware dependencies from mixology core
* Monorepo workspaces -> path dependencies for Mixology

* Decouple hardware dependencies from mixology core

* SeqFlow initial setup using DeviceSpinner and One-liner

* Add sim peristaltic pump device into mixology

* Add selector_port_map into yaml and config args

* Change to editable

* Add slide_container as vessel

SeqFlow does not have rxn vessel, but slide as a similar function, which gets chemincal from source

* Pass SlideContainer to SeqFlow

* Add SlideContainer Class (base:Vessel)

* Change script entrypoint for seqflow-client

* Remove client codes from src/

* Add more APIs into server

* Add temp get_duration_s() into seqflow job

* Fix the yaml for device spinner

* Change the temp volumn for starting solution

* Override _load_job() from SeqJob

* Add protocol for SeqFlow

* Add ResumeState for seqflow

* Change sim_pump function name

* Add run_step in seqflow instrument

* Update client example

* Solution chagned to dict

* Bug fix in instrument.py, missing self in class function

* Change the protocl yaml format

* Modify Run_step to accomodate the sim devices

* Add unit in var name for flow rate and duration

* Pass the step var member to run_step() for safety.

Before it was passing kargs which prone to create bugs

* Seperate resume and and new solution case in step

* Modify SlideContainer

 max cap not require for slides since it goes to waste bottle directly

* Fix Ruff

* Fix mypy

* Change duration_m from duration_s for model

Seq-o-matic also has convetion of duration_s

* Fix TypeO

* Use FileBackedDict for device-spinner

* Update docstring

* Change slide_container to rxn_vessel for convention

* Add job_class parameter in instrument._load_job()
- Add job_class parameter to base Instrument._load_job() to allow specific job types.
- This change is backward-compatible as existing instruments (Brainwasher, BrainSlosher) override this method.

* Add SeqFlowJobStatus and more function to set theses state

* Add DeviceType (Literal)

* Remove device from job file

* Fix Ruff

* Fix mypy

* Convert into static method for save_resume_state()

* Fix typeO: remove self from static method

* Seperate Seqflow Config model into seperate file

* Add pump.stop() and pump.dispense() by duration_s

* Fix Ruff check

* Add default_flow_rate_mlpm in job, and flow_rate_mlpm in step for override

* Remove default florw rate and simplify run_step()

* Update peristaltic_pump to accept 0.0 flow rate, and do nothing

* Fix TypeO
* Monorepo workspaces -> path dependencies for Mixology

* Decouple hardware dependencies from mixology core

* SeqFlow initial setup using DeviceSpinner and One-liner

* Add sim peristaltic pump device into mixology

* Add selector_port_map into yaml and config args

* Change to editable

* Add slide_container as vessel

SeqFlow does not have rxn vessel, but slide as a similar function, which gets chemincal from source

* Pass SlideContainer to SeqFlow

* Add SlideContainer Class (base:Vessel)

* Change script entrypoint for seqflow-client

* Remove client codes from src/

* Add more APIs into server

* Add temp get_duration_s() into seqflow job

* Fix the yaml for device spinner

* Change the temp volumn for starting solution

* Override _load_job() from SeqJob

* Add protocol for SeqFlow

* Add ResumeState for seqflow

* Change sim_pump function name

* Add run_step in seqflow instrument

* Update client example

* Solution chagned to dict

* Bug fix in instrument.py, missing self in class function

* Change the protocl yaml format

* Modify Run_step to accomodate the sim devices

* Add unit in var name for flow rate and duration

* Pass the step var member to run_step() for safety.

Before it was passing kargs which prone to create bugs

* Seperate resume and and new solution case in step

* Modify SlideContainer

 max cap not require for slides since it goes to waste bottle directly

* Fix Ruff

* Fix mypy

* Change duration_m from duration_s for model

Seq-o-matic also has convetion of duration_s

* Fix TypeO

* Use FileBackedDict for device-spinner

* Update docstring

* Change slide_container to rxn_vessel for convention

* Add job_class parameter in instrument._load_job()
- Add job_class parameter to base Instrument._load_job() to allow specific job types.
- This change is backward-compatible as existing instruments (Brainwasher, BrainSlosher) override this method.

* Add SeqFlowJobStatus and more function to set theses state

* Add DeviceType (Literal)

* Remove device from job file

* Fix Ruff

* Fix mypy

* Convert into static method for save_resume_state()

* Fix typeO: remove self from static method

* Seperate Seqflow Config model into seperate file

* Add pump.stop() and pump.dispense() by duration_s

* Fix Ruff check

* Add default_flow_rate_mlpm in job, and flow_rate_mlpm in step for override

* Remove default florw rate and simplify run_step()

* Update peristaltic_pump to accept 0.0 flow rate, and do nothing

* Fix TypeO

* Add logging config

* Remove unused functions

* Move named_call (ZMQ server) to config

* Fix mypy

* Fix Ruff

* Update version

* Update uv lock

* Starting devices in the seqflow class instead

* remove seqflow_device is None checking

* remove seqflow_device is None checking

* Remove the case where seqflow is None
* Monorepo workspaces -> path dependencies for Mixology

* Add Ficus on dependency

* Add Ficus and config files in local disk

* Update version

* Ruff check fixed

* Add default value. Fix mypy error

* Accept config-dir as an args

* Update the git tag

* Shutdown seqflow on keyboard interrupt

* Update uv.lock (version changed)

* Add logging model

* Specify the one-liner version in pyproject.toml

* Use RouterServerConfig model from one-liner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants