[docs]defget_module_config_path(module_code):config_path=os.environ.get(f"GEONATURE_{module_code}_CONFIG_FILE")ifconfig_path:returnPath(config_path)config_path=Path(CONFIG_FILE).parent/f"{module_code.lower()}_config.toml"ifconfig_path.exists():returnconfig_pathdist=get_dist_from_code(module_code)module_path=Path(sys.modules[dist.entry_points["code"].module].__file__).parent# module_path is commonly backend/gn_module_XXX/ but config dir is at package rootconfig_path=module_path.parent.parent/"config"/"conf_gn_module.toml"ifconfig_path.exists():returnconfig_pathreturnNone
[docs]defget_dist_from_code(module_code):fordistiniter_modules_dist():ifmodule_code==dist.entry_points["code"].load():returndistraiseException(f"Module with code {module_code} not installed in venv")
[docs]defiterate_revisions(script,base_revision):""" Iterate revisions without following depends_on directive. Useful to find all revisions of a given branch. """yelded=set()todo={base_revision}whiletodo:rev=todo.pop()yieldrevyelded.add(rev)rev=script.get_revision(rev)todo|=rev.nextrev-yelded
[docs]defalembic_branch_in_use(branch_name,directory,x_arg):""" Return true if at least one revision of the given branch is applied. """db=current_app.extensions["sqlalchemy"].dbmigrate=current_app.extensions["migrate"].migrateconfig=migrate.get_config(directory,x_arg)script=ScriptDirectory.from_config(config)base_revision=script.get_revision(script.as_revision_number(branch_name))branch_revisions=set(iterate_revisions(script,base_revision.revision))migration_context=MigrationContext.configure(db.session.connection())current_heads=migration_context.get_current_heads()# get_current_heads does not return implicit revision through dependencies, get_all_current doescurrent_heads=set(map(lambdarev:rev.revision,script.get_all_current(current_heads)))returnnotbranch_revisions.isdisjoint(current_heads)
[docs]defmodule_db_upgrade(module_dist,directory=None,sql=False,tag=None,x_arg=[]):module_code=module_dist.entry_points["code"].load()module_blueprint=module_dist.entry_points["blueprint"].load()# force discovery of modelsifmodule_dist.entry_points.select(name="migrations"):try:alembic_branch=module_dist.entry_points["alembic_branch"].load()exceptKeyError:alembic_branch=module_code.lower()else:alembic_branch=Nonemodule=db.session.execute(select(TModules).filter_by(module_code=module_code)).scalar_one_or_none()ifmoduleisNone:# add module to databasetry:module_picto=module_dist.entry_points["picto"].load()exceptKeyError:module_picto="fa-puzzle-piece"try:module_type=module_dist.entry_points["type"].load()exceptKeyError:module_type=Nonetry:module_doc_url=module_dist.entry_points["doc_url"].load()exceptKeyError:module_doc_url=Nonemodule=TModules(type=module_type,module_code=module_code,module_label=module_code.capitalize(),module_path=module_code.lower(),module_target="_self",module_picto=module_picto,module_doc_url=module_doc_url,active_frontend=True,active_backend=True,ng_module=module_code.lower(),)db.session.add(module)db.session.commit()elifalembic_branchandnotalembic_branch_in_use(alembic_branch,directory,x_arg):""" The module branch is not known to be applied by Alembic, but the module is present in gn_commons.t_modules table. Refusing to upgrade the Alembic branch. Upgrading of old module requiring manual stamp? """returnFalseifalembic_branch:revision=alembic_branch+"@head"db_upgrade(directory,revision,sql,tag,x_arg)returnTrue