Skip to content

Classes without __namespace__ cannot be used for reflection #1774

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
rmadsen-ks opened this issue Apr 27, 2022 · 11 comments
Open

Classes without __namespace__ cannot be used for reflection #1774

rmadsen-ks opened this issue Apr 27, 2022 · 11 comments

Comments

@rmadsen-ks
Copy link
Contributor

rmadsen-ks commented Apr 27, 2022

Environment

  • Pythonnet version: 3.0.0-preview2022-04-11
  • Python version: 3.10
  • Operating System: MacOS
  • .NET Runtime: .net 6

Details

My software does lots of reflection on "plugin" types. Simply inheriting from a specific type is enough in C#, but when I use python.net I also have to define __namespace__. Since my users generally have the namespace being ., there is no logic reason for them to have to do this.

I can see which part of the code causes this:

    // from MetaType.cs:133 (git: 7247da55c174be1b733e5f9fc4e1c356f6c42dc4)
    if (clsDict.HasKey("__assembly__") || clsDict.HasKey("__namespace__"))
    {
            return TypeManager.CreateSubType(name, base_type, clsDict);
    }

I am wonder if we could broaden the cases where TypeManager.CreateSubType is used. For example in cases where the super class is a type created with CreateSubType, or just any .NET class in general. Maybe it could also be if the super class implements a specific interface.

_TODO_

Add a way to not have to specify namespace in the class in order for reflection to work.

@lostmsu
Copy link
Member

lostmsu commented Apr 27, 2022

The logic reason is that classes with __namespace__ are .NET classes as well as Python classes, and classes without it are just Python classes. This is by design.

@lostmsu lostmsu closed this as completed Apr 27, 2022
@filmor
Copy link
Member

filmor commented Apr 27, 2022

@lostmsu The point is that it could be enough that the base class is a .NET class. Since we control the __new__ in this case anyhow, this wouldn't be a huge change (a breaking one, yes, but I think the new behaviour might be less surprising).

@lostmsu
Copy link
Member

lostmsu commented Apr 27, 2022

@filmor are you suggesting all new derived classes to be .NET classes by default? What would be the way to turn that off?

@lostmsu lostmsu reopened this Apr 27, 2022
@rmadsen-ks
Copy link
Contributor Author

Maybe I can add that if the base class is abstract, inheriting from it without namespace causes a an exception during construction: "Python.Runtime.PythonException: cannot instantiate abstract class". A similar issue happens with interfaces.

Also the python object seems to loose all memory of its type once it gets converted back into an C# object, casting it to its base type.

Both these issues could be fixed by this change.

@phuongdtvd
Copy link

phuongdtvd commented Nov 17, 2022

@rmadsen-ks Hi can I ask if you find any workaround for the problem? I’m having the exact same problem of inheriting from an abstract base class then converting back into C# loses all info. GetType.GetFields() won’t work at all and I’m honestly stuck right now. I wonder if #433 can help.

@rmadsen-ks
Copy link
Contributor Author

Hi @phuongdtvd, this sounded like a design decision to me, so I made a fork which does some of these things a bit differently. I don't think #433 makes a huge difference here.

@filmor
Copy link
Member

filmor commented Nov 18, 2022

@rmadsen-ks Could you create a PR from your branch? I personally don't see (right now) a problem with always making classes derived from .NET classes also .NET classes themselves (with a way to shut that off). We could make this behaviour configurable (something like Runtime.Configure("<feature-name>", true)), to keep it compatible without bumping the major version.

@rmadsen-ks
Copy link
Contributor Author

Hi @filmor, sure, but I have a bunch of features on that fork, some more or less experimental. In total, it is not that many changes. I'll clean it up a bit and setup a PR.

@rmadsen-ks
Copy link
Contributor Author

@filmor, I have added PR #2019. Those are the majority of changes in my fork.

@lostmsu
Copy link
Member

lostmsu commented Nov 29, 2022

Turning previously non-.NET types defined in Python as derived from .NET types into .NET types would be a breaking change. As 3.0 is released, this is problematic.

@filmor
Copy link
Member

filmor commented Nov 29, 2022

@lostmsu I lined out how we could do it anyhow, via a runtime/startup feature flag mechanism. No magic required.

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

4 participants