Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a plugin system that handles fine grained dependencies, and use it for applets #357

Merged
merged 4 commits into from
Aug 1, 2023

Conversation

whitequark
Copy link
Member

This PR introduces three related changes:

  • Instead of the awful applet registration in glasgow.applet.all, entry points are now used.
  • Instead of requiring every dependency of every applet to be installed just to run glasgow --help, applets now specify their own dependencies, and missing dependencies are gracefully handled by replacing applet help with instructions for installing them.
  • The system underlying the above is generalized so that it can be used to handle similar collections of tools in other parts of the codebase, of which we have at least two (applet tools and data loggers).

This is essentially the implementation of the plan outlined in #234 (comment).

It also paves way for out-of-tree applets. (At the moment they are explicitly forbidden to avoid creating a backwards compatibility hazard.)

@whitequark whitequark requested a review from attie July 24, 2023 01:38
@whitequark whitequark force-pushed the applet-entry-points branch 2 times, most recently from 98b50e6 to 64cdfde Compare July 24, 2023 04:44
@whitequark
Copy link
Member Author

@attie Note that the commits all have long descriptions, for you to read!

Copy link
Member

@attie attie left a comment

Choose a reason for hiding this comment

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

In the last commit, software.glasgow.cli:_applet() needs updating:
GlasgowAppletUnavailable -> PluginRequirementsUnmet


Otherwise, looks very good!

software/glasgow/cli.py Outdated Show resolved Hide resolved
software/glasgow/cli.py Outdated Show resolved Hide resolved
software/glasgow/cli.py Outdated Show resolved Hide resolved
software/glasgow/cli.py Outdated Show resolved Hide resolved
`glasgow.applet.all` was an abomination. Now that it is gone, we have
several new possibilities:
* Out-of-tree applets is the major one. (This commit explicitly
  prohibits them because the API is not stable or ready for public
  consumption.)
* Applets can now have package dependencies of their own, through
  their list of optional dependency groups that must be installed.
  This prevents any further dependency bloat of the software stack.
* Applet metadata can at some point be cached to reduce load times.
  Loading every applet (which we still do, just in a less directly
  intentional way) is costly, especially on low-power systems or
  systems with slow disk, and the cost only grows as more applets
  are developed. Unfortunately, this will continue to be the case
  so long as `argparse` continues to be used.

It might seem odd to move applet's "name" from its source code to
`pyproject.toml`. This actually makes sense because it is less its
name and more a handle by which it is invoked. It is likely that
the handles of out-of-tree applets will collide reasonably often
and in that case they will be automatically disambiguated.
As a concrete example, this (abridged) `pyproject.toml` with
a mandatory dependency on `aiohttp`:

    dependencies = ["aiohttp~=3.8"]

    [project.entry-points."glasgow.applet"]
    audio-yamaha-opx = "glasgow.applet.audio.yamaha_opx:AudioYamahaOPxApplet"

can now be transformed into the following one with an optional
dependency on `aiohttp`:

  [project.optional-dependencies]
  http = ["aiohttp~=3.8"]

  [project.entry-points."glasgow.applet"]
  audio-yamaha-opx = "glasgow.applet.audio.yamaha_opx:AudioYamahaOPxApplet [http]"

If `aiohttp` is not installed or its version is unsatisfying, the CLI
shows a placeholder instead of the applet whose `--help` text explains
how to install the missing packages.

See GlasgowEmbedded#234.
At this point we have at least three subsystems that would benefit
from a plugin mechanism based on entry points that was added to
handle applets:
* Applets. Duh.
* Applet tools. Currently very awkwardly attached to applets even
  though they aren't really related.
* Data loggers. `support.data_loggers` depends on `aiohttp` for
  a part of its functionality but because there was no way to
  express it, a data logger specific work around was added.

This commit lays the foundation for using the same plugin system
for all three.
Copy link
Member

@attie attie left a comment

Choose a reason for hiding this comment

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

Fantastic, thanks very much!

@attie
Copy link
Member

attie commented Jul 31, 2023

... one downside to this, is that we need to pip install .../path/to/glasgow/software again if we add a new applet.

Certainly manageable, but might trip people up.

@electroniceel
Copy link
Member

... one downside to this, is that we need to pip install .../path/to/glasgow/software again if we add a new applet.

you mean adding a new applet that needs some new dependency, or even when adding a new applet that doesn't need any new dependency?

I haven't used the new entry-point stuff of setuptools yet, so I might be missing something here. But shouldn't the entry-point feature take care of making all the applets available, even if you change the pyproject.toml?

@attie
Copy link
Member

attie commented Jul 31, 2023

you mean adding a new applet that needs some new dependency, or even when adding a new applet that doesn't need any new dependency?

Any new applet seems to require a reinstall, even if you used pip install -e

But shouldn't the entry-point feature take care of making all the applets available, even if you change the pyproject.toml?

With -e, I would have hoped so (but not really expect it), but it seems to not be the case... Without -e, I wouldn't expect it.

@whitequark
Copy link
Member Author

... one downside to this, is that we need to pip install .../path/to/glasgow/software again if we add a new applet.

This is already in README by the way.

With -e, I would have hoped so (but not really expect it), but it seems to not be the case... Without -e, I wouldn't expect it.

There's no really good way to do this infrastructurally even with -e. And I think this is just something people using the Glasgow software will need to learn.

@whitequark whitequark added this pull request to the merge queue Aug 1, 2023
Merged via the queue into GlasgowEmbedded:main with commit ef17f63 Aug 1, 2023
8 of 9 checks passed
@whitequark whitequark deleted the applet-entry-points branch August 1, 2023 08:20
@attie
Copy link
Member

attie commented Aug 1, 2023

Indeed it is... in light of this PR, how would you feel about me/you changing:

Changes to pyproject.toml, most importantly to the dependencies, are not picked up until pipx reinstall is manually run.

to:

Changes to pyproject.toml, most importantly to the dependencies or list of applet entrypoints, are not picked up until pipx reinstall is manually run.

@whitequark
Copy link
Member Author

Yes absolutely.

@attie
Copy link
Member

attie commented Aug 1, 2023

Great - see #379

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.

None yet

3 participants