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

Plugin fields should propagate to subclassed target types. #15876

Merged
merged 1 commit into from Jun 24, 2022

Conversation

kaos
Copy link
Member

@kaos kaos commented Jun 18, 2022

Consider subclassed PythonSourceTarget. Now, all plugin fields that are registered on
PythonSourceTarget should also be registered on the custom subclassed target, otherwise
subclassing a target will lose any plugin fields in doing so, making it very difficult to customize
targets without inadvertently losing functionality added by plugin fields.

This is addressed by ensuring that the Target PluginField class mirrors the class hierarchy of the
owning Target class, and when registering unions all subclassed union bases are registered with the
same union members as the subclassed union base (in addition to any directly registered for the
subclassed union base type).

[ci skip-rust]

Consider subclassed `PythonSourceTarget`. Now, all plugin fields that are registered on
`PythonSourceTarget` should also be registered on the custom subclassed target, otherwise
subclassing a target will lose any plugin fields in doing so, making it very difficult to customize
targets without inadvertently losing functionality added by plugin fields.

This is addressed by ensuring that the Target `PluginField` class mirrors the class hierarchy of the
owning Target class, and when registering unions all subclassed union bases are registered with the
same union members as the subclassed union base (in addition to any directly registered for the
subclassed union base type).

[ci skip-rust]
@kaos
Copy link
Member Author

kaos commented Jun 18, 2022

From the design doc comment thread: https://docs.google.com/document/d/1DdVZ4DqX7uwiYuCL_ntb17yPxyez1fbiu8K0whZ78Lg/edit#

image

In other words, this is prep-work to support adding the Visibility feature entirely as a plugin.

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.

@Eric-Arellano definitely better understands this code: will let them take a look.

Copy link
Contributor

@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.

I'm not following why this is necessary? Iiuc, this is about boilerplate reduction for plugin authors? They have a workaround, only it's clunky?

Is someone subclassing target types - a plugin, or pantsbuild/pants?

@@ -72,6 +72,14 @@ def from_rules(cls, rules: Iterable[UnionRule]) -> UnionMembership:
mapping: DefaultDict[type, OrderedSet[type]] = defaultdict(OrderedSet)
for rule in rules:
mapping[rule.union_base].add(rule.union_member)
# Subclassed union bases should inherit the superclass's union members.
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like a separate change?

Copy link
Member Author

Choose a reason for hiding this comment

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

Separate from what?

Copy link
Contributor

Choose a reason for hiding this comment

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

From the main change with plugin fields being inherited. I don't see why unions are involved?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah.

Otherwise union.get(SomeTarget.PluginFields) wouldn't give you anything when you register a plugin field on Target.

@kaos
Copy link
Member Author

kaos commented Jun 24, 2022

It's for opening up for the visibility feature to be in a backend so it's opt-in.

With this change we can register the visibility field as a plugin field on the Target base class so all targets get it without having to explicitly register it on all individually.

@kaos
Copy link
Member Author

kaos commented Jun 24, 2022

Did you see the comment thread from the visibility design doc in a previous comment in this PR. Thought it explained the motivation for this pretty well.?

@kaos
Copy link
Member Author

kaos commented Jun 24, 2022

Also, I think it removes a surprising gotcha. If I subclass the PythonDistribution target class for instance, in order to customize it for some reason, I no longer have any of the plugin fields for it.

@kaos kaos merged commit 643d8da into pantsbuild:main Jun 24, 2022
@kaos kaos deleted the propagate_plugin_fields_to_subclasses branch June 24, 2022 22:04
thejcannon added a commit that referenced this pull request Aug 25, 2022
Before:
```
>>> print(union_membership.get(BlackRequest))
FrozenOrderedSet([<class 'pants.backend.python.lint.autoflake.rules.AutoflakeRequest'>, <class 'pants.backend.python.lint.black.rules.BlackRequest'>, <class 'pants.backend.python.lint.docformatter.rules.DocformatterRequest'>, <class 'pants.backend.python.lint.isort.rules.IsortRequest'>, <class 'pants.backend.shell.lint.shfmt.rules.ShfmtRequest'>, <class 'pants.backend.go.lint.gofmt.rules.GofmtRequest'>, <class 'pants.backend.java.lint.google_java_format.rules.GoogleJavaFormatRequest'>, <class 'pants.backend.scala.lint.scalafmt.rules.ScalafmtRequest'>])
```

After:
```
>>> print(union_membership.get(BlackRequest))
FrozenOrderedSet([])
```

This was introduced in #15876 which was first in 2.14.
thejcannon added a commit to thejcannon/pants that referenced this pull request Aug 25, 2022
…build#16645)

Before:
```
>>> print(union_membership.get(BlackRequest))
FrozenOrderedSet([<class 'pants.backend.python.lint.autoflake.rules.AutoflakeRequest'>, <class 'pants.backend.python.lint.black.rules.BlackRequest'>, <class 'pants.backend.python.lint.docformatter.rules.DocformatterRequest'>, <class 'pants.backend.python.lint.isort.rules.IsortRequest'>, <class 'pants.backend.shell.lint.shfmt.rules.ShfmtRequest'>, <class 'pants.backend.go.lint.gofmt.rules.GofmtRequest'>, <class 'pants.backend.java.lint.google_java_format.rules.GoogleJavaFormatRequest'>, <class 'pants.backend.scala.lint.scalafmt.rules.ScalafmtRequest'>])
```

After:
```
>>> print(union_membership.get(BlackRequest))
FrozenOrderedSet([])
```

This was introduced in pantsbuild#15876 which was first in 2.14.
# 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]
cczona pushed a commit to cczona/pants that referenced this pull request Sep 1, 2022
…build#16645)

Before:
```
>>> print(union_membership.get(BlackRequest))
FrozenOrderedSet([<class 'pants.backend.python.lint.autoflake.rules.AutoflakeRequest'>, <class 'pants.backend.python.lint.black.rules.BlackRequest'>, <class 'pants.backend.python.lint.docformatter.rules.DocformatterRequest'>, <class 'pants.backend.python.lint.isort.rules.IsortRequest'>, <class 'pants.backend.shell.lint.shfmt.rules.ShfmtRequest'>, <class 'pants.backend.go.lint.gofmt.rules.GofmtRequest'>, <class 'pants.backend.java.lint.google_java_format.rules.GoogleJavaFormatRequest'>, <class 'pants.backend.scala.lint.scalafmt.rules.ScalafmtRequest'>])
```

After:
```
>>> print(union_membership.get(BlackRequest))
FrozenOrderedSet([])
```

This was introduced in pantsbuild#15876 which was first in 2.14.
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.

None yet

4 participants