iuuujkl
iuuujkl

Reputation: 2394

Loop over __all__ in __init__.py

I have a __init__.py file in a folder. This is the content:

from .user import UserManager
from .user_group import UserGroupManager

__all__ = [
    "UserManager",
    "UserGroupManager",
]

In fact the list of managers is way larger, but that will only make the question to complex. Now I want to loop over all the managers I got. Is there a way to loop over those with this __init__.py file? I don't have a list of all possible managers anywhere else in the application, only in this init file.

I thought doing something like this in a service.py file:

def get_manager_by_id(id: str):
    for manager in managers.__all__:
        # use the manager

But that raises an error that manager is a string, which is logic. Is the solution here to find the manager with the string or is there a better way to do this?

Upvotes: 0

Views: 551

Answers (1)

Jasmijn
Jasmijn

Reputation: 10452

I can think of two reasonably sensible ways to do this. My preference would go to:

# __init__.py
from .user import UserManager
from .user_group import UserGroupManager

MANAGERS = [UserManager, UserGroupManager]

__all__ = [
    "UserManager",
    "UserGroupManager",
]

# service.py
def get_manager_by_id(id: str):
    for manager in managers.MANAGERS:
        # use the manager

It has the advantage that if you want to add other things to __init__.py (utility functions, constants, classes that aren't managers...), it won't interfere with get_manager_by_id.

Alternatively, you could do:

# __init__.py remains as you wrote it

# service.py
def get_manager_by_id(id: str):
    for manager_name in managers.__all__:
        manager = getattr(managers, manager_name)
        # use the manager

... but if you want to add other things to your package, now you gotta check if manager actually is a manager class somehow.

Upvotes: 1

Related Questions