import os import os.path import sys import gc import importlib import types import hserver.api from simplelog import log def new_module(modname, path = None, file = None): mod = types.ModuleType( modname ) if not path is None: mod.__path__ = path if not file is None: mod.__file__ = file sys.modules[ modname ] = mod return mod class Package: def __init__(self, pm, path, pname): self.__pm = pm self.__path = path self.__modpath = "packages.%s" % (pname,) self.__mod = new_module( self.__modpath ) self.__allowed_modules = [ "hserver", "hserver.api" ] self.__modules = {} self.__builtins = dict(__builtins__) self.__builtins["__import__"] = self.__mod_import self.__builtins["export"] = self.__export self.__exports = {} self.__load() def module(self): return self.__mod def __load(self): print("Package.__load(): Path=%s" % (self.__path,)) self.__templates = hserver.TemplateModule("%s/templates" % (self.__path,)) self.__modules["%s.Templates" % (self.__modpath,)] = self.__templates if os.path.exists("%s/package.conf" % (self.__path,)): pcn = "%s/package.conf" % (self.__path,) self.__config = new_module( "package.conf", file=pcn ) self.__mod_refresh( self.__config ) if (hasattr(self.__config,"modules")): for mname in self.__config.modules: self.__allowed_modules.append( mname ) files = os.listdir( self.__path ) for fn in files: if (fn.endswith(".py")): self.__mod_create( fn[:-3] ) print("Package: Modules: %s" % (self.__modules,)) def __mod_create(self, localname): "Erstelle/Lade ein Modul aus diesem Package" modname = "%s.%s" % (self.__modpath,localname) if modname in self.__modules: return self.__modules[ modname ] modpath = localname.split(".") localfile = modpath[-1] del modpath[-1] if len(modpath)==0 : modparent = self.__mod else: modparent = self.__mod_create( ".".join(modpath) ) mfile = ("%s/%s/%s.py" % (self.__path,"/".join(modpath),localfile)).replace("//","/") mpath = ("%s/%s" % (self.__path,"/".join(modpath))).replace("//","/") print("__mod_create( %s ): Check: F=%s , P=%s" % (localname, mfile, mpath)) if not (os.path.exists(mfile)): mfile = ("%s/%s/%s/__init__.py" % (self.__path,"/".join(modpath),localfile)).replace("//","/") mpath = ("%s/%s/%s" % (self.__path,"/".join(modpath), localfile)).replace("//","/") print("__mod_create( %s ): Check: F=%s , P=%s" % (localname, mfile, mpath)) if os.path.exists(mpath): if not (os.path.exists(mfile)): mfile = None else: raise Exception("Package: module '%s'not found" % (localname,)) print("__mod_create( %s ): Result: F=%s , P=%s" % (localname, mfile, mpath)) mod = new_module( modname, path=mpath, file=mfile ) self.__modules[ modname ] = mod setattr( modparent, localfile, mod) mod.__builtins__ = self.__builtins self.__mod_refresh( mod ) return mod def exports(self): return dict(self.__exports) def modules(self): return dict(self.__modules) def reload(self): for modname in list(self.__modules.keys()): mod = self.__modules[ modname ] self.__mod_refresh( mod ) self.__update_classes( modname ) files = os.listdir( self.__path ) for fn in files: if (fn.endswith(".py")): if not fn[:-3] in self.__modules: self.__mod_create( fn[:-3] ) def __update_classes(self, modname): for o in gc.get_objects(): if (isinstance( o, object )): if o.__class__.__module__ == modname: c = getattr( self.__modules[modname], o.__class__.__name__, None ) if not c is None: try: o.__class__ = c except Exception as ex: print("__update_classes(): Exception: %s" % (ex,)) def __mod_import(self,name,globals=None,locals=None,fromlist=(),level=0): print("import(%s,%s,%s,%s,%s)" % (name,"...","...",fromlist,level)) bname = name.split(".")[0] if (name in self.__allowed_modules): mod = importlib.import_module( name ) self.__modules[ name ] = mod bmod = sys.modules[ bname ] else: mod = self.__mod_create( name ) if bname == name: bmod = mod else: bmod = self.__modules[ "%s.%s" % (self.__modpath,bname) ] if (not fromlist is None) and (len(fromlist) > 0): return mod return bmod def __mod_refresh(self, mod): if not hasattr(mod, "__file__"): return print("__mod_refresh: %s [%s]" % (mod.__name__,mod.__file__)) if not os.path.exists( mod.__file__ ): del self.__modules[ mod.__name__ ] return f = open(mod.__file__, "r") src = f.read() f.close() co = compile( src, mod.__file__, "exec" ) mod.Templates = self.__templates exec( co, mod.__dict__ ) def __export(self, name, o, glob=False): self.__exports[ name ] = o if glob: self.__pm.export( name, o ) def __getattr__(self, name): if name in self.__modules: return self.__modules[ name ] if name in self.__exports: return self.__exports[ name ] raise AttributeError("%s not found in %s" % (name,self)) class PackageManager: def __init__(self, path ): self.__path = os.path.abspath( path ) self.__packagesmod = new_module( "packages" ) self.__packages = {} self.__exports = {} print("PackageManager loads from %s" % (self.__path,)) self.__load() def loadPackageFromPath(self,path, name = None): log("PackageManager: manually load Package from path {0}".format(path)) if name is None: name = os.path.basename(path) p = Package( self, path, name) self.__add( name, p ) def __load(self): plist = os.listdir( self.__path ) for pname in plist: ppath = "%s/%s" % (self.__path,pname) if (os.path.isdir(ppath)): print("PackageManager loads %s" % (pname,)) p = Package( self, ppath, pname ) self.__add( pname, p ) def __add(self,name,package): self.__packages[ name ] = package setattr( self.__packagesmod, name, package.module() ) def export(self, name, o): self.__exports[ name ] = o def imp(self, modname): if modname in self.__exports: return self.__exports[ modname ] return None def list_exports(self): return list( self.__exports.keys() ) def exports(self): return self.__exports def packages(self): return self.__packages def __getattr__(self, name): if name in self.__packages: return self.__packages[ name ] raise AttributeError("%s not found in %s" % (name,self))