happy-kitchen-89482
08/11/2021, 6:37 PMException: Invalid Get. Because the second argument to `Get(BuiltPackage, PythonDistributionFieldSet, PythonDistributionFieldSet(address=Address(testprojects/src/python/hello/native:dist), provides=<class 'pants.backend.python.target_types.PythonProvidesField'>(alias='provides', address=testprojects/src/python/hello/native:dist, value=<pants.backend.python.macros.python_artifact.PythonArtifact object at 0x107324b38>, default=None)))` is annotated with `@union`, the third argument should be a member of that union. Did you intend to register `UnionRule(PythonDistributionFieldSet, PythonDistributionFieldSet)`? If not, you may be using the wrong type (PythonDistributionFieldSet) for the third argument.
PythonDistributionFieldSet is not an @union, but its superclass (PackageFieldSet) is.happy-kitchen-89482
08/11/2021, 6:37 PMhundreds-father-404
08/11/2021, 6:38 PMPackageFieldSet
, you inherit the @union
stuff. So the engine naively thinks that your subclass is a union base too
I don't know how to fix this. In Python, how do you have a superclass have a property but not any subclasses?hundreds-father-404
08/11/2021, 6:39 PMancient-vegetable-10556
08/11/2021, 6:40 PMancient-vegetable-10556
08/11/2021, 6:42 PMdef union(cls, name: str):
if cls.__name__ != str:
return cls
# do actual decoration here
return cls
ancient-vegetable-10556
08/11/2021, 6:43 PMunion()
would need to return a decorator function, but the idea is that you give @union
enough information to figure out if the decorator should bail for subclasses.ancient-vegetable-10556
08/11/2021, 6:43 PM@union
decorator less eggplant thoughancient-vegetable-10556
08/11/2021, 6:44 PMhundreds-father-404
08/11/2021, 6:45 PMancient-vegetable-10556
08/11/2021, 6:45 PM@union("PackageFieldSet")
class PackageFieldSet(FieldSet, etc etc etc):
etc
hundreds-father-404
08/11/2021, 6:46 PMancient-vegetable-10556
08/11/2021, 6:46 PMancient-vegetable-10556
08/11/2021, 6:47 PMhundreds-father-404
08/11/2021, 6:47 PMhundreds-father-404
08/11/2021, 6:48 PMcurved-television-6568
08/11/2021, 6:52 PMdef union(cls, name: str):
if cls.__name__ != str:
return cls
# do actual decoration here
return
Would this actually work?
The decorator is on the base class only, child classes would still inherit the “actual decoration” from the base…ancient-vegetable-10556
08/11/2021, 6:53 PMancient-vegetable-10556
08/11/2021, 6:53 PMancient-vegetable-10556
08/11/2021, 6:54 PMcurved-television-6568
08/11/2021, 6:54 PMcurved-television-6568
08/11/2021, 6:54 PMancient-vegetable-10556
08/11/2021, 6:55 PMwitty-crayon-22786
08/11/2021, 6:59 PMwitty-crayon-22786
08/11/2021, 6:59 PMancient-vegetable-10556
08/11/2021, 6:59 PMancient-vegetable-10556
08/11/2021, 6:59 PMancient-vegetable-10556
08/11/2021, 8:18 PMhappy-kitchen-89482
08/11/2021, 8:30 PMancient-vegetable-10556
08/11/2021, 8:32 PMancient-vegetable-10556
08/11/2021, 8:32 PMwitty-crayon-22786
08/11/2021, 8:34 PMHave sometimes wondered if we could replace unions with subclassing…@enough-analyst-54434 has explored that. but i think that a really important portion to preserve is optional registration. so you wouldn’t actually be able to use the inheritance hierarchy to decide which instances were registered.
witty-crayon-22786
08/11/2021, 8:34 PMhappy-kitchen-89482
08/11/2021, 8:36 PMwitty-crayon-22786
08/11/2021, 8:36 PMhappy-kitchen-89482
08/11/2021, 8:36 PMunion
is a little confusingwitty-crayon-22786
08/11/2021, 8:37 PMwitty-crayon-22786
08/11/2021, 8:41 PM@union
member (to construct it/call it/etc), so requiring that it is a subtype would be reasonable. it’s just somewhat orthogonal to the registration problemhappy-kitchen-89482
08/11/2021, 8:49 PMwitty-crayon-22786
08/11/2021, 8:59 PM@union
decorator, probably. @ancient-vegetable-10556: are you still looking at that?happy-kitchen-89482
08/11/2021, 9:05 PMancient-vegetable-10556
08/11/2021, 9:35 PM@union
works and how we resolve rules in the graphcurved-television-6568
08/11/2021, 10:09 PMancient-vegetable-10556
08/11/2021, 10:09 PMcurved-television-6568
08/11/2021, 10:10 PMhundreds-father-404
08/11/2021, 10:11 PMwitty-crayon-22786
08/11/2021, 10:27 PMGet(X, Y, ..)
(where Y
is a union) into a series of Get(X, $member, ..)
for the union members… which happens here: https://github.com/pantsbuild/pants/blob/731c855630a9eed6c68fdf6129541dc6a69ec3e1/src/python/pants/engine/internals/scheduler.py#L658-L666ancient-vegetable-10556
08/11/2021, 10:28 PMwitty-crayon-22786
08/11/2021, 10:29 PM@union
decorator used to literally just poke a _union
field onto a class (which would still suffer from this bug, but maybe more clearly)… now it’s generalizedancient-vegetable-10556
08/11/2021, 10:29 PMhappy-kitchen-89482
08/12/2021, 1:31 AMhappy-kitchen-89482
08/12/2021, 1:31 AMcurved-television-6568
08/12/2021, 6:44 AMcurved-television-6568
08/12/2021, 6:47 AMcurved-television-6568
08/12/2021, 6:49 AMhundreds-father-404
08/12/2021, 7:57 AMIs it desired that all union members be subclasses of the union base classI don't think it's desired. We'd lose major flexibility, like registering something someone else wrote (pants core) to use a union you defined in your plugin, because you can't change the pants core type to subclass your union
curved-television-6568
08/12/2021, 8:13 AMWe can still require that the classes you register into the unions must be subtypes of the union class
hundreds-father-404
08/12/2021, 8:15 AMwitty-crayon-22786
08/12/2021, 4:39 PMwitty-crayon-22786
08/12/2021, 4:40 PMwitty-crayon-22786
08/12/2021, 4:47 PMwitty-crayon-22786
08/12/2021, 4:48 PMhundreds-father-404
08/12/2021, 4:58 PMProtocol
!witty-crayon-22786
08/12/2021, 5:01 PMProtocol
? hmmm!happy-kitchen-89482
08/13/2021, 4:54 AMwitty-crayon-22786
08/13/2021, 8:06 PM@union
implied Protocol
, or actually automatically extended it for you, maybe it wouldn’t actually increase complexity that much…witty-crayon-22786
08/13/2021, 8:07 PM@union
to (strawname) @protocol
or @protocol_base
or somethingwitty-crayon-22786
08/13/2021, 8:08 PMancient-vegetable-10556
08/13/2021, 8:24 PMenough-analyst-54434
08/13/2021, 8:25 PMenough-analyst-54434
08/13/2021, 8:25 PMancient-vegetable-10556
08/13/2021, 8:25 PMenough-analyst-54434
08/13/2021, 8:33 PMcurved-television-6568
08/16/2021, 1:12 PMenough-analyst-54434
08/16/2021, 1:48 PMcheese_instance.get_milkfat_percentage
. Then all registered union members must have a method get_milkfat_percentage
. That method name and signature is not generalizable in any base protocol. The only way it would be is if we swtiched to having a single catch-all plugin protocol, say <http://Plugin.do|Plugin.do>(*args, *kwargs)
. That seems likely unworkable and also against one of the plugin API selling points of type-checkability.curved-television-6568
08/16/2021, 1:55 PMget_milkfat_percentage
in your derived union protocol.. I think this will work. example coming in the PR…enough-analyst-54434
08/16/2021, 2:03 PMfrom typing import Protocol; class MyUnionBase(Protocol): ...
with from pants.unions import Union; class MyUnionBase(Union):...
? Yeah - I'll check out the PR.curved-television-6568
08/16/2021, 10:13 PMwitty-crayon-22786
08/16/2021, 10:44 PMcurved-television-6568
08/17/2021, 1:41 PM