Skip to content

Conversation

atcuno
Copy link
Contributor

@atcuno atcuno commented Mar 17, 2025

…rnel modules. Convert plugins to new method.

Ok @ikelos I am really happy to see how this turned out. Previously each of the enumeration plugins printed different columns and used different names. This gets us to where everything is consistent with a proper name.

Furthermore, given the maturity we now have with the versioning of modules, there is no need for a particular plugin to be the "main" one that the others inherit from (like thrdscan in Windows for threads plugins), and instead we can have a fully versioned chain of classes that plugins can use for our self.implementation style enumeration when the outputs will be the same.

You will see the in the comment I left, but this also sets us up to display Load Arguments, but jamming that into this PR would have spiraled it, so that will fill in here once merged.

@atcuno atcuno requested a review from ikelos March 17, 2025 17:30
@atcuno
Copy link
Contributor Author

atcuno commented Mar 17, 2025

This will need to be merged after #1717 is merged and then this branch rebased, but otherwise will be good.

Copy link
Member

@ikelos ikelos left a comment

Choose a reason for hiding this comment

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

This isn't passing some of the tests at the moment.

Also I really uncertain as to the effects of inheriting from a plugin that doesn't live under an os directory. I'd really strongly advise that we only proxy methods from the class, that will allow the methods to stay shared, with minimal duplicated code and ensures we don't have to deal with any shared complexity (like a plugin inheritting from itself before it knows whether its own version passes the requirements. I can't see a compelling reason to use inheritance for the sake of run = ModuleDisplayPlugin.run (although we'll need to think about binding of methods to make sure that works properly)...

return reqs


class ModuleDisplayPlugin(plugins.PluginInterface):
Copy link
Member

Choose a reason for hiding this comment

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

This seems like the wrong place for it, and inheriting from the plugin interface means it may get listed as main plugin (our code to list plugins looks for anything that inherits from plugin). Are we sure that's what we want? I'd much prefer any plugins we have to live as a plugin in the right directory.

name="linux_utilities_modules",
component=linux_utilities_modules.Modules,
version=(3, 0, 0),
name="linux_utilities_modules_module_display_plugin",
Copy link
Member

Choose a reason for hiding this comment

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

It would surely be better to define classmethod generator and run methods and then just proxy them at this point? We're really not getting anything from inheritance other than complexity?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can __init__ of each plugin just set .run and and ._generator to the shared function? and Where would that shared functons best live now? I was trying to avoid one plugin becoming the container (say lsmod) that the other plugins then need to import and depend on.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that should be ok, but you can just define it straight in the class I think? So

class Blah:
  run = linux_utilities_modules.ModuleDisplayPlugin.run

?

@atcuno
Copy link
Contributor Author

atcuno commented Mar 17, 2025

Yes, the 1 test would break until I rebase with the netfilter PR you just merged. That is a really good point on inheriting to look like a plugin + re-using .run. I will adjust to that.

@atcuno atcuno force-pushed the linux_unifiy_module_gathering_output branch from f2e10da to 1096217 Compare March 17, 2025 23:42
@atcuno atcuno force-pushed the linux_unifiy_module_gathering_output branch from 1096217 to f906bde Compare March 17, 2025 23:57
Copy link
Member

@ikelos ikelos left a comment

Choose a reason for hiding this comment

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

Looking much better, but there's nothing to be gained by the multiple inheritance. Literally just reach into the classes and assign the methods to the new classes. It should all work (because self is included explicitly, so it'll refer to the instantiated class, not the ModuleDisplayPlugin class, which likely will never get instantiated ever. It's just acting as a code wrapper to keep it all nice and warm and bundled up for the plugins that actually want to use it... 5:)

_required_framework_version = (2, 0, 0)

def __init__(self, *args, **kwargs):
super().__init__(self.compare_kset_and_lsmod, *args, **kwargs)
Copy link
Member

Choose a reason for hiding this comment

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

I mean this is nice, but not worth it, just set a self variable in here, and pull it back in the proxied method.

name="linux_utilities_modules",
component=linux_utilities_modules.Modules,
version=(3, 0, 0),
name="linux_utilities_modules_module_display_plugin",
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that should be ok, but you can just define it straight in the class I think? So

class Blah:
  run = linux_utilities_modules.ModuleDisplayPlugin.run

?

self.implementation = implementation

@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
Copy link
Member

Choose a reason for hiding this comment

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

Add the results of this to the individual class get_requirements.

The constructor of the plugin must call super() with the `implementation` set
"""

_version = (1, 0, 0)
Copy link
Member

@ikelos ikelos Mar 18, 2025

Choose a reason for hiding this comment

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

Don't need these local variables, since they shouldn't be being inherited anyway (you can if you really want, but the plugins should be defining their own needs

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I realized we version this directly, so it's important for this to have its own version! 5:S

),
]

def _generator(self):
Copy link
Member

Choose a reason for hiding this comment

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

This might give a ruff warning, because it's a private member, but you can actually make it public and just assign it to a private member in the new class?

  _generator = modules.ModuleDisplayPlugin.generator

for example?

@atcuno
Copy link
Contributor Author

atcuno commented Mar 18, 2025

Nice idea! I think its sorted now. Also, if you see in the diff functions moving, its so they could be referenced from the code under them.

Copy link
Member

@ikelos ikelos left a comment

Choose a reason for hiding this comment

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

Looks good, let's get it landed 5:)

@ikelos ikelos merged commit bd5fb7d into develop Mar 18, 2025
24 checks passed
@ikelos ikelos deleted the linux_unifiy_module_gathering_output branch March 18, 2025 08:18
@ikelos
Copy link
Member

ikelos commented May 8, 2025

So I said:

I'd really strongly advise that we only proxy methods from the class, that will allow the methods to stay shared, with minimal duplicated code and ensures we don't have to deal with any shared complexity.

Looking much better, but there's nothing to be gained by the multiple inheritance.

To which you eventually said:

I think its sorted now.

And I then merged it in, seemingly because I was getting tired of reworking it and because it was an overly large pull request. I'm sorry, I shouldn't have accepted it, I don't think I thought this through full before landing it. You sounded as though you'd fixed the inheritance that I objected to twice, but there's still inheritance being used and is now causing some headaches in a circular dependency because this extension module is actually partial plugins rather than discrete code blocks each doing their own thing (see #1773).

Please can we can this refactored ASAP. No inheritance please. None. Only code blocks and version checks...

@ikelos
Copy link
Member

ikelos commented May 8, 2025

Ok, having calmed a bit (but only a bit) and scoped out exactly what's going on, it seems we jury rigged inheritance. It's not as bad as I thought, but trying to pull in complex functions (like run and generator) removes the ability for plugin to easily be able to override settings (or for us to separate concerns when, for example, part of the dumping functionality needs to be refactored). I'm working up a PR that should improve this, but I suspect that the ModuleDisplayPlugin will not exist in its current form for long.

@ikelos ikelos assigned atcuno and unassigned atcuno May 8, 2025
@ikelos
Copy link
Member

ikelos commented May 8, 2025

Ok, I've worked up #1801 to get this slightly more in order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants