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
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
${{ matrix.extra-pytest-warnings }}
enable-coverage: ${{ matrix.enable-coverage }}
jupyter-platform-dirs: "1"
package-managers: "uv"
codecov-flags: "unit"
strategy:
fail-fast: false
Expand Down
30 changes: 19 additions & 11 deletions doc/howtoguides/requirements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ What is stored
installed from the python package index, the git commit or the archive it came from. Any
:term:`package manager` can recreate the environment from this list.
* ``manager``: the :term:`package manager` that generated the requirements, with the content
of the files it needs to recreate the environment: ``requirements.txt`` for pip-venv.
of the files it needs to recreate the environment: ``requirements.txt`` for pip-venv,
``pyproject.toml`` and ``uv.lock`` for uv.

Use ``--exclude-requirements`` to store nothing.

Expand All @@ -37,7 +38,7 @@ one explicitly

.. code-block:: bash

ewoks convert demo demo.json --test --package-manager-name pip-venv
ewoks convert demo demo.json --test --package-manager-name uv

``ewoks install`` uses the :term:`package manager` that generated the requirements, unless it
is not installed on the machine. It installs the stored files of that :term:`package manager`.
Expand All @@ -47,15 +48,15 @@ confirmed separately unless ``--yes`` is provided

.. code-block:: bash

ewoks install demo.json --yes --package-manager-name pip-venv
ewoks install demo.json --yes --package-manager-name uv

``--package-manager-command`` provides the command that invokes the tool, for example when it
is not on the ``PATH`` or when a faster implementation should be used

.. code-block:: bash

ewoks install demo.json --yes --package-manager-name pip-venv \
--package-manager-command /path/to/python
ewoks install demo.json --yes --package-manager-name uv \
--package-manager-command /path/to/uv

Choose the environment
----------------------
Expand Down Expand Up @@ -85,21 +86,28 @@ The default name is the identifier of the :term:`workflow`, which is the ``id``
content.

Without ``--env-root`` the :term:`package manager` decides where the environment goes. venv
creates an environment wherever it is told to, so for pip-venv ewoks uses ``~/.ewoks/envs``.
and uv create an environment wherever they are told to, so for pip-venv and uv ewoks uses
``~/.ewoks/envs``.
Comment on lines 88 to +90

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This part is a bit confusing, perhaps we can reword it:

Suggested change
Without ``--env-root`` the :term:`package manager` decides where the environment goes. venv
creates an environment wherever it is told to, so for pip-venv ewoks uses ``~/.ewoks/envs``.
and uv create an environment wherever they are told to, so for pip-venv and uv ewoks uses
``~/.ewoks/envs``.
Use ``--env-root`` to choose where the environment will be created. Else, the :term:`package manager` will create it in a default folder (`~/.ewoks/envs` for pip-venv and uv)

@woutdenolf woutdenolf Aug 28, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes this was an LLM extraction of the full paragraph for all managers

Without ``--env-root`` the :term:`package manager` decides where the environment goes: conda
creates it in its own environment directory (``conda config --show envs_dirs``), so
``conda activate <name>`` finds it, and poetry in the directory it creates project
environments in (``poetry config virtualenvs.path``). venv, uv and pixi create an environment
wherever they are told to, so for those ewoks uses ``~/.ewoks/envs``.

I think in the end a bullet-list is better. If you are ok I would like this leave this as it is and refactor ones all managers are included.


An environment that already exists is installed in, which adds the requirements to what is
already there. Use ``--clean`` to remove it first. Only a directory that contains a python
environment is removed.

The environment of a :term:`workflow` is a directory: for pip-venv it is a virtual
environment. ``ewoks execute --env`` takes that directory, not the python interpreter inside
it.
environment and for uv a project with the environment in ``.venv``. ``ewoks execute --env``
takes that directory, not the python interpreter inside it.

Limitations
-----------

* ``--python-version`` is a request: pip-venv can only use the version of the python
interpreter that creates the environment. A warning is emitted when the version cannot be
provided.
* ``--python-version`` is a request: uv can provide any python version but pip-venv can only
use the version of the python interpreter that creates the environment. A warning is emitted
when the version cannot be provided.
Comment on lines +103 to +105

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* ``--python-version`` is a request: uv can provide any python version but pip-venv can only
use the version of the python interpreter that creates the environment. A warning is emitted
when the version cannot be provided.
* ``--python-version`` is a request: `uv` can create an environment with any python version but `pip-venv` can only use the version of the python interpreter. A warning is emitted when the version cannot be satisfied.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The full paragraph is

* ``--python-version`` is a request: uv can provide any python version, conda and pixi provide
  the patch versions built by their channel, and pip-venv and poetry can only use the version of
  the python interpreter that creates the environment. A warning is emitted when the version
  cannot be provided.

Again I would like to leave this one as it is.

* uv resolves the ``distributions`` into a lock file, which requires access to the package

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it would be good to specify which part is about ewoks convert and which part is about ewoks install.

Suggested change
* uv resolves the ``distributions`` into a lock file, which requires access to the package
* Running `ewoks convert` with `uv` resolves the ``distributions`` into a lock file, which requires access to the package index.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Full version

* uv, poetry and pixi resolve the ``distributions`` into a lock file, which requires access to
  the package index. When that fails, a warning is emitted and the requirements are stored
  without files: the environment is then recreated from the ``distributions`` list.

index. When that fails, a warning is emitted and the requirements are stored without files:

@loichuder loichuder Aug 27, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
index. When that fails, a warning is emitted and the requirements are stored without files:
index. If that fails, a warning is emitted and the distributions are stored as-is (without lock file). Running `ewoks install` will then create an environment only from the ``distributions`` list.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

see above

the environment is then recreated from the ``distributions`` list.
* A lock file is only read by a :term:`package manager` that understands its format version, so

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are we only talking about uv here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, any package manager that has lock files.

reproducing an environment can require a version of the tool that is at least as recent as
the one that generated the requirements.
* A package installed from a local directory cannot be recreated elsewhere. This is reported as
a warning when the requirements are generated.
2 changes: 1 addition & 1 deletion doc/reference/glossary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Glossary
An execution engine is the underlying software used to execute the :term:`workflow`. :term:`Ewoks` supports multiple execution engines: pypushflow, orange, dask and the ewoks internal excution engine.

Package manager
A package manager creates python environments and installs packages in them. :term:`Ewoks` uses package managers to store the environment in which a :term:`workflow` was created and to recreate it: pip with venv.
A package manager creates python environments and installs packages in them. :term:`Ewoks` uses package managers to store the environment in which a :term:`workflow` was created and to recreate it: pip with venv and uv.

blissdata
`Blissdata <https://bliss.gitlab-pages.esrf.fr/blissdata>`_ is an API for accessing data from BLISS in memory.
6 changes: 4 additions & 2 deletions doc/tutorials/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ There are two sides to this
* the *re-producer* receives the :term:`workflow`, recreates the environment and executes the
:term:`workflow` in it.

Both sides use a :term:`package manager`. The walk-through below does both sides
Both sides use a :term:`package manager`. The walk-throughs below do the same thing with each
of the supported ones

.. toctree::
:maxdepth: 1

install/pip_venv
install/uv

The producer and the re-producer do not need the same :term:`package manager`: the
requirements contain the installed python packages, which any :term:`package manager` can
Expand Down Expand Up @@ -68,7 +70,7 @@ and the command to remove it again
Remove : rm -rf ewoks_envs/demo

Without ``--yes`` you are asked to confirm after the packages have been listed. The
walk-through uses ``--env-root`` to create the environment in the working directory. Without
walk-throughs use ``--env-root`` to create the environment in the working directory. Without
it the environment is created where the :term:`package manager` creates named environments.

Execute the workflow
Expand Down
162 changes: 162 additions & 0 deletions doc/tutorials/install/uv.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
.. _install_uv:

uv
==

End-to-end walk-through of `workflow installation and execution <../install.rst>`_ with `uv <https://docs.astral.sh/uv/>`_.

Install uv
----------

.. tabs::

.. group-tab:: Linux

.. code-block:: bash

export UV_INSTALL_DIR=$HOME/.local/uv/bin # default location
curl -LsSf https://astral.sh/uv/install.sh | INSTALLER_NO_MODIFY_PATH=1 sh
export PATH=$UV_INSTALL_DIR:$PATH

.. group-tab:: macOS

.. code-block:: bash

export UV_INSTALL_DIR=$HOME/.local/uv/bin # default location
curl -LsSf https://astral.sh/uv/install.sh | INSTALLER_NO_MODIFY_PATH=1 sh
export PATH=$UV_INSTALL_DIR:$PATH

.. group-tab:: Windows

.. code-block:: powershell

$env:UV_INSTALL_DIR = "$env:USERPROFILE\.local\uv\bin" # default location
irm https://astral.sh/uv/install.ps1 | iex
$env:PATH = "$env:UV_INSTALL_DIR;$env:PATH"

Producer side
-------------

Create an environment, install :term:`ewoks` in it and store a :term:`workflow` with the
packages of that environment as its ``requirements``

.. tabs::

.. group-tab:: Linux

.. code-block:: bash

uv venv ewoks_producer
source ewoks_producer/bin/activate
uv pip install ewoks
ewoks convert demo demo.json --test
deactivate

.. group-tab:: macOS

.. code-block:: bash

uv venv ewoks_producer
source ewoks_producer/bin/activate
uv pip install ewoks
ewoks convert demo demo.json --test
deactivate

.. group-tab:: Windows

.. code-block:: powershell

uv venv ewoks_producer
ewoks_producer\Scripts\activate.ps1
uv pip install ewoks
ewoks convert demo demo.json --test
deactivate

Install any package that provides :term:`tasks <Task>` instead of
``ewoks`` for a real :term:`workflow`.

Re-producer side
----------------

Only ``ewoks`` itself is needed to recreate the environment of ``demo.json``

.. tabs::

.. group-tab:: Linux

.. code-block:: bash

uv venv ewoks_reproducer
source ewoks_reproducer/bin/activate
uv pip install ewoks
ewoks install demo.json --yes --env-root ewoks_envs

.. group-tab:: macOS

.. code-block:: bash

uv venv ewoks_reproducer
source ewoks_reproducer/bin/activate
uv pip install ewoks
ewoks install demo.json --yes --env-root ewoks_envs

.. group-tab:: Windows

.. code-block:: powershell

uv venv ewoks_reproducer
ewoks_reproducer\Scripts\activate.ps1
uv pip install ewoks
ewoks install demo.json --yes --env-root ewoks_envs

The environment of the :term:`workflow` is a uv project in ``ewoks_envs/demo`` with the
virtual environment in its ``.venv`` directory.

Execute the workflow
--------------------

.. tabs::

.. group-tab:: Linux

.. code-block:: bash

ewoks execute --env ewoks_envs/demo demo.json --outputs=all

.. group-tab:: macOS

.. code-block:: bash

ewoks execute --env ewoks_envs/demo demo.json --outputs=all

.. group-tab:: Windows

.. code-block:: powershell

ewoks execute --env ewoks_envs\demo demo.json --outputs=all

Clean up
--------

.. tabs::

.. group-tab:: Linux

.. code-block:: bash

deactivate
rm -rf ewoks_producer ewoks_reproducer ewoks_envs demo.json

.. group-tab:: macOS

.. code-block:: bash

deactivate
rm -rf ewoks_producer ewoks_reproducer ewoks_envs demo.json

.. group-tab:: Windows

.. code-block:: powershell

deactivate
Remove-Item -Recurse -Force ewoks_producer, ewoks_reproducer, ewoks_envs, demo.json
2 changes: 2 additions & 0 deletions src/ewoks/_requirements/utils/_supported.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
from typing import Type

from ..pip_venv import PipVenvManager
from ..uv import UvManager
from .base_manager import BaseManager


@lru_cache(1)
def get_supported_managers() -> Dict[str, Type[BaseManager]]:
managers = [
PipVenvManager,
UvManager,
]
return {manager_cls.NAME: manager_cls for manager_cls in managers}
11 changes: 6 additions & 5 deletions src/ewoks/_requirements/utils/base_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
class BaseManagerInfo(models.BaseModel):
name: str = Field(
description="Package manager that generated the requirements.",
examples=["pip-venv"],
examples=["pip-venv", "uv"],
)
version: str = Field(
description="Version of the package manager.", examples=["25.0.1"]
Expand All @@ -35,8 +35,9 @@ class BaseManagerInfo(models.BaseModel):
default_factory=dict,
description=(
"Content of the files the package manager needs to reproduce the "
"environment: 'requirements.txt' for pip-venv. Empty when the package "
"manager could not generate them."
"environment: 'requirements.txt' for pip-venv, 'pyproject.toml' and "
"'uv.lock' for uv. Empty when the package manager could not generate "
"them."
),
examples=[{"requirements.txt": "ewoks==7.0.0\nnetworkx==3.4.2\n"}],
)
Expand Down Expand Up @@ -184,8 +185,8 @@ def environment_location(

def environments_root(self) -> Path:
"""Root directory in which the package manager creates named environments.
Package managers that create an environment wherever they are told to (venv)
use a directory of ewoks.
Package managers that create an environment wherever they are told to (venv
and uv) use a directory of ewoks.
Comment on lines +188 to +189

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't understand what "Package managers that create an environment wherever they are told to" and "use a directory of ewoks." mean.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

directory of ewoks should be "~/.ewoks/envs".

Again the full version is

    def environments_root(self) -> Path:
        """Root directory in which the package manager creates named environments.
        Package managers that create an environment wherever they are told to (venv,
        uv and pixi) use a directory of ewoks.
        """
        return EWOKS_ENVIRONMENTS_ROOT

wherever they are told to -> For some package managers you cannot tell it to create a virtual environment on a specific location. This docstring needs improvement indeed.

"""
return EWOKS_ENVIRONMENTS_ROOT

Expand Down
1 change: 1 addition & 0 deletions src/ewoks/_requirements/utils/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

ENVIRONMENT_SUBDIRS: Tuple[str, ...] = (
"", # environment prefix, for example created by `python -m venv`
".venv", # uv project
)


Expand Down
2 changes: 1 addition & 1 deletion src/ewoks/_requirements/utils/metadata/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,5 @@ class Distribution(BaseModel):
installer: Optional[str] = Field(
default=None,
description="Tool that installed the distribution.",
examples=["pip"],
examples=["pip", "uv"],
)
Loading
Loading