Load module to invoke its decorators

二次信任 提交于 2019-12-11 07:25:45

问题


I have a program consistring of several modules specifying the respective web application handlers and one, specifying the respective router.
The library I use can be found here.

Excerpt from webapp.service (there are more such modules):

from webapp.router import ROUTER

@ROUTER.route('/service/[id:int]')
class ServicePermissions(AuthenticatedService):
    """Handles service permissions."""

    NODE = 'services'
    NAME = 'services manager'
    DESCRIPTION = 'Manages services permissions'
    PROMOTE = False

webapp.router:

ROUTER = Router()

When I import the webapp.router module, the webapp.service module does obviously not run. Hence, the @ROUTER.route('/service/[id:int]') decorator is not run and my web aplication will fail with the message, that the respective route is not available.

What is the best practice in that case to run the code in webapp.service to "run" the decorators? I do not really need to import the module itself or any of its members.


回答1:


As stated in the comments fot the question, you simply have to import the modules. As for linter complaints, those are the lesser of your problems. Linters are there to help - if they get into the way, just don't listen to them.

So, the simple way just to get your things working is, at the end of your __main__.py or __init__.py, depending on your app structure, to import explicitly all the modules that make use of the view decorator.

If you have a linter, check how to silence it on the import lines - that is usually accomplished with a special comment on the import line.

Python's introspection is fantastic, but it can't find instances of a class, or subclasses, if those are defined in modules that are not imported: such a module is just a text file sitting on the disk, like any data file.

What some frameworks offer as an approach is to have a "discovery" utility that will silently import all "py" files in the project folders. That way your views can "come into existence" without explicit imports.

You could use a function like:

import os

def discover(caller_file):
    caller_folder = os.path.dirname(caller_file)
    for current, folders, files in os.walk(caller_folder):
        if current == "__pycache__":
            continue
        for file in files:
            if file.endswith(".py"):
                __import__(os.path.join(current, file))

And call it on your main module with discover(__file__)



来源:https://stackoverflow.com/questions/47334197/load-module-to-invoke-its-decorators

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!