595 {key%format}. |
595 {key%format}. |
596 |
596 |
597 filter uses function to transform value. syntax is |
597 filter uses function to transform value. syntax is |
598 {key|filter1|filter2|...}.''' |
598 {key|filter1|filter2|...}.''' |
599 |
599 |
600 def __init__(self, loader, filters=None, defaults=None, resources=None, |
600 def __init__(self, loader, filters=None, defaults=None, resources=None): |
601 aliases=()): |
|
602 self._loader = loader |
601 self._loader = loader |
603 if filters is None: |
602 if filters is None: |
604 filters = {} |
603 filters = {} |
605 self._filters = filters |
604 self._filters = filters |
606 self._funcs = templatefuncs.funcs # make this a parameter if needed |
605 self._funcs = templatefuncs.funcs # make this a parameter if needed |
608 defaults = {} |
607 defaults = {} |
609 if resources is None: |
608 if resources is None: |
610 resources = nullresourcemapper() |
609 resources = nullresourcemapper() |
611 self._defaults = defaults |
610 self._defaults = defaults |
612 self._resources = resources |
611 self._resources = resources |
613 self._aliasmap = _aliasrules.buildmap(aliases) |
|
614 self._cache = {} # key: (func, data) |
612 self._cache = {} # key: (func, data) |
615 self._tmplcache = {} # literal template: (func, data) |
613 self._tmplcache = {} # literal template: (func, data) |
616 |
614 |
617 def overlaymap(self, origmapping, newmapping): |
615 def overlaymap(self, origmapping, newmapping): |
618 """Create combined mapping from the original mapping and partial |
616 """Create combined mapping from the original mapping and partial |
663 return v |
661 return v |
664 |
662 |
665 def _load(self, t): |
663 def _load(self, t): |
666 '''load, parse, and cache a template''' |
664 '''load, parse, and cache a template''' |
667 if t not in self._cache: |
665 if t not in self._cache: |
668 x = parse(self._loader(t)) |
666 x = self._loader(t) |
669 if self._aliasmap: |
|
670 x = _aliasrules.expand(self._aliasmap, x) |
|
671 # put poison to cut recursion while compiling 't' |
667 # put poison to cut recursion while compiling 't' |
672 self._cache[t] = (_runrecursivesymbol, t) |
668 self._cache[t] = (_runrecursivesymbol, t) |
673 try: |
669 try: |
674 self._cache[t] = compileexp(x, self, methods) |
670 self._cache[t] = compileexp(x, self, methods) |
675 except: # re-raises |
671 except: # re-raises |
806 self._map = {} |
802 self._map = {} |
807 self._filters = templatefilters.filters.copy() |
803 self._filters = templatefilters.filters.copy() |
808 self._filters.update(filters) |
804 self._filters.update(filters) |
809 self.defaults = defaults |
805 self.defaults = defaults |
810 self._resources = resources |
806 self._resources = resources |
811 self._aliases = aliases |
807 self._aliasmap = _aliasrules.buildmap(aliases) |
812 self._minchunk, self._maxchunk = minchunk, maxchunk |
808 self._minchunk, self._maxchunk = minchunk, maxchunk |
813 |
809 |
814 @classmethod |
810 @classmethod |
815 def frommapfile(cls, mapfile, filters=None, defaults=None, resources=None, |
811 def frommapfile(cls, mapfile, filters=None, defaults=None, resources=None, |
816 cache=None, minchunk=1024, maxchunk=65536): |
812 cache=None, minchunk=1024, maxchunk=65536): |
817 """Create templater from the specified map file""" |
813 """Create templater from the specified map file""" |
818 t = cls(filters, defaults, resources, cache, [], minchunk, maxchunk) |
814 t = cls(filters, defaults, resources, cache, [], minchunk, maxchunk) |
819 cache, tmap, aliases = _readmapfile(mapfile) |
815 cache, tmap, aliases = _readmapfile(mapfile) |
820 t.cache.update(cache) |
816 t.cache.update(cache) |
821 t._map = tmap |
817 t._map = tmap |
822 t._aliases = aliases |
818 t._aliasmap = _aliasrules.buildmap(aliases) |
823 return t |
819 return t |
824 |
820 |
825 def __contains__(self, key): |
821 def __contains__(self, key): |
826 return key in self.cache or key in self._map |
822 return key in self.cache or key in self._map |
827 |
823 |
828 def load(self, t): |
824 def load(self, t): |
829 '''Get the template for the given template name. Use a local cache.''' |
825 """Get parsed tree for the given template name. Use a local cache.""" |
830 if t not in self.cache: |
826 if t not in self.cache: |
831 try: |
827 try: |
832 self.cache[t] = util.readfile(self._map[t]) |
828 self.cache[t] = util.readfile(self._map[t]) |
833 except KeyError as inst: |
829 except KeyError as inst: |
834 raise templateutil.TemplateNotFound( |
830 raise templateutil.TemplateNotFound( |
836 except IOError as inst: |
832 except IOError as inst: |
837 reason = (_('template file %s: %s') |
833 reason = (_('template file %s: %s') |
838 % (self._map[t], |
834 % (self._map[t], |
839 stringutil.forcebytestr(inst.args[1]))) |
835 stringutil.forcebytestr(inst.args[1]))) |
840 raise IOError(inst.args[0], encoding.strfromlocal(reason)) |
836 raise IOError(inst.args[0], encoding.strfromlocal(reason)) |
841 return self.cache[t] |
837 return self._parse(self.cache[t]) |
|
838 |
|
839 def _parse(self, tmpl): |
|
840 x = parse(tmpl) |
|
841 if self._aliasmap: |
|
842 x = _aliasrules.expand(self._aliasmap, x) |
|
843 return x |
842 |
844 |
843 def renderdefault(self, mapping): |
845 def renderdefault(self, mapping): |
844 """Render the default unnamed template and return result as string""" |
846 """Render the default unnamed template and return result as string""" |
845 return self.render('', mapping) |
847 return self.render('', mapping) |
846 |
848 |
849 return b''.join(self.generate(t, mapping)) |
851 return b''.join(self.generate(t, mapping)) |
850 |
852 |
851 def generate(self, t, mapping): |
853 def generate(self, t, mapping): |
852 """Return a generator that renders the specified named template and |
854 """Return a generator that renders the specified named template and |
853 yields chunks""" |
855 yields chunks""" |
854 proc = engine(self.load, self._filters, self.defaults, self._resources, |
856 proc = engine(self.load, self._filters, self.defaults, self._resources) |
855 self._aliases) |
|
856 stream = proc.process(t, mapping) |
857 stream = proc.process(t, mapping) |
857 if self._minchunk: |
858 if self._minchunk: |
858 stream = util.increasingchunks(stream, min=self._minchunk, |
859 stream = util.increasingchunks(stream, min=self._minchunk, |
859 max=self._maxchunk) |
860 max=self._maxchunk) |
860 return stream |
861 return stream |