Henning, It is very questionable if "protected" should be available for overriding in Python, since we are not really doing compile time overriding in a .NET class with all sorts of differences in class compilation vs runtime emission.
But as a quick workaround you can add protected in this method in pythonnet: private static void AddVirtualMethod(MethodInfo method, Type baseType, TypeBuilder typeBuilder) Let us know about the result. Cheers, Denis On Tue, Sep 27, 2016 at 2:49 AM, Henning Moeller <hmoel...@comprion.com> wrote: > Hi Denis, > > > > thank you again. That helped a lot. > > > > But – I’m sorry to bother you again. In the classes I really have to use, > some of the virtual methods are protected. Those are not resolved by > pythonnet. Only public virtual is recognized and overridden by the > inherited class. See the (only slightly) altered example: > > > > namespace PythonBaseClass > > { > > using System; > > > > public class Door > > { > > public virtual void Open() > > { > > if (!IsOpen()) > > Toggle(); > > } > > > > public virtual void Close() > > { > > if (IsOpen()) > > Toggle(); > > } > > > > public virtual bool IsOpen() > > { > > Console.WriteLine("Door.IsOpen()"); > > return false; > > } > > > > *protected* virtual void Toggle() > > { > > Console.WriteLine("Door.Toggle()"); > > } > > } > > } > > > > The Python code has just been altered so that the namespace is properly > set. Running the example comes with the following output: > > > > Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:19:22) [MSC v.1500 32 > bit (Intel)] on win32 > > Type "help", "copyright", "credits" or "license" for more information. > > >>> from PythonInheritedClass import * > > >>> d = StringDoor() > > >>> d.status > > 'closed' > > >>> d.Open() > > StringDoor.IsOpen() > > *Door.Toggle()* > > >>> > > > > Any ideas? This looks a little bit more “doable” than the abstract thing. > > > > BR, > > > > Henning > > > > *From:* PythonDotNet [mailto:pythondotnet-bounces+hmoeller= > comprion....@python.org] *On Behalf Of *Denis Akhiyarov > *Sent:* Montag, 26. September 2016 20:16 > *To:* A list for users and developers of Python for .NET < > pythondotnet@python.org> > *Subject:* Re: [Python.NET] Inheriting from abstract .NET class > > > > Hi Henning, > > > > This feature was implemented by @tonyroberts in 2013 and is tested in CI > with test_subclass.py file. > > > > According to these tests, the missing piece in your code is defining > explicitly __namespace__ on the .NET class derived in Python: > > > > In [11]: class StringDoor1(Door): > > ....: __namespace__ = "PythonBaseClass" > > ....: def __init__(self): > > ....: self.status = "closed" > > ....: > > ....: def IsOpen(self): > > ....: print "StringDoor.IsOpen()" > > ....: return self.status == "open" > > ....: > > ....: def Toggle(self): > > ....: print "StringDoor.Toggle()" > > ....: if self.status == "open": > > ....: self.status = "closed" > > ....: else: > > ....: self.status = "open" > > > > In [12]: d = StringDoor1() > > > > In [13]: d.status > > Out[13]: 'closed' > > > > In [14]: d.Open() > > StringDoor.IsOpen() > > StringDoor.Toggle() > > > > In [15]: d.status > > Out[15]: 'open' > > > > > > > > Thanks, > > Denis > > > > On Mon, Sep 26, 2016 at 9:19 AM, Henning Moeller <hmoel...@comprion.com> > wrote: > > Hi Denis, > > > > Thanks for your fast response. Sounds completely reasonable to me. And > this has not been too much of an issue for me. > > > > I got rid of the abstract base class simply by providing an “empty” > implementation and using a non-abstract base class. No need for meta > classes any more. This way, I got rid of error messages. Great! > > > > Unfortunately, there seem to be an issue when calling a virtual method > inside the C# implementation. Even when overriding this virtual method in > Python, it’s still the base class’ implementation which is called. > > > > See the new simple base class defined in C#: > > > > namespace PythonBaseClass > > { > > using System; > > > > public class Door > > { > > public virtual void Open() > > { > > if (!IsOpen()) > > Toggle(); > > } > > > > public virtual void Close() > > { > > if (IsOpen()) > > Toggle(); > > } > > > > public virtual bool IsOpen() > > { > > Console.WriteLine("Door.IsOpen()"); > > return false; > > } > > > > public virtual void Toggle() > > { > > Console.WriteLine("Door.Toggle()"); > > } > > } > > } > > > > The consuming Python code now looks like this: > > > > import clr > > from PythonBaseClass import Door > > > > class StringDoor(Door): > > def __init__(self): > > self.status = "closed" > > > > def IsOpen(self): > > print "StringDoor.IsOpen()" > > return self.status == "open" > > > > def Toggle(self): > > print "StringDoor.Toggle()" > > if self.status == "open": > > self.status = "closed" > > else: > > self.status = "open" > > > > But the output does not look like expected: > > > > Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:19:22) [MSC v.1500 32 > bit (Intel)] on win32 > > Type "help", "copyright", "credits" or "license" for more information. > > >>> from PythonInheritedClass import StringDoor > > >>> d = StringDoor() > > >>> d.status > > 'closed' > > >>> d.Open() > > *Door.IsOpen()* > > *Door.Toggle()* > > >>> d.status > > *'closed'* > > >>> > > > > From my understanding, the output should rather read “ > StringDoor.<something>()” instead of “Door.<something>()”. Obviously, > only the base implementation is called but the overridden methods are > ignored. > > > > Also a limitation of inheriting C# classes in pythonnet? > > > > BR, > > > > Henning > > > > *From:* PythonDotNet [mailto:pythondotnet-bounces+hmoeller= > comprion....@python.org] *On Behalf Of *Denis Akhiyarov > *Sent:* Donnerstag, 22. September 2016 19:38 > *To:* A list for users and developers of Python for .NET < > pythondotnet@python.org> > *Subject:* Re: [Python.NET] Inheriting from abstract .NET class > > > > You are not a "Python n00b" based on metaclass usage! > > > > My recommendation is to keep simple integration layer between CPython and > .NET, hence metaclasses were/are not supported. > > > > But contributions are welcome! Although I expect this to be a tremendous > undertaking based on reviewing multiple sources. > > > > Note that metaclass is a very different low-level concept from > higher-level abstract classes in .NET, hence direct mapping (e.g. > `.register()` ) is not feasible. > > > > Thanks, > > Denis > > > > On Thu, Sep 22, 2016 at 10:04 AM, Henning Moeller <hmoel...@comprion.com> > wrote: > > Hello out there, > > > > I’m trying to inherit from an abstract .NET base class in Python (2.7). > I’m a Python n00b but from what I understood… > > > > Here’s what I managed to do in Python only and which works fine: > > > > [File: room.py] ------- > > import abc > > > > class Room(object): > > def __init__(self, door): > > self.door = door > > > > def open(self): > > self.door.open() > > > > def close(self): > > self.door.close() > > > > def is_open(self): > > return self.door.is_open() > > > > class Door(object): > > __metaclass__ = abc.ABCMeta > > > > def open(self): > > if not self.is_open(): > > self.toggle() > > > > def close(self): > > if self.is_open(): > > self.toggle() > > > > @abc.abstractmethod > > def is_open(self): > > pass > > > > @abc.abstractmethod > > def toggle(self): > > pass > > > > class StringDoor(Door): > > def __init__(self): > > self.status = "closed" > > > > def is_open(self): > > return self.status == "open" > > > > def toggle(self): > > if self.status == "open": > > self.status = "closed" > > else: > > self.status = "open" > > > > class BooleanDoor(Door): > > def __init__(self): > > self.status = True > > > > def is_open(self): > > return self.status > > > > def toggle(self): > > self.status = not (self.status) > > > > Door.register(StringDoor) > > Door.register(BooleanDoor) > > ------- > > > > Now, all I did was to replace the abstract base class Door by a C# > representation: > > > > [File: PythonAbstractBaseClass.dll] ------- > > namespace PythonAbstractBaseClass > > { > > public abstract class Door > > { > > public virtual void Open() > > { > > if (!IsOpen()) > > Toggle(); > > } > > > > public virtual void Close() > > { > > if (IsOpen()) > > Toggle(); > > } > > > > public abstract bool IsOpen(); > > public abstract void Toggle(); > > } > > } > > ------- > > > > Removing Door from the Python part and importing it from the .NET assembly > instead, I end up with this: > > > > [File: room2.py] ------- > > import clr > > import abc > > from PythonAbstractBaseClass import Door > > > > class Room(object): > > def __init__(self, door): > > self.door = door > > > > def open(self): > > self.door.open() > > > > def close(self): > > self.door.close() > > > > def is_open(self): > > return self.door.is_open() > > > > class StringDoor(Door): > > def __init__(self): > > self.status = "closed" > > > > def is_open(self): > > return self.status == "open" > > > > def toggle(self): > > if self.status == "open": > > self.status = "closed" > > else: > > self.status = "open" > > > > class BooleanDoor(Door): > > def __init__(self): > > self.status = True > > > > def is_open(self): > > return self.status > > > > def toggle(self): > > self.status = not (self.status) > > > > Door.register(StringDoor) > > Door.register(BooleanDoor) > > ------- > > > > But this fails with the following error message: > > > > Door.register(StringDoor) > > AttributeError: type object 'Door' has no attribute 'register' > > > > From what I understood about abc.ABCMeta, this metaclass contributes the > ‘register’ method. It seems that abstract C# classes do not come with the > same metaclass. They instead come with metaclass “CLR Metatype” which > obviously does not provide ‘register’. > > > > But if I drop the call to ‘register’, on instantiating one of the derived > classes, I receive the error message > > > > sdoor = StringDoor() > > TypeError: cannot instantiate abstract class > > > > Is there a way to inherit from an abstract .NET class or is this is > missing feature? > > > > Thanks in advance, > > > > Henning > > > > > _________________________________________________ > Python.NET mailing list - PythonDotNet@python.org > https://mail.python.org/mailman/listinfo/pythondotnet > > > > > _________________________________________________ > Python.NET mailing list - PythonDotNet@python.org > https://mail.python.org/mailman/listinfo/pythondotnet > > > > _________________________________________________ > Python.NET mailing list - PythonDotNet@python.org > https://mail.python.org/mailman/listinfo/pythondotnet >
_________________________________________________ Python.NET mailing list - PythonDotNet@python.org https://mail.python.org/mailman/listinfo/pythondotnet