Changes in sasmodels/custom/__init__.py [0f48f1e:d321747] in sasmodels
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/custom/__init__.py
r0f48f1e rd321747 12 12 import sys 13 13 import os 14 from os.path import basename, splitext 14 from os.path import basename, splitext, join as joinpath, exists, dirname 15 15 16 16 try: … … 18 18 from importlib.util import spec_from_file_location, module_from_spec # type: ignore 19 19 def load_module_from_path(fullname, path): 20 # type: (str, str) -> "module" 20 21 """load module from *path* as *fullname*""" 21 22 spec = spec_from_file_location(fullname, os.path.expanduser(path)) … … 27 28 import imp 28 29 def load_module_from_path(fullname, path): 30 # type: (str, str) -> "module" 29 31 """load module from *path* as *fullname*""" 30 32 # Clear out old definitions, if any … … 37 39 return module 38 40 41 _MODULE_CACHE = {} # type: Dict[str, Tuple("module", int)] 42 _MODULE_DEPENDS = {} # type: Dict[str, List[str]] 43 _MODULE_DEPENDS_STACK = [] # type: List[str] 39 44 def load_custom_kernel_module(path): 45 # type: str -> "module" 40 46 """load SAS kernel from *path* as *sasmodels.custom.modelname*""" 41 47 # Pull off the last .ext if it exists; there may be others 42 48 name = basename(splitext(path)[0]) 43 # Placing the model in the 'sasmodels.custom' name space. 44 kernel_module = load_module_from_path('sasmodels.custom.'+name, 45 os.path.expanduser(path)) 46 return kernel_module 49 path = os.path.expanduser(path) 50 51 # Reload module if necessary. 52 if need_reload(path): 53 # Assume the module file is the only dependency 54 _MODULE_DEPENDS[path] = set([path]) 55 56 # Load the module while pushing it onto the dependency stack. If 57 # this triggers any submodules, then they will add their dependencies 58 # to this module as the "working_on" parent. Pop the stack when the 59 # module is loaded. 60 _MODULE_DEPENDS_STACK.append(path) 61 module = load_module_from_path('sasmodels.custom.'+name, path) 62 _MODULE_DEPENDS_STACK.pop() 63 64 # Include external C code in the dependencies. We are looking 65 # for module.source and assuming that it is a list of C source files 66 # relative to the module itself. Any files that do not exist, 67 # such as those in the standard libraries, will be ignored. 68 # TODO: look in builtin module path for standard c sources 69 # TODO: share code with generate.model_sources 70 c_sources = getattr(module, 'source', None) 71 if isinstance(c_sources, (list, tuple)): 72 _MODULE_DEPENDS[path].update(_find_sources(path, c_sources)) 73 74 # Cache the module, and tag it with the newest timestamp 75 timestamp = max(os.path.getmtime(f) for f in _MODULE_DEPENDS[path]) 76 _MODULE_CACHE[path] = module, timestamp 77 78 #print("loading", os.path.basename(path), _MODULE_CACHE[path][1], 79 # [os.path.basename(p) for p in _MODULE_DEPENDS[path]]) 80 81 # Add path and all its dependence to the parent module, if there is one. 82 if _MODULE_DEPENDS_STACK: 83 working_on = _MODULE_DEPENDS_STACK[-1] 84 _MODULE_DEPENDS[working_on].update(_MODULE_DEPENDS[path]) 85 86 return _MODULE_CACHE[path][0] 87 88 def need_reload(path): 89 # type: str -> bool 90 """ 91 Return True if any path dependencies have a timestamp newer than the time 92 when the path was most recently loaded. 93 """ 94 # TODO: fails if a dependency has a modification time in the future 95 # If the newest dependency has a time stamp in the future, then this 96 # will be recorded as the cached time. When a second dependency 97 # is updated to the current time stamp, it will still be considered 98 # older than the current build and the reload will not be triggered. 99 # Could instead treat all future times as 0 here and in the code above 100 # which records the newest timestamp. This will force a reload when 101 # the future time is reached, but other than that should perform 102 # correctly. Probably not worth the extra code... 103 _, cache_time = _MODULE_CACHE.get(path, (None, -1)) 104 depends = _MODULE_DEPENDS.get(path, [path]) 105 #print("reload", any(cache_time < os.path.getmtime(p) for p in depends)) 106 #for f in depends: print(">>> ", f, os.path.getmtime(f)) 107 return any(cache_time < os.path.getmtime(p) for p in depends) 108 109 def _find_sources(path, source_list): 110 # type: (str, List[str]) -> List[str] 111 """ 112 Return a list of the sources relative to base file; ignore any that 113 are not found. 114 """ 115 root = dirname(path) 116 found = [] 117 for source_name in source_list: 118 source_path = joinpath(root, source_name) 119 if exists(source_path): 120 found.append(source_path) 121 return found
Note: See TracChangeset
for help on using the changeset viewer.