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

chore!: restructure plugin models #775

Merged
merged 11 commits into from
Jul 12, 2024

Conversation

lengau
Copy link
Contributor

@lengau lengau commented Jul 10, 2024

  • Have you signed the CLA?

This does several related things:

  1. Removes the vestigial PluginModel from craft_parts.plugins.base
  2. Combines PluginPropertiesModel and PluginProperties (which didn't need separation anymore)
  3. Makes the unmarshal method of PluginProperties usable by all plugins (and deletes the unnecessary overrides)

@lengau lengau force-pushed the work/CRAFT-2913/2-refactor-plugin-models branch from 27af4e5 to 8e88178 Compare July 10, 2024 15:56
This class was vestigial, being a child of PluginPropertiesModel, while
all plugins' properties classes are children of PluginProperties,
which is itself a child of PluginPropertiesModel.

This is a breaking change because external plugins for applications
(e.g. snapcraft) inherit from both PluginProperties and PluginModel.
@lengau lengau force-pushed the work/CRAFT-2913/2-refactor-plugin-models branch from 8e88178 to edd76ff Compare July 10, 2024 19:15
@lengau lengau changed the title chore!: remove PluginModel class chore!: restructure plugin models Jul 10, 2024
@lengau lengau force-pushed the work/CRAFT-2913/2-refactor-plugin-models branch 2 times, most recently from ff77dd9 to fcc9096 Compare July 10, 2024 19:41
This does several things:

- Merges PluginProperties and PluginPropertiesModel
- Makes PluginProperties.unmarshal() work for most plugins be default
- Makes PluginProperties.marshal() fully dump json-able objects
- Adds a `plugin` field to all plugins, providing their names.
@lengau lengau force-pushed the work/CRAFT-2913/2-refactor-plugin-models branch from fcc9096 to 2d2e216 Compare July 10, 2024 20:31
@lengau lengau force-pushed the work/CRAFT-2913/2-refactor-plugin-models branch from bded288 to 1899868 Compare July 10, 2024 20:56
@lengau lengau marked this pull request as ready for review July 10, 2024 20:56
@lengau lengau force-pushed the work/CRAFT-2913/2-refactor-plugin-models branch from 0ba2c27 to 3d9308d Compare July 10, 2024 22:41
validate_assignment=True,
)

plugin: Any = ""
Copy link
Collaborator

Choose a reason for hiding this comment

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

why Any?

Copy link
Contributor

Choose a reason for hiding this comment

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

Is it to play nice with the various Literal["x"] overrides in subclasses?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was left over from what @tigarmo suggests when I was playing around with different ways to make creating child nicer and cleaner with pyright. In the end I went with double-declaring frozen=True though, so I'll switch this back to str

@@ -65,4 +81,7 @@ def get_pull_properties(cls) -> list[str]:
def get_build_properties(cls) -> list[str]:
"""Obtain the list of properties affecting the build stage."""
properties = cls.schema(by_alias=True).get("properties")
return list(properties.keys()) if properties else []
if properties:
del properties["plugin"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

how safe is this?

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess it should be safe since if the code reaches this then the plugin entry is there, but it could be written as properties.pop("plugin", None)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should be safe (the plugin key not existing in the properties dict would mean we have a much bigger problem), but I rewrite it with a list comprehension anyway since that's faster and safer

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(And if you meant because of the del, yes that's safe too, as schema creates a new dict each time.)

@@ -65,4 +81,7 @@ def get_pull_properties(cls) -> list[str]:
def get_build_properties(cls) -> list[str]:
"""Obtain the list of properties affecting the build stage."""
properties = cls.schema(by_alias=True).get("properties")
return list(properties.keys()) if properties else []
if properties:
del properties["plugin"]
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess it should be safe since if the code reaches this then the plugin entry is there, but it could be written as properties.pop("plugin", None)


from overrides import override

from .base import Plugin
from .properties import PluginProperties


class NilPluginProperties(PluginProperties):
class NilPluginProperties(PluginProperties, frozen=True):
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't this one have _required_fields = ("plugin",)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Somewhat counter-intuitively, no. The name _required_fields came from it being the required argument in extract_plugin_properties, but in reality it's more like _extra_fields or _fields_that_dont_start_with_the_plugins_name.

Looking at this though, extract_plugin_properties is only actually used here, so I'm thinking about dumping it altogether and moving the logic here anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I've moved the logic from extract_plugin_properties into PluginProperties.unmarshal() and used the model's properties to determine the fields to use.

validate_assignment=True,
)

plugin: Any = ""
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it to play nice with the various Literal["x"] overrides in subclasses?

I missed some changes when I was playing with PluginProperties.
The plugin name will always be a string.
Moves the logic from extract_plugin_properties directly into
PluginProperties.unmarshal()
@lengau lengau force-pushed the work/CRAFT-2913/2-refactor-plugin-models branch from b168041 to 95e5fa6 Compare July 12, 2024 15:16
Copy link
Contributor

@mr-cal mr-cal left a comment

Choose a reason for hiding this comment

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

Nice refactor!

@lengau lengau merged commit 029f1ad into feature/2.0 Jul 12, 2024
8 checks passed
@lengau lengau deleted the work/CRAFT-2913/2-refactor-plugin-models branch July 12, 2024 16:09
@lengau lengau mentioned this pull request Jul 12, 2024
1 task
@lengau lengau linked an issue Jul 23, 2024 that may be closed by this pull request
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.

Migrate to Pydantic 2.x
4 participants