développement d'un framework modulaire
bonjour,
J'essaye de créer un framework WEB API REST "coreless" par dessus Tornado et en y intégrant Gino, en faite le core du framework sera un système de loader de module, les modules seront interconnectés mais j'ai quelques problèmes d'import relatif.
ça marche mais ... j'ai l'impression de ne pas m'y prendre correctement et qu'il s'agit plus d'un hack que d'autre chose. Mon linter me dit "Attempted relative import beyond top-level package" par exemple au niveau du main du module
voici un cas reproduction minimal épuré de tout commentaire ou docstrings
/main.py
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| # coding: utf-8
import importlib
import sys
import types
class MissingEntryPointError(Exception): pass
class RequiredDependenciesNotEnabledError(Exception): pass
class ModuleAlreadyLoadedError(Exception): pass
class Application:
def __init__(self, *args, **kwargs):
self.__enabled_modules = kwargs.pop("enabled_modules", {})
self.__dirmodule = kwargs.pop("dirmodule", "modules")
self.__modules = {}
# super().__init__(*args, **kwargs)
def load_module(self, name, config):
if name in self.__modules:
raise ModuleAlreadyLoadedError(name)
module = importlib.import_module("{0}.{1}.main".format(self.__dirmodule, name))
try:
entry_point = getattr(module, "setup")
except AttributeError:
raise MissingEntryPointError(name)
try:
entry_point(self, config)
except Exception as e:
raise e
else:
self.__modules[name] = module
@property
def enabled_modules(self):
return types.MappingProxyType(self.__enabled_modules)
enabled_modules = {"module_a": {}}
app = Application(enabled_modules=enabled_modules)
for module, config in app.enabled_modules.items():
app.load_module(module, config) |
/modules/module_a/main.py
Code:
1 2 3 4 5 6 7 8 9
| from .func.f import f
dependencies = []
def setup(app, module_config):
print("module loaded")
print(f()) |
/modules/module_a/func/f.py
Je me dis que retravailler mon idée mais en utilisant des packages serait plus simple (bien que je ne sache pas faire, ça doit pas être sorcier quand même) mais cela poserait un problème,
Gino étant une ORM (basé sur SqlAlchemy) j'ai besoin de charger les modèles de tables, hors les modules pourrons dépendre d'autres modules, un exemple:
une table parent avec une colonne: id
une table enfant avec deux colonnes: id et parent_id (foreign key qui fait référence sur parent.id en delete on cascade )
(toutes les modules que je compte faire serons avec des delete on cascade)
imaginons que je crée un parent et en enfant, avec le module parent et enfant d'activés, puis que je désactive le module enfant (le contraire est impossible puisque le module enfant demande comme dépendance parent), donc à partir de là je n'est plus qu'un modèle de table, celui de parent. Maintenant supposons que je veuille supprimer le parent, pas de soucis, mais dans mon interface web je me dit que se serait bien de connaitre tous les enfants (et potentiel petits enfants) de façon récursive dans le popup disant "voulez vous vraiment supprimer X" (en supposant que j'ai la solution du coté de l'ORM pour charger tous les enfants de façon récursive avant le delete on cascade, je ne me suis pas encore penché sur les relationship loading techniques).
L'avantage avec mes imports dynamiques c'est que je peux importer les fichiers avec tous les fichiers du nom de db_models.py avec un simple coup de glob récursif mais ça reste bancal...
En parallèle je regarde si l'automap ne pourrais pas solutionner en partie se problème.
Enfin voilà si quelqu'un à un conseil je suis preneur :D