Changeset d321747 in sasmodels for sasmodels/custom/__init__.py


Ignore:
Timestamp:
Oct 1, 2018 7:20:17 PM (6 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
c11d09f
Parents:
a5bcd61
Message:

sasview only updates models when code changes; now detects changes to c files

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/custom/__init__.py

    r91bd550 rd321747  
    1212import sys 
    1313import os 
    14 from os.path import basename, splitext 
     14from os.path import basename, splitext, join as joinpath, exists, dirname 
    1515 
    1616try: 
     
    1818    from importlib.util import spec_from_file_location, module_from_spec  # type: ignore 
    1919    def load_module_from_path(fullname, path): 
     20        # type: (str, str) -> "module" 
    2021        """load module from *path* as *fullname*""" 
    2122        spec = spec_from_file_location(fullname, os.path.expanduser(path)) 
     
    2728    import imp 
    2829    def load_module_from_path(fullname, path): 
     30        # type: (str, str) -> "module" 
    2931        """load module from *path* as *fullname*""" 
    3032        # Clear out old definitions, if any 
     
    3739        return module 
    3840 
    39 _MODULE_CACHE = {} 
    40 _MODULE_DEPENDS = {} 
    41 _MODULE_DEPENDS_STACK = [] 
     41_MODULE_CACHE = {} # type: Dict[str, Tuple("module", int)] 
     42_MODULE_DEPENDS = {} # type: Dict[str, List[str]] 
     43_MODULE_DEPENDS_STACK = [] # type: List[str] 
    4244def load_custom_kernel_module(path): 
     45    # type: str -> "module" 
    4346    """load SAS kernel from *path* as *sasmodels.custom.modelname*""" 
    4447    # Pull off the last .ext if it exists; there may be others 
     
    4649    path = os.path.expanduser(path) 
    4750 
    48     # reload module if necessary 
     51    # Reload module if necessary. 
    4952    if need_reload(path): 
    50         # Push to the next dependency level 
    51         _MODULE_DEPENDS_STACK.append(path) 
     53        # Assume the module file is the only dependency 
    5254        _MODULE_DEPENDS[path] = set([path]) 
    5355 
    54         # Load module into the 'sasmodels.custom' name space. 
    55         # If this triggers any submodule loads then they will be added 
    56         # as dependencies below when _MODULE_DEPENDS_STACK is not empty. 
     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) 
    5761        module = load_module_from_path('sasmodels.custom.'+name, path) 
    58  
    59         # Pop the dependency level 
    6062        _MODULE_DEPENDS_STACK.pop() 
    6163 
    62         # TODO: include external C code in the dependencies 
    63         # If we had the model info structure we could do the following: 
    64         #    _MODEL_DEPENDS[path].extend(generate.model_sources(info)) 
    65         # but at this point all we have is the module.  Don't want to 
    66         # repeat the logic in modelinfo.make_model_info. 
     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)) 
    6773 
    68         # Cache the module with the newest timestamp 
     74        # Cache the module, and tag it with the newest timestamp 
    6975        timestamp = max(os.path.getmtime(f) for f in _MODULE_DEPENDS[path]) 
    7076        _MODULE_CACHE[path] = module, timestamp 
     
    7379        #    [os.path.basename(p) for p in _MODULE_DEPENDS[path]]) 
    7480 
     81    # Add path and all its dependence to the parent module, if there is one. 
    7582    if _MODULE_DEPENDS_STACK: 
    76         # Add child and all its dependence to the parent module 
    7783        working_on = _MODULE_DEPENDS_STACK[-1] 
    7884        _MODULE_DEPENDS[working_on].update(_MODULE_DEPENDS[path]) 
     
    8187 
    8288def 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    """ 
    8394    # TODO: fails if a dependency has a modification time in the future 
    8495    # If the newest dependency has a time stamp in the future, then this 
     
    92103    _, cache_time = _MODULE_CACHE.get(path, (None, -1)) 
    93104    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)) 
    94107    return any(cache_time < os.path.getmtime(p) for p in depends) 
     108 
     109def _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.