Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added supporr for class/property/method attributes.
- Added shortened Attribute aliases which just generates tuples.
- More general CLR base class support - creating a class instance from C# is now more similar to creating one from python.
- Added attribute decorator to clr.py.
- Added testing for the various possibilities
  • Loading branch information
rmadsen-ks committed Oct 31, 2022
commit 28f47170d0b6ecce383076060b956cbf3705f360
3 changes: 3 additions & 0 deletions src/python_tests_runner/PythonTestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ static IEnumerable<string[]> PythonTestCases()
yield return new[] { "test_delegate", "test_bool_delegate" };
yield return new[] { "test_subclass", "test_virtual_generic_method" };
yield return new[] { "test_subclass", "test_interface_and_class_impl2" };
yield return new[] { "test_subclass", "test_class_with_attributes" };
yield return new[] { "test_subclass", "test_class_with_advanced_attribute" };
yield return new[] { "test_subclass", "test_more_subclasses" };
}

/// <summary>
Expand Down
67 changes: 61 additions & 6 deletions src/runtime/Resources/clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@ def test(self):
string z = x.test; // calls into python and returns "x"
"""

def __init__(self, type_, fget=None, fset=None):
def __init__(self, type_, fget=None, fset=None, attributes = []):
self.__name__ = getattr(fget, "__name__", None)
self._clr_property_type_ = type_
self.fget = fget
self.fset = fset

self._clr_attributes_ = attributes
def __call__(self, fget):
return self.__class__(self._clr_property_type_,
self.__class__(self._clr_property_type_,
fget=fget,
fset=self.fset)
fset=self.fset,
attributes = self._clr_attributes_)


def setter(self, fset):
self.fset = fset
Expand All @@ -47,8 +49,32 @@ def __set__(self, instance, value):
if not self.fset:
raise AttributeError("%s is read-only" % self.__name__)
return self.fset.__get__(instance, None)(value)
def add_attribute(self, attribute):
self._clr_attributes_.append(attribute)
return self

class property(object):

def __init__(self, type, default):
import weakref
self._clr_property_type_ = type
self.default = default
self.values = weakref.WeakKeyDictionary()
self._clr_attributes_ = []
self.fget = 1
self.fset = 1
def __get__(self, instance, owner):
v = self.values.get(instance, self.default)
return v
def __set__(self, instance, value):
self.values[instance] = value
def add_attribute(self, attribute):
self._clr_attributes_.append(attribute)
return self
def __call__(self, type, default):
self2 = self.__class__(self._clr_property_type_, type, default)
self2._clr_attributes_ = self._clr_attributes_
return self2
class clrmethod(object):
"""
Method decorator for exposing python methods to .NET.
Expand All @@ -67,18 +93,47 @@ def test(self, x):
int z = x.test("hello"); // calls into python and returns len("hello")
"""

def __init__(self, return_type, arg_types, clrname=None, func=None):
def __init__(self, return_type = None, arg_types = [], clrname=None, func=None, **kwargs):
if return_type == None:
import System
return_type = System.Void
self.__name__ = getattr(func, "__name__", None)
self._clr_return_type_ = return_type
self._clr_arg_types_ = arg_types
self._clr_method_name_ = clrname or self.__name__
self.__func = func
if 'attributes' in kwargs:
self._clr_attributes_ = kwargs["attributes"]
else:
self._clr_attributes_ = []

def __call__(self, func):
return self.__class__(self._clr_return_type_,
self2 = self.__class__(self._clr_return_type_,
self._clr_arg_types_,
clrname=self._clr_method_name_,
func=func)
self2._clr_attributes_ = self._clr_attributes_
return self2

def __get__(self, instance, owner):
return self.__func.__get__(instance, owner)

def clr_attribute(self, attribute):
self._clr_attributes_.append(attribute)
return self

class attribute(object):

def __init__(self, attr, *args, **kwargs):
self.attr = attr
import Python.Runtime
#todo: ensure that attributes only are pushed when @ is used.
#import inspect
#Python.Runtime.PythonDerivedType.Test(inspect.stack()[1].code_context)

Python.Runtime.PythonDerivedType.PushAttribute(attr)
def __call__(self, x):
import Python.Runtime
if Python.Runtime.PythonDerivedType.AssocAttribute(self.attr, x):
pass
return x
Loading