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

Fix PluginField not working in production #10469

Merged
merged 7 commits into from Jul 28, 2020

Conversation

Eric-Arellano
Copy link
Contributor

Two issues:

  1. We weren't actually passing UnionMembership to the Target constructor, so PluginFields were being ignored.
  2. Using a static PluginField class meant that registering a field on one target would register it on all targets.

[ci skip-rust-tests]

Copy link
Sponsor Member

@stuhood stuhood left a comment

Choose a reason for hiding this comment

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

Thanks.

Copy link
Member

@jsirois jsirois left a comment

Choose a reason for hiding this comment

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

I won't block - but I don't like perpetuating what seems like a needless decpetion with the camel casing and @classproperty sleights.

# type so that registering a PluginField for one target doesn't end up registering for all
# targets. This means that we cannot use a statically declared class, so we instead
# dynamically create a class. We use a class property and name the method in PascalCase so
# that this implementation doesn't leak to call sites.
Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer just a @memoized_classmethod and not pretending this is a nested type. Saying SomeTarget.plugin_field() is ~no more typing and less magic. Maybe better SomeTarget.register_plugin_field(Field) -> UnionRule - absolutely no magic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

SomeTarget.register_plugin_field(Field) -> UnionRule I like that.

Copy link
Sponsor Member

@stuhood stuhood Jul 27, 2020

Choose a reason for hiding this comment

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

I'm fine either way. It would be best if that ended up being a pattern that we could use elsewhere as well though... ie, Subsystem.register() -> TaskRule or something.

@Eric-Arellano Eric-Arellano removed this from the 1.30.x milestone Jul 27, 2020
Copy link
Contributor Author

@Eric-Arellano Eric-Arellano left a comment

Choose a reason for hiding this comment

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

PTAL. I'm not sure this is much of an improvement - certainly makes unit tests more awkward.

There's also an argument that it's helpful to be transparent that this is using UnionRule. We use UnionRule for other plugin tasks, like adding a new linter, so it's consistent to have the user explicitly do that here.

Copy link
Member

@jsirois jsirois left a comment

Choose a reason for hiding this comment

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

Excellent.

# that this implementation doesn't leak to call sites.
def _anonymous_plugin_field_cls(cls) -> Type:
# NB: We make this a method, rather than using a static class, to ensure that every
# subclass has a distinct `.PluginField` class. This ensures that registering a plugin
Copy link
Member

Choose a reason for hiding this comment

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

The comment has drifted. There is no longer method vs static class nor .PluginField. Perhaps just focus on the 1 union per Target subtype need:

@final
@memoized_classproperty
def _plugin_field_union(cls) -> Type:
  # N.B.: We want each Target subtype to collect its own union of plugin fields to ensure plugin
  # fields don't leak across target types.
  return union(type(f"{cls.__name__}PluginField", (), {}))

@@ -262,7 +262,7 @@ class CustomField(BoolField):
alias = "custom_field"
default = False

union_membership = UnionMembership({FortranTarget.PluginField: [CustomField]})
union_membership = UnionMembership({FortranTarget._anonymous_plugin_field_cls: [CustomField]})
Copy link
Member

@jsirois jsirois Jul 27, 2020

Choose a reason for hiding this comment

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

This would be less awkward if UnionMembership had UnionMembership.from_rules(Iterable[UnionRule]) -> UnionMembership which it arguably should have already anyhow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call. I'll do that as a precursor PR.

@jsirois
Copy link
Member

jsirois commented Jul 27, 2020

There's also an argument that it's helpful to be transparent that this is using UnionRule. We use UnionRule for other plugin tasks, like adding a new linter, so it's consistent to have the user explicitly do that here.

True currently. I've had my long standing unpublished PR to eliminate UnionRule though. Plugin tasks need to today but need not in principle register anything if they are already subclassing an @union'd type. Assuming a future where we kill UnionRule, the return type of this registration method - and all registration methods we may add to form a pattern, would be the more opaque Rule type. At that point the user only interacts with Rule since @rule registers a subtype of this as would registration methods.

# Rust tests will be skipped. Delete if not intended.
[ci skip-rust-tests]
@coveralls
Copy link

coveralls commented Jul 28, 2020

Coverage Status

Coverage remained the same at 0.0% when pulling 3b6c2fe on Eric-Arellano:fix-union-fields into f6ffe46 on pantsbuild:master.

# Rust tests and lints will be skipped. Delete if not intended.
[ci skip-rust]

# Building wheels and fs_util will be skipped. Delete if not intended.
[ci skip-build-wheels]
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

4 participants