You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add Support for Adding .NET Attributes when Creating .NET Classes #1768
I want to be able to specify attributes on my class defined in python. This is essential for my specific use case, but I imagine generally useful. I can come up with 3 different situations where it could be useful to add attributes:
Attributes on types - This can be done with an annotation
Attributes on methods - This can be done with an annotation
Attributes on properties - It seems clr.clrproperty needs to be modified to support it.
### from test_clrmethod.py# Attaching attributes to types (1)@clr.attribute(DebuggerDisplayAttribute, "ExampleClrClass: X={X}")classExampleClrClass(System.Object):
__namespace__="PyTest"def__init__(self):
self._x=3# Attaching attributes to methods (2)@clr.clrmethod(int, [int])@clr.attribute(DescriptionAttribute, "Test method")deftest(self, x):
returnx*2defget_X(self):
returnself._xdefset_X(self, value):
self._x=value# Attaching attributes to properties (3)X=clr.clrproperty(int, get_X, set_X)\
.attribute(DescriptionAttribute, "Gets or sets X")\
.attribute(BrowsableAttribute, True)
# Also attaching attributes to properties (3)@clr.clrproperty(int)@clr.attribute(DescriptionAttribute, "Gets Y")defY(self):
returnself._x*2
Regarding using clr.attribte(DebuggerDisplayAttribute, "...") vs clr.attribute(DebuggerDisplay("...")), it is exceedingly hard to infer how an attribute is constructed form the attribute value itself. Instead the list of constructors can be iterated and matched with a list of arguments and this way the best matching constructor can be found.
I can probably implement this myself, but before making a PR I want to know if it will be accepted or it is a bad idea.
changed the title [-]Add Support for .NET Attributes when Creating .NET Classes [/-][+]Add Support for Adding .NET Attributes when Creating .NET Classes [/+]on Apr 13, 2022
Sounds good to me. But I believe at least your variant of syntax would be very tricky to implement for classes (methods are fine), because Python would first create class ExampleClrClass, and only then apply the attribute to it. But in .NET you can't create a class and then change it by adding attributes - you'd have to create a new class, which in your example would have the same name (which might not be a problem as long as you don't use reflection to find it).
BTW, the code in question is in CreateDerivedType function.
Finally, for the scenario you described, you could just override ToString function.
Also: @rmadsen-ks is there anything that is keeping us from just constructing the instances in Python already, like __clr_attributes__ = [DebuggerDisplayAttribute("ExampleClrClass: X={X}")]?
Also: @rmadsen-ks is there anything that is keeping us from just constructing the instances in Python already, like __clr_attributes__ = [DebuggerDisplayAttribute("ExampleClrClass: X={X}")]?
I also think that would be the most elegant solution, but in the dynamic type builder(ClassDerived.cs) we have to emit some IL code that calls the attribute constructor. So, from the attribute instance we would have to reverse engineer the arguments to insert into that constructor and I believe that is generally impossible.
Hmm, we could theoretically special-case System.Attribute derivatives, or automatically introduce facades without the Attribute suffix (so DebuggerDisplay("...") which would not be a real DebuggerDisplayAttribute instance but just contain a reference to the class and the arguments), though that could lead to quite a bit of confusion.
@filmor, I think this sounds like a great idea. So the list of tasks becomes:
Attribute facades that generates instances of 'AttributeConstructor'. Named the same as the attribute but without 'Attribute'.
Allow the use of __clr_attributes__ to assign attributes to generated types and members.
I have a good idea of how to do 2. For 1 I could use some hint of where to start looking.
Also for 1, for Attributes which are not named with the 'Attribute' suffix or if there is a naming conflict, we could fallback to support the use a tuple as in my example?
Activity
[-]Add Support for .NET Attributes when Creating .NET Classes [/-][+]Add Support for Adding .NET Attributes when Creating .NET Classes [/+]lostmsu commentedon Apr 13, 2022
Sounds good to me. But I believe at least your variant of syntax would be very tricky to implement for classes (methods are fine), because Python would first create class
ExampleClrClass, and only then apply the attribute to it. But in .NET you can't create a class and then change it by adding attributes - you'd have to create a new class, which in your example would have the same name (which might not be a problem as long as you don't use reflection to find it).BTW, the code in question is in
CreateDerivedTypefunction.Finally, for the scenario you described, you could just override
ToStringfunction.rmadsen-ks commentedon Apr 19, 2022
@lostmsu, you are right the '@'-attribute won't work for classes.
So maybe something like this then?
Your final comment I assume is referring to DebuggerDisplayAttribute, but I just used that as an example.
lostmsu commentedon Apr 19, 2022
@rmadsen-ks absolutely correct, and
__attributes__would work.filmor commentedon Apr 21, 2022
It could make sense to prefix all of the class members that we use with
clr, like__clr_attributes__.filmor commentedon Apr 21, 2022
Also: @rmadsen-ks is there anything that is keeping us from just constructing the instances in Python already, like
__clr_attributes__ = [DebuggerDisplayAttribute("ExampleClrClass: X={X}")]?rmadsen-ks commentedon Apr 21, 2022
I also think that would be the most elegant solution, but in the dynamic type builder(ClassDerived.cs) we have to emit some IL code that calls the attribute constructor. So, from the attribute instance we would have to reverse engineer the arguments to insert into that constructor and I believe that is generally impossible.
filmor commentedon Apr 21, 2022
Hmm, we could theoretically special-case
System.Attributederivatives, or automatically introduce facades without theAttributesuffix (soDebuggerDisplay("...")which would not be a realDebuggerDisplayAttributeinstance but just contain a reference to the class and the arguments), though that could lead to quite a bit of confusion.rmadsen-ks commentedon Apr 22, 2022
@filmor, I think this sounds like a great idea. So the list of tasks becomes:
__clr_attributes__to assign attributes to generated types and members.I have a good idea of how to do 2. For 1 I could use some hint of where to start looking.
Also for 1, for Attributes which are not named with the 'Attribute' suffix or if there is a naming conflict, we could fallback to support the use a tuple as in my example?