Ticket #1301: turbokid_reload_and_filter.patch

File turbokid_reload_and_filter.patch, 7.9 kB (added by chrisz, 2 years ago)

TurboKid? patch for reload mechanism and i18n filter

  • kidsupport.py

    old new  
    3232class KidSupport(object): 
    3333    #XXX: Is itertools.count threadsafe? 
    3434    string_template_serial = itertools.count() 
    35  
     35 
    3636    def __init__(self, extra_vars_func=None, options=None): 
    3737        if options is None: 
    3838            options = dict() 
     
    4343        self.sitetemplate = None 
    4444        self.stname = options.get("kid.sitetemplate", None) 
    4545        self.compiled_templates = {} 
    46  
     46 
    4747    def load_template_string(self, template_string): 
    4848        assert isinstance(template_string, basestring) 
    4949        tempclass = kid.load_template( 
    50             template_string, 
     50            template_string, 
    5151            name = "KidTemplateFromString-%d" % self.string_template_serial.next() 
    5252            ).Template 
    5353        tempclass.serializer = self.serializer 
    5454        return tempclass 
    55  
     55 
    5656    def load_template(self, classname=None, template_string=None, loadingSite=False): 
    5757        """Searches for a template along the Python path. 
    58  
     58 
    5959        Template files must end in ".kid" and be in legitimate packages. 
    6060        If the templates are precompiled to ".pyc" files, you can 
    61         set the "kid.precompiled" option to 
     61        set the "kid.precompiled" option to 
    6262        just do a straight import of the template. 
    6363        """ 
    64  
     64 
    6565        if template_string is not None: 
    6666            return self.load_template_string(template_string) 
    6767        elif classname is None: 
     
    7373                self.load_template(self.stname, loadingSite=True) 
    7474                sys.modules["sitetemplate"] = sys.modules[self.stname] 
    7575                self.sitetemplate = sys.modules["sitetemplate"] 
    76  
     76 
    7777        divider = classname.rfind(".") 
    7878        if divider > -1: 
    7979            package = classname[0:divider] 
    8080            basename = classname[divider+1:] 
    8181        else: 
    8282            raise ValueError, "All templates must be in a package" 
    83  
    84         if not self.options.get("kid.precompiled", False): 
    85             tfile = pkg_resources.resource_filename(package, 
    86                                                     "%s.kid" % basename) 
     83 
     84        if self.options.get("kid.precompiled", False): 
     85            # Always use the precompiled template since this is what 
     86            # the config says. 
     87            mod = __import__(classname, dict(), dict(), [basename]) 
     88        else: 
     89            tfile = pkg_resources.resource_filename( 
     90                package, "%s.kid" % basename) 
    8791            ct = self.compiled_templates 
    8892            if sys.modules.has_key(classname) and ct.has_key(classname): 
    8993                # This means that in sys.modules there is already the compiled 
     
    9296                # In this case we may need to recompile because the template 
    9397                # itself or one of its bases could have been modified. 
    9498                tclass = sys.modules[classname].Template 
    95                 involved_modules = [classname] + _get_extended_modules(tclass) 
    96                 # Check the status of every involved module, if the module has 
    97                 # been modified remove it from sys.modules, update its mtime 
    98                 # and set to True the reload_template flag. 
    99                 reload_template = False 
    100                 for module in involved_modules: 
     99                ttime = ct[classname] 
     100                mtime = os.stat(sys.modules[classname].__file__).st_mtime 
     101                reload_template = mtime > ttime 
     102                if reload_template: 
     103                    ttime = mtime 
     104                # Check the status of all base moduls. 
     105                for module in _get_extended_modules(tclass): 
    101106                    mtime = os.stat(sys.modules[module].__file__).st_mtime 
    102                     if ct[module] != mtime: 
     107                    if mtime > ct[module]: 
     108                        # base template has changed 
    103109                        del sys.modules[module] 
    104110                        ct[module] = mtime 
    105111                        reload_template = True 
    106  
     112                    if mtime > ttime: 
     113                        # base module has changed 
     114                        reload_template = True 
     115                        ttime = mtime 
    107116                if reload_template: 
    108117                    # We need to recompile the template. 
    109118                    log.debug("Recompiling template for %s" % classname) 
    110                     # If the template module is still in sys.modules (this 
    111                     # means that the template has not been modified but one or 
    112                     # more of its base templates have been) remove it 
    113                     # otherwise Kid will not recompile the removed bases 
    114                     # templates giving us a NoneType error. 
    115                     if sys.modules.has_key(classname): 
    116                         del sys.modules[classname] 
    117                     mod = _compile_template(package, basename, 
    118                                             tfile, classname) 
     119                    del sys.modules[classname] 
     120                    ct[classname] = ttime 
     121                    mod = _compile_template( 
     122                        package, basename, tfile, classname) 
    119123                else: 
    120                     # No need to recompile the template or its bases, 
     124                    # No need to recompile the template or its bases, 
    121125                    # just reuse the existing modules. 
    122126                    mod = __import__(classname, dict(), dict(), [basename]) 
    123127            else: 
     
    127131                log.debug("Compiling template for %s" % classname) 
    128132                mod = _compile_template(package, basename, tfile, classname) 
    129133                tclass = mod.Template 
    130                 involved_modules = [classname] + _get_extended_modules(tclass) 
    131                 for module in involved_modules: 
    132                     ct[module] = os.stat(sys.modules[module].__file__).st_mtime 
    133         else: 
    134             # Always use the precompiled template since this is what 
    135             # the config says. 
    136             mod = __import__(classname, dict(), dict(), [basename]) 
     134                ttime = os.stat(sys.modules[classname].__file__).st_mtime 
     135                for module in _get_extended_modules(tclass): 
     136                    mtime = os.stat(sys.modules[module].__file__).st_mtime 
     137                    ct[module] = mtime 
     138                    if mtime > ttime: 
     139                        ttime = mtime 
     140                # Store max of mtimes of template and all of its bases 
     141                ct[classname] = ttime 
    137142 
    138143        tempclass = mod.Template 
    139144        tempclass.serializer = self.serializer 
     
    141146 
    142147    def render(self, info, format="html", fragment=False, template=None): 
    143148        """Renders data in the desired format. 
    144  
     149 
    145150        @param info: the data itself 
    146151        @type info: dict 
    147152        @param format: "html", "xml" or "json" 
     
    169174        if options.get("kid.assume_encoding", "utf-8"): 
    170175            t.assume_encoding = options.get("kid.assume_encoding", "utf-8") 
    171176        if options.get("kid.i18n.run_template_filter", False): 
    172             t._filters+=[options.get("kid.i18n_filter")] 
    173  
     177            filter = options.get("kid.i18n_filter") 
     178            if callable(filter) and filter not in t._filters: 
     179                t._filters.append(filter) 
     180 
    174181        return t.serialize(encoding=self.defaultencoding, output=format, fragment=fragment) 
    175182 
    176183    def transform(self, info, template): 
     
    182189        if self.get_extra_vars: 
    183190            data.update(self.get_extra_vars()) 
    184191        data.update(info) 
    185  
     192 
    186193        t = tclass(**data) 
    187  
     194 
    188195        options = self.options 
    189196        if options.get("kid.i18n.run_template_filter", False): 
    190             t._filters+=[options.get("kid.i18n_filter")] 
     197            filter = options.get("kid.i18n_filter") 
     198            if callable(filter) and filter not in t._filters: 
     199                t._filters.append(filter) 
     200 
    191201        return ElementStream(t.transform()).expand() 
    192