ManderaGeneral / generalimport

Handle all your optional dependencies with a single call!
https://pypi.org/project/generalimport/
Apache License 2.0
15 stars 1 forks source link

Allow subclassing from missing dependency #27

Open ZanSara opened 1 year ago

ZanSara commented 1 year ago

Problem

So far generalimport does not allow users to create subclasses of missing dependencies. So this code:

generalimport("my_module")
import my_module

class SubClass(my_module.BaseClass):
    def __init__(self):
        ...

fails with:

Traceback (most recent call last):
  File "/work/generalimport/example.py", line 6, in <module>
    class SubClass(test_module.BaseClass):
  File "/work/generalimport/generalimport/fake_module.py", line 21, in error_func
    raise MissingOptionalDependency(f"Optional dependency {name} was used but it isn't installed.")
generalimport.exception.MissingOptionalDependency: Optional dependency 'test_module' was used but it isn't installed.

This is quite limiting in OOP and makes using generalimport with libraries like sqlalchemy close to impossible.

Proposed solution

I propose leveraging __mro_entries__ to make this usecase work. Classes based on non-existing modules should fail only when initialized.

PR coming soon :slightly_smiling_face:

Mandera commented 1 year ago

This is a really good idea, I haven't thought of this! I noticed that __init_subclass__ = error_func is the only method preventing subclassing currently.

I've never heard of __mro_entries__ before, never found it when I did my initial dunder research!

Found PEP 560 referencing it

Like I mentioned in the PR - I'd love if we could return a FakeModule object when it's subclasses