templater: move hybrid class and functions to templateutil module
And make _hybrid and _mappable classes public. _showlist() is still marked
as private since it's weird and third-party codes shouldn't depend on it.
--- a/hgext/lfs/__init__.py Thu Mar 08 23:10:46 2018 +0900
+++ b/hgext/lfs/__init__.py Thu Mar 08 23:15:09 2018 +0900
@@ -143,7 +143,7 @@
registrar,
revlog,
scmutil,
- templatekw,
+ templateutil,
upgrade,
util,
vfs as vfsmod,
@@ -375,12 +375,12 @@
makemap = lambda v: {
'file': v,
'lfsoid': pointers[v].oid() if pointers[v] else None,
- 'lfspointer': templatekw.hybriddict(pointer(v)),
+ 'lfspointer': templateutil.hybriddict(pointer(v)),
}
# TODO: make the separator ', '?
- f = templatekw._showlist('lfs_file', files, templ, mapping)
- return templatekw._hybrid(f, files, makemap, pycompat.identity)
+ f = templateutil._showlist('lfs_file', files, templ, mapping)
+ return templateutil.hybrid(f, files, makemap, pycompat.identity)
@command('debuglfsupload',
[('r', 'rev', [], _('upload large files introduced by REV'))])
--- a/hgext/remotenames.py Thu Mar 08 23:10:46 2018 +0900
+++ b/hgext/remotenames.py Thu Mar 08 23:15:09 2018 +0900
@@ -35,7 +35,7 @@
registrar,
revsetlang,
smartset,
- templatekw,
+ templateutil,
)
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
@@ -237,8 +237,8 @@
if 'remotebranches' in repo.names:
remotenames += repo.names['remotebranches'].names(repo, ctx.node())
- return templatekw.compatlist(context, mapping, 'remotename', remotenames,
- plural='remotenames')
+ return templateutil.compatlist(context, mapping, 'remotename', remotenames,
+ plural='remotenames')
@templatekeyword('remotebookmarks', requires={'repo', 'ctx', 'templ'})
def remotebookmarkskw(context, mapping):
@@ -250,8 +250,8 @@
if 'remotebookmarks' in repo.names:
remotebmarks = repo.names['remotebookmarks'].names(repo, ctx.node())
- return templatekw.compatlist(context, mapping, 'remotebookmark',
- remotebmarks, plural='remotebookmarks')
+ return templateutil.compatlist(context, mapping, 'remotebookmark',
+ remotebmarks, plural='remotebookmarks')
@templatekeyword('remotebranches', requires={'repo', 'ctx', 'templ'})
def remotebrancheskw(context, mapping):
@@ -263,8 +263,8 @@
if 'remotebranches' in repo.names:
remotebranches = repo.names['remotebranches'].names(repo, ctx.node())
- return templatekw.compatlist(context, mapping, 'remotebranch',
- remotebranches, plural='remotebranches')
+ return templateutil.compatlist(context, mapping, 'remotebranch',
+ remotebranches, plural='remotebranches')
def _revsetutil(repo, subset, x, rtypes):
"""utility function to return a set of revs based on the rtypes"""
--- a/mercurial/formatter.py Thu Mar 08 23:10:46 2018 +0900
+++ b/mercurial/formatter.py Thu Mar 08 23:15:09 2018 +0900
@@ -359,14 +359,15 @@
data = util.sortdict(_iteritems(data))
def f():
yield _plainconverter.formatdict(data, key, value, fmt, sep)
- return templatekw.hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
+ return templateutil.hybriddict(data, key=key, value=value, fmt=fmt,
+ gen=f)
@staticmethod
def formatlist(data, name, fmt, sep):
'''build object that can be evaluated as either plain string or list'''
data = list(data)
def f():
yield _plainconverter.formatlist(data, name, fmt, sep)
- return templatekw.hybridlist(data, name=name, fmt=fmt, gen=f)
+ return templateutil.hybridlist(data, name=name, fmt=fmt, gen=f)
class templateformatter(baseformatter):
def __init__(self, ui, out, topic, opts):
--- a/mercurial/templatefilters.py Thu Mar 08 23:10:46 2018 +0900
+++ b/mercurial/templatefilters.py Thu Mar 08 23:15:09 2018 +0900
@@ -17,7 +17,6 @@
node,
pycompat,
registrar,
- templatekw,
templateutil,
url,
util,
@@ -366,7 +365,7 @@
@templatefilter('splitlines')
def splitlines(text):
"""Any text. Split text into a list of lines."""
- return templatekw.hybridlist(text.splitlines(), name='line')
+ return templateutil.hybridlist(text.splitlines(), name='line')
@templatefilter('stringescape')
def stringescape(text):
--- a/mercurial/templatekw.py Thu Mar 08 23:10:46 2018 +0900
+++ b/mercurial/templatekw.py Thu Mar 08 23:15:09 2018 +0900
@@ -23,156 +23,24 @@
pycompat,
registrar,
scmutil,
+ templateutil,
util,
)
-class _hybrid(object):
- """Wrapper for list or dict to support legacy template
-
- This class allows us to handle both:
- - "{files}" (legacy command-line-specific list hack) and
- - "{files % '{file}\n'}" (hgweb-style with inlining and function support)
- and to access raw values:
- - "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
- - "{get(extras, key)}"
- - "{files|json}"
- """
-
- def __init__(self, gen, values, makemap, joinfmt, keytype=None):
- if gen is not None:
- self.gen = gen # generator or function returning generator
- self._values = values
- self._makemap = makemap
- self.joinfmt = joinfmt
- self.keytype = keytype # hint for 'x in y' where type(x) is unresolved
- def gen(self):
- """Default generator to stringify this as {join(self, ' ')}"""
- for i, x in enumerate(self._values):
- if i > 0:
- yield ' '
- yield self.joinfmt(x)
- def itermaps(self):
- makemap = self._makemap
- for x in self._values:
- yield makemap(x)
- def __contains__(self, x):
- return x in self._values
- def __getitem__(self, key):
- return self._values[key]
- def __len__(self):
- return len(self._values)
- def __iter__(self):
- return iter(self._values)
- def __getattr__(self, name):
- if name not in (r'get', r'items', r'iteritems', r'iterkeys',
- r'itervalues', r'keys', r'values'):
- raise AttributeError(name)
- return getattr(self._values, name)
-
-class _mappable(object):
- """Wrapper for non-list/dict object to support map operation
-
- This class allows us to handle both:
- - "{manifest}"
- - "{manifest % '{rev}:{node}'}"
- - "{manifest.rev}"
-
- Unlike a _hybrid, this does not simulate the behavior of the underling
- value. Use unwrapvalue() or unwraphybrid() to obtain the inner object.
- """
-
- def __init__(self, gen, key, value, makemap):
- if gen is not None:
- self.gen = gen # generator or function returning generator
- self._key = key
- self._value = value # may be generator of strings
- self._makemap = makemap
-
- def gen(self):
- yield pycompat.bytestr(self._value)
-
- def tomap(self):
- return self._makemap(self._key)
-
- def itermaps(self):
- yield self.tomap()
-
-def hybriddict(data, key='key', value='value', fmt=None, gen=None):
- """Wrap data to support both dict-like and string-like operations"""
- prefmt = pycompat.identity
- if fmt is None:
- fmt = '%s=%s'
- prefmt = pycompat.bytestr
- return _hybrid(gen, data, lambda k: {key: k, value: data[k]},
- lambda k: fmt % (prefmt(k), prefmt(data[k])))
-
-def hybridlist(data, name, fmt=None, gen=None):
- """Wrap data to support both list-like and string-like operations"""
- prefmt = pycompat.identity
- if fmt is None:
- fmt = '%s'
- prefmt = pycompat.bytestr
- return _hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x))
-
-def unwraphybrid(thing):
- """Return an object which can be stringified possibly by using a legacy
- template"""
- gen = getattr(thing, 'gen', None)
- if gen is None:
- return thing
- if callable(gen):
- return gen()
- return gen
-
-def unwrapvalue(thing):
- """Move the inner value object out of the wrapper"""
- if not util.safehasattr(thing, '_value'):
- return thing
- return thing._value
-
-def wraphybridvalue(container, key, value):
- """Wrap an element of hybrid container to be mappable
-
- The key is passed to the makemap function of the given container, which
- should be an item generated by iter(container).
- """
- makemap = getattr(container, '_makemap', None)
- if makemap is None:
- return value
- if util.safehasattr(value, '_makemap'):
- # a nested hybrid list/dict, which has its own way of map operation
- return value
- return _mappable(None, key, value, makemap)
-
-def compatdict(context, mapping, name, data, key='key', value='value',
- fmt=None, plural=None, separator=' '):
- """Wrap data like hybriddict(), but also supports old-style list template
-
- This exists for backward compatibility with the old-style template. Use
- hybriddict() for new template keywords.
- """
- c = [{key: k, value: v} for k, v in data.iteritems()]
- t = context.resource(mapping, 'templ')
- f = _showlist(name, c, t, mapping, plural, separator)
- return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
-
-def compatlist(context, mapping, name, data, element=None, fmt=None,
- plural=None, separator=' '):
- """Wrap data like hybridlist(), but also supports old-style list template
-
- This exists for backward compatibility with the old-style template. Use
- hybridlist() for new template keywords.
- """
- t = context.resource(mapping, 'templ')
- f = _showlist(name, data, t, mapping, plural, separator)
- return hybridlist(data, name=element or name, fmt=fmt, gen=f)
+_hybrid = templateutil.hybrid
+_mappable = templateutil.mappable
+_showlist = templateutil._showlist
+hybriddict = templateutil.hybriddict
+hybridlist = templateutil.hybridlist
+compatdict = templateutil.compatdict
+compatlist = templateutil.compatlist
def showdict(name, data, mapping, plural=None, key='key', value='value',
fmt=None, separator=' '):
ui = mapping.get('ui')
if ui:
- ui.deprecwarn("templatekw.showdict() is deprecated, use compatdict()",
- '4.6')
+ ui.deprecwarn("templatekw.showdict() is deprecated, use "
+ "templateutil.compatdict()", '4.6')
c = [{key: k, value: v} for k, v in data.iteritems()]
f = _showlist(name, c, mapping['templ'], mapping, plural, separator)
return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
@@ -180,82 +48,13 @@
def showlist(name, values, mapping, plural=None, element=None, separator=' '):
ui = mapping.get('ui')
if ui:
- ui.deprecwarn("templatekw.showlist() is deprecated, use compatlist()",
- '4.6')
+ ui.deprecwarn("templatekw.showlist() is deprecated, use "
+ "templateutil.compatlist()", '4.6')
if not element:
element = name
f = _showlist(name, values, mapping['templ'], mapping, plural, separator)
return hybridlist(values, name=element, gen=f)
-def _showlist(name, values, templ, mapping, plural=None, separator=' '):
- '''expand set of values.
- name is name of key in template map.
- values is list of strings or dicts.
- plural is plural of name, if not simply name + 's'.
- separator is used to join values as a string
-
- expansion works like this, given name 'foo'.
-
- if values is empty, expand 'no_foos'.
-
- if 'foo' not in template map, return values as a string,
- joined by 'separator'.
-
- expand 'start_foos'.
-
- for each value, expand 'foo'. if 'last_foo' in template
- map, expand it instead of 'foo' for last key.
-
- expand 'end_foos'.
- '''
- strmapping = pycompat.strkwargs(mapping)
- if not plural:
- plural = name + 's'
- if not values:
- noname = 'no_' + plural
- if noname in templ:
- yield templ(noname, **strmapping)
- return
- if name not in templ:
- if isinstance(values[0], bytes):
- yield separator.join(values)
- else:
- for v in values:
- r = dict(v)
- r.update(mapping)
- yield r
- return
- startname = 'start_' + plural
- if startname in templ:
- yield templ(startname, **strmapping)
- vmapping = mapping.copy()
- def one(v, tag=name):
- try:
- vmapping.update(v)
- # Python 2 raises ValueError if the type of v is wrong. Python
- # 3 raises TypeError.
- except (AttributeError, TypeError, ValueError):
- try:
- # Python 2 raises ValueError trying to destructure an e.g.
- # bytes. Python 3 raises TypeError.
- for a, b in v:
- vmapping[a] = b
- except (TypeError, ValueError):
- vmapping[name] = v
- return templ(tag, **pycompat.strkwargs(vmapping))
- lastname = 'last_' + name
- if lastname in templ:
- last = values.pop()
- else:
- last = None
- for v in values:
- yield one(v)
- if last is not None:
- yield one(last, tag=lastname)
- endname = 'end_' + plural
- if endname in templ:
- yield templ(endname, **strmapping)
-
def getlatesttags(context, mapping, pattern=None):
'''return date, distance and name for the latest tag of rev'''
repo = context.resource(mapping, 'repo')
--- a/mercurial/templater.py Thu Mar 08 23:10:46 2018 +0900
+++ b/mercurial/templater.py Thu Mar 08 23:15:09 2018 +0900
@@ -498,7 +498,7 @@
data.update((k, evalfuncarg(context, mapping, v))
for k, v in args['kwargs'].iteritems())
- return templatekw.hybriddict(data)
+ return templateutil.hybriddict(data)
@templatefunc('diff([includepattern [, excludepattern]])')
def diff(context, mapping, args):
@@ -548,7 +548,7 @@
ctx = context.resource(mapping, 'ctx')
m = ctx.match([raw])
files = list(ctx.matches(m))
- return templatekw.compatlist(context, mapping, "file", files)
+ return templateutil.compatlist(context, mapping, "file", files)
@templatefunc('fill(text[, width[, initialident[, hangindent]]])')
def fill(context, mapping, args):
@@ -718,7 +718,7 @@
# TODO: perhaps this should be evalfuncarg(), but it can't because hgweb
# abuses generator as a keyword that returns a list of dicts.
joinset = evalrawexp(context, mapping, args[0])
- joinset = templatekw.unwrapvalue(joinset)
+ joinset = templateutil.unwrapvalue(joinset)
joinfmt = getattr(joinset, 'joinfmt', pycompat.identity)
joiner = " "
if len(args) > 1:
@@ -808,7 +808,7 @@
except (TypeError, ValueError):
# i18n: "max" is a keyword
raise error.ParseError(_("max first argument should be an iterable"))
- return templatekw.wraphybridvalue(iterable, x, x)
+ return templateutil.wraphybridvalue(iterable, x, x)
@templatefunc('min(iterable)')
def min_(context, mapping, args, **kwargs):
@@ -823,7 +823,7 @@
except (TypeError, ValueError):
# i18n: "min" is a keyword
raise error.ParseError(_("min first argument should be an iterable"))
- return templatekw.wraphybridvalue(iterable, x, x)
+ return templateutil.wraphybridvalue(iterable, x, x)
@templatefunc('mod(a, b)')
def mod(context, mapping, args):
@@ -847,7 +847,7 @@
try:
data = obsutil.markersoperations(markers)
- return templatekw.hybridlist(data, name='operation')
+ return templateutil.hybridlist(data, name='operation')
except (TypeError, KeyError):
# i18n: "obsfateoperations" is a keyword
errmsg = _("obsfateoperations first argument should be an iterable")
@@ -864,7 +864,7 @@
try:
data = obsutil.markersdates(markers)
- return templatekw.hybridlist(data, name='date', fmt='%d %d')
+ return templateutil.hybridlist(data, name='date', fmt='%d %d')
except (TypeError, KeyError):
# i18n: "obsfatedate" is a keyword
errmsg = _("obsfatedate first argument should be an iterable")
@@ -881,7 +881,7 @@
try:
data = obsutil.markersusers(markers)
- return templatekw.hybridlist(data, name='user')
+ return templateutil.hybridlist(data, name='user')
except (TypeError, KeyError, ValueError):
# i18n: "obsfateusers" is a keyword
msg = _("obsfateusers first argument should be an iterable of "
@@ -1120,7 +1120,7 @@
def _flatten(thing):
'''yield a single stream from a possibly nested set of iterators'''
- thing = templatekw.unwraphybrid(thing)
+ thing = templateutil.unwraphybrid(thing)
if isinstance(thing, bytes):
yield thing
elif isinstance(thing, str):
@@ -1134,7 +1134,7 @@
yield pycompat.bytestr(thing)
else:
for i in thing:
- i = templatekw.unwraphybrid(i)
+ i = templateutil.unwraphybrid(i)
if isinstance(i, bytes):
yield i
elif i is None:
--- a/mercurial/templateutil.py Thu Mar 08 23:10:46 2018 +0900
+++ b/mercurial/templateutil.py Thu Mar 08 23:15:09 2018 +0900
@@ -13,7 +13,6 @@
from . import (
error,
pycompat,
- templatekw,
util,
)
@@ -23,9 +22,219 @@
class TemplateNotFound(error.Abort):
pass
+class hybrid(object):
+ """Wrapper for list or dict to support legacy template
+
+ This class allows us to handle both:
+ - "{files}" (legacy command-line-specific list hack) and
+ - "{files % '{file}\n'}" (hgweb-style with inlining and function support)
+ and to access raw values:
+ - "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
+ - "{get(extras, key)}"
+ - "{files|json}"
+ """
+
+ def __init__(self, gen, values, makemap, joinfmt, keytype=None):
+ if gen is not None:
+ self.gen = gen # generator or function returning generator
+ self._values = values
+ self._makemap = makemap
+ self.joinfmt = joinfmt
+ self.keytype = keytype # hint for 'x in y' where type(x) is unresolved
+ def gen(self):
+ """Default generator to stringify this as {join(self, ' ')}"""
+ for i, x in enumerate(self._values):
+ if i > 0:
+ yield ' '
+ yield self.joinfmt(x)
+ def itermaps(self):
+ makemap = self._makemap
+ for x in self._values:
+ yield makemap(x)
+ def __contains__(self, x):
+ return x in self._values
+ def __getitem__(self, key):
+ return self._values[key]
+ def __len__(self):
+ return len(self._values)
+ def __iter__(self):
+ return iter(self._values)
+ def __getattr__(self, name):
+ if name not in (r'get', r'items', r'iteritems', r'iterkeys',
+ r'itervalues', r'keys', r'values'):
+ raise AttributeError(name)
+ return getattr(self._values, name)
+
+class mappable(object):
+ """Wrapper for non-list/dict object to support map operation
+
+ This class allows us to handle both:
+ - "{manifest}"
+ - "{manifest % '{rev}:{node}'}"
+ - "{manifest.rev}"
+
+ Unlike a hybrid, this does not simulate the behavior of the underling
+ value. Use unwrapvalue() or unwraphybrid() to obtain the inner object.
+ """
+
+ def __init__(self, gen, key, value, makemap):
+ if gen is not None:
+ self.gen = gen # generator or function returning generator
+ self._key = key
+ self._value = value # may be generator of strings
+ self._makemap = makemap
+
+ def gen(self):
+ yield pycompat.bytestr(self._value)
+
+ def tomap(self):
+ return self._makemap(self._key)
+
+ def itermaps(self):
+ yield self.tomap()
+
+def hybriddict(data, key='key', value='value', fmt=None, gen=None):
+ """Wrap data to support both dict-like and string-like operations"""
+ prefmt = pycompat.identity
+ if fmt is None:
+ fmt = '%s=%s'
+ prefmt = pycompat.bytestr
+ return hybrid(gen, data, lambda k: {key: k, value: data[k]},
+ lambda k: fmt % (prefmt(k), prefmt(data[k])))
+
+def hybridlist(data, name, fmt=None, gen=None):
+ """Wrap data to support both list-like and string-like operations"""
+ prefmt = pycompat.identity
+ if fmt is None:
+ fmt = '%s'
+ prefmt = pycompat.bytestr
+ return hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x))
+
+def unwraphybrid(thing):
+ """Return an object which can be stringified possibly by using a legacy
+ template"""
+ gen = getattr(thing, 'gen', None)
+ if gen is None:
+ return thing
+ if callable(gen):
+ return gen()
+ return gen
+
+def unwrapvalue(thing):
+ """Move the inner value object out of the wrapper"""
+ if not util.safehasattr(thing, '_value'):
+ return thing
+ return thing._value
+
+def wraphybridvalue(container, key, value):
+ """Wrap an element of hybrid container to be mappable
+
+ The key is passed to the makemap function of the given container, which
+ should be an item generated by iter(container).
+ """
+ makemap = getattr(container, '_makemap', None)
+ if makemap is None:
+ return value
+ if util.safehasattr(value, '_makemap'):
+ # a nested hybrid list/dict, which has its own way of map operation
+ return value
+ return mappable(None, key, value, makemap)
+
+def compatdict(context, mapping, name, data, key='key', value='value',
+ fmt=None, plural=None, separator=' '):
+ """Wrap data like hybriddict(), but also supports old-style list template
+
+ This exists for backward compatibility with the old-style template. Use
+ hybriddict() for new template keywords.
+ """
+ c = [{key: k, value: v} for k, v in data.iteritems()]
+ t = context.resource(mapping, 'templ')
+ f = _showlist(name, c, t, mapping, plural, separator)
+ return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
+
+def compatlist(context, mapping, name, data, element=None, fmt=None,
+ plural=None, separator=' '):
+ """Wrap data like hybridlist(), but also supports old-style list template
+
+ This exists for backward compatibility with the old-style template. Use
+ hybridlist() for new template keywords.
+ """
+ t = context.resource(mapping, 'templ')
+ f = _showlist(name, data, t, mapping, plural, separator)
+ return hybridlist(data, name=element or name, fmt=fmt, gen=f)
+
+def _showlist(name, values, templ, mapping, plural=None, separator=' '):
+ '''expand set of values.
+ name is name of key in template map.
+ values is list of strings or dicts.
+ plural is plural of name, if not simply name + 's'.
+ separator is used to join values as a string
+
+ expansion works like this, given name 'foo'.
+
+ if values is empty, expand 'no_foos'.
+
+ if 'foo' not in template map, return values as a string,
+ joined by 'separator'.
+
+ expand 'start_foos'.
+
+ for each value, expand 'foo'. if 'last_foo' in template
+ map, expand it instead of 'foo' for last key.
+
+ expand 'end_foos'.
+ '''
+ strmapping = pycompat.strkwargs(mapping)
+ if not plural:
+ plural = name + 's'
+ if not values:
+ noname = 'no_' + plural
+ if noname in templ:
+ yield templ(noname, **strmapping)
+ return
+ if name not in templ:
+ if isinstance(values[0], bytes):
+ yield separator.join(values)
+ else:
+ for v in values:
+ r = dict(v)
+ r.update(mapping)
+ yield r
+ return
+ startname = 'start_' + plural
+ if startname in templ:
+ yield templ(startname, **strmapping)
+ vmapping = mapping.copy()
+ def one(v, tag=name):
+ try:
+ vmapping.update(v)
+ # Python 2 raises ValueError if the type of v is wrong. Python
+ # 3 raises TypeError.
+ except (AttributeError, TypeError, ValueError):
+ try:
+ # Python 2 raises ValueError trying to destructure an e.g.
+ # bytes. Python 3 raises TypeError.
+ for a, b in v:
+ vmapping[a] = b
+ except (TypeError, ValueError):
+ vmapping[name] = v
+ return templ(tag, **pycompat.strkwargs(vmapping))
+ lastname = 'last_' + name
+ if lastname in templ:
+ last = values.pop()
+ else:
+ last = None
+ for v in values:
+ yield one(v)
+ if last is not None:
+ yield one(last, tag=lastname)
+ endname = 'end_' + plural
+ if endname in templ:
+ yield templ(endname, **strmapping)
+
def stringify(thing):
"""Turn values into bytes by converting into text and concatenating them"""
- thing = templatekw.unwraphybrid(thing)
+ thing = unwraphybrid(thing)
if util.safehasattr(thing, '__iter__') and not isinstance(thing, bytes):
if isinstance(thing, str):
# This is only reachable on Python 3 (otherwise
@@ -59,7 +268,7 @@
def evalfuncarg(context, mapping, arg):
"""Evaluate given argument as value type"""
thing = evalrawexp(context, mapping, arg)
- thing = templatekw.unwrapvalue(thing)
+ thing = unwrapvalue(thing)
# evalrawexp() may return string, generator of strings or arbitrary object
# such as date tuple, but filter does not want generator.
if isinstance(thing, types.GeneratorType):
@@ -76,7 +285,7 @@
thing = util.parsebool(data)
else:
thing = func(context, mapping, data)
- thing = templatekw.unwrapvalue(thing)
+ thing = unwrapvalue(thing)
if isinstance(thing, bool):
return thing
# other objects are evaluated as strings, which means 0 is True, but
@@ -236,4 +445,4 @@
val = dictarg.get(key)
if val is None:
return
- return templatekw.wraphybridvalue(dictarg, key, val)
+ return wraphybridvalue(dictarg, key, val)