Skip to content

fix: guarding optional imports for hooks#627

Merged
psschwei merged 2 commits into
generative-computing:mainfrom
psschwei:hooks-bug
Mar 12, 2026
Merged

fix: guarding optional imports for hooks#627
psschwei merged 2 commits into
generative-computing:mainfrom
psschwei:hooks-bug

Conversation

@psschwei

@psschwei psschwei commented Mar 11, 2026

Copy link
Copy Markdown
Member

Misc PR

Type of PR

  • Bug Fix
  • New Feature
  • Documentation
  • Other

Description

  • Link to Issue:

The cpex package (cpex.framework) provides the ContextForge plugin framework — base classes (Plugin, PluginPayload, PluginResult) and infrastructure (hook registry, payload policies) that Mellea's plugin system builds on. It's an optional dependency.

The bug: two files defined classes that inherit from cpex types at module level, outside the if _HAS_PLUGIN_FRAMEWORK: guard:

  • base.py: class MelleaBasePayload(PluginPayload) — base for all 17 hook payloads
  • registry.py: class _FunctionHookAdapter(Plugin) and class _MethodHookAdapter(Plugin) — adapters for registering hooks

When cpex isn't installed, those names don't exist, so import mellea raises NameError and the entire package is broken. The fix was to provide a frozen pydantic.BaseModel fallback for PluginPayload and wrap the two adapter classes inside the existing if _HAS_PLUGIN_FRAMEWORK: guard (they're only ever instantiated through already-guarded code paths).

Testing

  • Tests added to the respective file if code was changed
  • New code has 100% coverage if code as added
  • Ensure existing tests and github automation passes (a maintainer will kick off the github automation when the rest of the PR is populated)

Signed-off-by: Paul S. Schweigert <paul@paulschweigert.com>
@psschwei
psschwei requested a review from a team as a code owner March 11, 2026 22:19
@github-actions

Copy link
Copy Markdown
Contributor

The PR description has been updated. Please fill out the template for your PR to be reviewed.

@mergify

mergify Bot commented Mar 11, 2026

Copy link
Copy Markdown

Merge Protections

Your pull request matches the following merge protections and will not be merged until they are valid.

🟢 Enforce conventional commit

Wonderful, this rule succeeded.

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert|release)(?:\(.+\))?:

Comment thread mellea/plugins/base.py Outdated
except ImportError:
from pydantic import BaseModel as _BaseModel

class PluginPayload(_BaseModel): # type: ignore[no-redef]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I would add a log warning here in case someone is trying to define an instance of MelleaBasePayload without cpex installed (and without realizing it isn't installed), and they get unexpected behavior.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm in favor of implementing this the same as the other cpex dependent classes are when cpex isn't installed: https://github.com/generative-computing/mellea/blob/main/mellea/plugins/base.py#L153-L243

We should stub the class and have it raise an import error.

Comment thread mellea/plugins/registry.py Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Don't we need to update this to pip install 'mellea[hooks]'?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, we should do a find and replace. There's a couple of spots where this is contextforge instead of cpex. Good catch!

@imolloy

imolloy commented Mar 12, 2026

Copy link
Copy Markdown

This looks reasonable to me. I submitted a PR to add the optional log warning and fix the messages ImportError messages. I'll see if @araujof has any other suggestions. Only other (potential) issue I saw is if something tries to call _register_single in mellea.plugins.register without the hooks extras it will fail, but this is only even called from register which does make the check.

Comment thread mellea/plugins/base.py Outdated
except ImportError:
from pydantic import BaseModel as _BaseModel

class PluginPayload(_BaseModel): # type: ignore[no-redef]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm in favor of implementing this the same as the other cpex dependent classes are when cpex isn't installed: https://github.com/generative-computing/mellea/blob/main/mellea/plugins/base.py#L153-L243

We should stub the class and have it raise an import error.

Comment thread mellea/plugins/registry.py Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, we should do a find and replace. There's a couple of spots where this is contextforge instead of cpex. Good catch!


class _MethodHookAdapter(Plugin):
"""Adapts a single ``@hook``-decorated bound method from a ``Plugin`` class.
if _HAS_PLUGIN_FRAMEWORK:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lets do the stubs with import errors for these two classes as well.

@jakelorocco

Copy link
Copy Markdown
Contributor

@psschwei, I pushed the changes mentioned in my review. Please feel free to disagree and revert my commit. I ran tests with and without cpex and everything passed.

@psschwei
psschwei enabled auto-merge March 12, 2026 13:13
@psschwei

Copy link
Copy Markdown
Member Author

works for me
thanks!

@psschwei
psschwei added this pull request to the merge queue Mar 12, 2026
Merged via the queue into generative-computing:main with commit 9588284 Mar 12, 2026
4 checks passed
@psschwei
psschwei deleted the hooks-bug branch May 5, 2026 12:44
akihikokuroda pushed a commit to akihikokuroda/mellea that referenced this pull request May 27, 2026
* fix: guarding optional imports for hooks

Signed-off-by: Paul S. Schweigert <paul@paulschweigert.com>

* fix: issues with mellea when hooks not installed

---------

Signed-off-by: Paul S. Schweigert <paul@paulschweigert.com>
Co-authored-by: Jake LoRocco <jake.lorocco@ibm.com>
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.

3 participants