Skip to content

Exception when deriving from a .NET class with abstract methods in Python #2571

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

Open
Eswcvlad opened this issue Apr 3, 2025 · 2 comments
Open

Comments

@Eswcvlad
Copy link

Eswcvlad commented Apr 3, 2025

Environment

  • Python.NET version: 3.0.5
  • Tested on three configurations:
    • Windows 10, Python 3.12.4, .NET Framework
    • Windows 10, Python 3.12.4, .NET 9.0.201
    • Debian 12, Python 3.11.2, .NET 8.0.407

Details

I have an abstract .NET class, which has abstract methods to override within a netstandard2.0 library. When I try to derive from such a class in Python, it throws a TypeError during class object creation.

Below is a basic example.

.NET library code:

namespace TestLib
{
    public abstract class TestClass
    {
        public string Foo()
        {
            return "Foo";
        }

        protected abstract string Bar();
    }
}

Python code:

from pathlib import Path

import clr

clr.AddReference(str(Path(__file__).parent / 'TestLib.dll'))

from TestLib import TestClass


class SubTestClass(TestClass):
    __namespace__ = 'CrlTest'

    def Bar(self):
        return 'Bar'


if __name__ == '__main__':
    stc = SubTestClass()
    print('Foo() -> ' + stc.Foo())
    print('Bar() -> ' + stc.Bar())

Python script output:

Traceback (most recent call last):
  File "<redacted>\crl_test.py", line 10, in <module>
    class SubTestClass(TestClass):
TypeError: Method 'Bar' in type 'CrlTest.SubTestClass' from assembly 'Python.Runtime.Dynamic, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
@Eswcvlad
Copy link
Author

Eswcvlad commented Apr 3, 2025

After some further testing, it looks like it is specifically the method being protected abstract. If it is public abstract, as with an interface, then it works fine.

@Eswcvlad
Copy link
Author

Eswcvlad commented Apr 8, 2025

Looks like this is, actually, a duplicate of #2192, though having protected abstract methods makes the issue more annoying...

For now I've forked it with a tweak to allow overriding protected methods. The downside is that all protected methods get automatically wrapped into public ones in Python, though, on the other hand, since Python doesn't differentiate between the two, it doesn't seem like a big deal...

Eswcvlad added a commit to Eswcvlad/itextpy that referenced this issue Apr 8, 2025
Annoyingly, you cannot override protected methods in Python.NET. And
this is a big problem for AbstractPdfDocumentEventHandler, as you need
to override an `abstract protected` method.

Relevant issues:
- pythonnet/pythonnet#2213
- pythonnet/pythonnet#2571

I've tried making a Python.NET fork, which allows you to override:
- https://github.com/Eswcvlad/pythonnet/tree/protected-override

But since the issue has been hanging for a while, I doubt it will be
fixed soon. And making a dependency on a fork is not great...

Changing this on iText side is not good as well, as it makes the C# API
worse...

For now, I've patched all AbstractPdfDocumentEventHandler
OnAcceptedEvent methods in iText to be public, but this is a very bad
solution, as:
- You would need to track any new subclasses on updates and patch them
  as well.
- You would need to update these patches for every release.
- This only handles one method, while this is a global problem.
- If you add another library, which also derives from
  AbstractPdfDocumentEventHandler, then it will not work, if
  OnAcceptedEvent remained "protected" there.

But it is better than nothing...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant