Skip to content

Support for Editable Dependencies #588

Description

@RobertRosca

As far as I could tell, there's currently no way to specify that a dependency should be installed in editable mode, which would be a useful feature for monorepo-style projects.

A practical example of this is from Jupyverse, which has a monorepo structure with multiple packages in a ./plugins/ directory. Here are the relevant sections from pyproject.toml for Jupyverse:

[build-system]
requires = [ "hatchling",]
build-backend = "hatchling.build"

[project]
dependencies = [
    "fastapi>=0.82.0",
    "fps>=0.0.19",
    "fps-uvicorn>=0.0.19",
    "fps-auth-base>=0.0.42",
    "fps-contents>=0.0.42",
    "fps-kernels>=0.0.42",
    "fps-terminals>=0.0.42",
    "fps-nbconvert>=0.0.42",
    "fps-yjs>=0.0.42"
]

[project.optional-dependencies]
jupyterlab = [ "fps-jupyterlab >=0.0.42",]
retrolab = [ "fps-retrolab >=0.0.42",]
auth = [ "fps-auth >=0.0.42",]
auth-fief = [ "fps-auth-fief >=0.0.42",]
noauth = ["fps-noauth >=0.0.42"]
test = [ "mypy", "types-setuptools", "pytest", "pytest-asyncio", "pytest-env", "requests", "websockets", "ipykernel",]
docs = [ "mkdocs", "mkdocs-material",]

[tool.hatch.envs.dev]
pre-install-commands = [
  "pip install -e ./plugins/auth_base",
  "pip install -e ./plugins/contents",
  "pip install -e ./plugins/frontend",
  "pip install -e ./plugins/kernels",
  "pip install -e ./plugins/lab",
  "pip install -e ./plugins/nbconvert",
  "pip install -e ./plugins/terminals",
  "pip install -e ./plugins/yjs",
]
dependencies = ["fastapi>=0.82.0"]
features = ["test"]

[tool.hatch.envs.dev.overrides]
matrix.auth.post-install-commands = [
  { value = "pip install -e ./plugins/noauth", if = ["noauth"] },
  { value = "pip install -e ./plugins/auth", if = ["auth"] },
  { value = "pip install -e ./plugins/auth_fief", if = ["auth_fief"] },
]
matrix.frontend.post-install-commands = [
  { value = "pip install -e ./plugins/jupyterlab", if = ["jupyterlab"]},
  { value = "pip install -e ./plugins/retrolab", if = ["retrolab"]},
]

[[tool.hatch.envs.dev.matrix]]
frontend = ["jupyterlab", "retrolab"]
auth = ["noauth", "auth", "auth_fief"]

For development you'd want to install the plugins in editable mode from the ./plugins/ directory, which is why [tool.hatch.envs.dev] defines a pre-install-command which runs pip install -e ./plugins/PLUGIN_NAME on core plugins, and then tool.hatch.envs.dev.overrides defines matrix post-install commands for specific additional packages.

As mentioned in this discussion post #516, there are a few ways I can think of to allow for this:

  1. Extend dev-mode-dirs to work with environment installation as well as builds.
  2. Add another dependency category, something like editable-dependencies, which would always perform a pip install -e ... on the provided dependency.
  3. Additional syntax for the dependency specification, maybe -e proj @ URI, which when found installs the dependency in editable mode.

Out of these three, I think 2 and 3 make the most sense as they are more explicit over what's happening.

editable-dependencies Category

The additional category approach would add sections for editable-dependencies and extra-editable-dependencies to the configuration file. This would look like:

[tool.hatch.envs.dev]
editable-dependencies = [
  "fps-auth-base @ {root:uri}/plugins/auth_base",
  "fps-contents @ {root:uri}/plugins/contents",
  ...
]

[tool.hatch.envs.dev.overrides]
matrix.auth.extra-editable-dependencies = [
  { value = "fps-noauth @ {root:uri}/plugins/noauth", if = ["noauth"] },
  ...
]

Support -e Flag for Local Dependencies

The additional syntax approach would use the existing sections, but support the -e flag:

[tool.hatch.envs.dev]
dependencies = [
  "-e fps-auth-base @ {root:uri}/plugins/auth_base",
  "-e fps-contents @ {root:uri}/plugins/contents",
  ...
]

[tool.hatch.envs.dev.overrides]
matrix.auth.extra-dependencies = [
  { value = "-e fps-noauth @ {root:uri}/plugins/noauth", if = ["noauth"] },
  ...
]

In a way this is odd as it isn't really specified in any PEPs, however PDM uses this syntax for editable dependencies already, so it isn't that odd. In PDM the above dependencies would look like:

[tool.pdm.dev-dependencies]
dev = [
    "-e file:///${PROJECT_ROOT}/plugins/auth_base#egg=fps-auth-base",
    "-e file:///${PROJECT_ROOT}/plugins/contents#egg=fps-contents",
]

Next Steps?

I'm happy to implement either of these two options, but not sure which one to go with.

The -e flag support is pretty nice and avoids requiring a new section, however having that flag in a requirement it isn't officially defined in any PEP, but on the other hand it is already used in PDM.

Additional categories are much clearer but make the files a bit more verbose.

Personally I prefer the -e flag since it is already used in PDM which is quite popular.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions