Mercurial > public > mercurial-scm > hg
diff mercurial/templateutil.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 832c59d1196e |
children | 687b865b95ad |
line wrap: on
line diff
--- a/mercurial/templateutil.py Sat Oct 05 10:29:34 2019 -0400 +++ b/mercurial/templateutil.py Sun Oct 06 09:45:02 2019 -0400 @@ -21,12 +21,15 @@ stringutil, ) + class ResourceUnavailable(error.Abort): pass + class TemplateNotFound(error.Abort): pass + class wrapped(object): """Object requiring extra conversion prior to displaying or processing as value @@ -103,6 +106,7 @@ A returned value must be serializable by templaterfilters.json(). """ + class mappable(object): """Object which can be converted to a single template mapping""" @@ -113,6 +117,7 @@ def tomap(self, context): """Create a single template mapping representing this""" + class wrappedbytes(wrapped): """Wrapper for byte string""" @@ -124,8 +129,9 @@ return item in self._value def getmember(self, context, mapping, key): - raise error.ParseError(_('%r is not a dictionary') - % pycompat.bytestr(self._value)) + raise error.ParseError( + _('%r is not a dictionary') % pycompat.bytestr(self._value) + ) def getmin(self, context, mapping): return self._getby(context, mapping, min) @@ -139,12 +145,14 @@ return func(pycompat.iterbytestr(self._value)) def filter(self, context, mapping, select): - raise error.ParseError(_('%r is not filterable') - % pycompat.bytestr(self._value)) + raise error.ParseError( + _('%r is not filterable') % pycompat.bytestr(self._value) + ) def itermaps(self, context): - raise error.ParseError(_('%r is not iterable of mappings') - % pycompat.bytestr(self._value)) + raise error.ParseError( + _('%r is not iterable of mappings') % pycompat.bytestr(self._value) + ) def join(self, context, mapping, sep): return joinitems(pycompat.iterbytestr(self._value), sep) @@ -158,6 +166,7 @@ def tovalue(self, context, mapping): return self._value + class wrappedvalue(wrapped): """Generic wrapper for pure non-list/dict/bytes value""" @@ -180,8 +189,9 @@ raise error.ParseError(_("%r is not iterable") % self._value) def itermaps(self, context): - raise error.ParseError(_('%r is not iterable of mappings') - % self._value) + raise error.ParseError( + _('%r is not iterable of mappings') % self._value + ) def join(self, context, mapping, sep): raise error.ParseError(_('%r is not iterable') % self._value) @@ -202,6 +212,7 @@ def tovalue(self, context, mapping): return self._value + class date(mappable, wrapped): """Wrapper for date tuple""" @@ -241,6 +252,7 @@ def tovalue(self, context, mapping): return (self._unixtime, self._tzoffset) + class hybrid(wrapped): """Wrapper for list or dict to support legacy template @@ -293,8 +305,11 @@ def filter(self, context, mapping, select): if util.safehasattr(self._values, 'get'): - values = {k: v for k, v in self._values.iteritems() - if select(self._wrapvalue(k, v))} + values = { + k: v + for k, v in self._values.iteritems() + if select(self._wrapvalue(k, v)) + } else: values = [v for v in self._values if select(self._wrapvalue(v, v))] return hybrid(None, values, self._makemap, self._joinfmt, self._keytype) @@ -324,10 +339,12 @@ # TODO: make it non-recursive for trivial lists/dicts xs = self._values if util.safehasattr(xs, 'get'): - return {k: unwrapvalue(context, mapping, v) - for k, v in xs.iteritems()} + return { + k: unwrapvalue(context, mapping, v) for k, v in xs.iteritems() + } return [unwrapvalue(context, mapping, x) for x in xs] + class hybriditem(mappable, wrapped): """Wrapper for non-list/dict object to support map operation @@ -386,6 +403,7 @@ def tovalue(self, context, mapping): return _unthunk(context, mapping, self._value) + class _mappingsequence(wrapped): """Wrapper for sequence of template mappings @@ -437,10 +455,16 @@ for nm in self.itermaps(context): # drop internal resources (recursively) which shouldn't be displayed lm = context.overlaymap(mapping, nm) - items.append({k: unwrapvalue(context, lm, v) - for k, v in nm.iteritems() if k not in knownres}) + items.append( + { + k: unwrapvalue(context, lm, v) + for k, v in nm.iteritems() + if k not in knownres + } + ) return items + class mappinggenerator(_mappingsequence): """Wrapper for generator of template mappings @@ -459,6 +483,7 @@ def tobool(self, context, mapping): return _nonempty(self.itermaps(context)) + class mappinglist(_mappingsequence): """Wrapper for list of template mappings""" @@ -472,6 +497,7 @@ def tobool(self, context, mapping): return bool(self._mappings) + class mappingdict(mappable, _mappingsequence): """Wrapper for a single template mapping @@ -495,6 +521,7 @@ def tovalue(self, context, mapping): return super(mappingdict, self).tovalue(context, mapping)[0] + class mappingnone(wrappedvalue): """Wrapper for None, but supports map operation @@ -508,6 +535,7 @@ def itermaps(self, context): return iter([]) + class mappedgenerator(wrapped): """Wrapper for generator of strings which acts as a list @@ -568,14 +596,20 @@ def tovalue(self, context, mapping): return [stringify(context, mapping, x) for x in self._gen(context)] + 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]))) + 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""" @@ -585,8 +619,18 @@ prefmt = pycompat.bytestr return hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x)) -def compatdict(context, mapping, name, data, key='key', value='value', - fmt=None, plural=None, separator=' '): + +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 @@ -596,8 +640,17 @@ f = _showcompatlist(context, mapping, name, c, 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=' '): + +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 @@ -606,6 +659,7 @@ f = _showcompatlist(context, mapping, name, data, plural, separator) return hybridlist(data, name=element or name, fmt=fmt, gen=f) + def compatfilecopiesdict(context, mapping, name, copies): """Wrap list of (dest, source) file names to support old-style list template and field names @@ -617,9 +671,13 @@ c = [{'name': k, 'source': v} for k, v in copies] f = _showcompatlist(context, mapping, name, c, plural='file_copies') copies = util.sortdict(copies) - return hybrid(f, copies, - lambda k: {'name': k, 'path': k, 'source': copies[k]}, - lambda k: '%s (%s)' % (k, copies[k])) + return hybrid( + f, + copies, + lambda k: {'name': k, 'path': k, 'source': copies[k]}, + lambda k: '%s (%s)' % (k, copies[k]), + ) + def compatfileslist(context, mapping, name, files): """Wrap list of file names to support old-style list template and field @@ -629,8 +687,8 @@ keywords. """ f = _showcompatlist(context, mapping, name, files) - return hybrid(f, files, lambda x: {'file': x, 'path': x}, - pycompat.identity) + return hybrid(f, files, lambda x: {'file': x, 'path': x}, pycompat.identity) + def _showcompatlist(context, mapping, name, values, plural=None, separator=' '): """Return a generator that renders old-style list template @@ -673,6 +731,7 @@ startname = 'start_' + plural if context.preload(startname): yield context.process(startname, mapping) + def one(v, tag=name): vmapping = {} try: @@ -689,6 +748,7 @@ vmapping[name] = v vmapping = context.overlaymap(mapping, vmapping) return context.process(tag, vmapping) + lastname = 'last_' + name if context.preload(lastname): last = values.pop() @@ -702,6 +762,7 @@ if context.preload(endname): yield context.process(endname, mapping) + def flatten(context, mapping, thing): """Yield a single stream from a possibly nested set of iterators""" if isinstance(thing, wrapped): @@ -711,8 +772,10 @@ elif isinstance(thing, str): # We can only hit this on Python 3, and it's here to guard # against infinite recursion. - raise error.ProgrammingError('Mercurial IO including templates is done' - ' with bytes, not strings, got %r' % thing) + raise error.ProgrammingError( + 'Mercurial IO including templates is done' + ' with bytes, not strings, got %r' % thing + ) elif thing is None: pass elif not util.safehasattr(thing, '__iter__'): @@ -731,12 +794,14 @@ for j in flatten(context, mapping, i): yield j + def stringify(context, mapping, thing): """Turn values into bytes by converting into text and concatenating them""" if isinstance(thing, bytes): return thing # retain localstr to be round-tripped return b''.join(flatten(context, mapping, thing)) + def findsymbolicname(arg): """Find symbolic name for the given compiled expression; returns None if nothing found reliably""" @@ -749,6 +814,7 @@ else: return None + def _nonempty(xiter): try: next(xiter) @@ -756,23 +822,27 @@ except StopIteration: return False + def _unthunk(context, mapping, thing): """Evaluate a lazy byte string into value""" if not isinstance(thing, types.GeneratorType): return thing return stringify(context, mapping, thing) + def evalrawexp(context, mapping, arg): """Evaluate given argument as a bare template object which may require further processing (such as folding generator of strings)""" func, data = arg return func(context, mapping, data) + def evalwrapped(context, mapping, arg): """Evaluate given argument to wrapped object""" thing = evalrawexp(context, mapping, arg) return makewrapped(context, mapping, thing) + def makewrapped(context, mapping, thing): """Lift object to a wrapped type""" if isinstance(thing, wrapped): @@ -782,10 +852,12 @@ return wrappedbytes(thing) return wrappedvalue(thing) + def evalfuncarg(context, mapping, arg): """Evaluate given argument as value type""" return unwrapvalue(context, mapping, evalrawexp(context, mapping, arg)) + def unwrapvalue(context, mapping, thing): """Move the inner value object out of the wrapper""" if isinstance(thing, wrapped): @@ -794,6 +866,7 @@ # such as date tuple, but filter does not want generator. return _unthunk(context, mapping, thing) + def evalboolean(context, mapping, arg): """Evaluate given argument as boolean, but also takes boolean literals""" func, data = arg @@ -806,12 +879,14 @@ thing = func(context, mapping, data) return makewrapped(context, mapping, thing).tobool(context, mapping) + def evaldate(context, mapping, arg, err=None): """Evaluate given argument as a date tuple or a date string; returns a (unixtime, offset) tuple""" thing = evalrawexp(context, mapping, arg) return unwrapdate(context, mapping, thing, err) + def unwrapdate(context, mapping, thing, err=None): if isinstance(thing, date): return thing.tovalue(context, mapping) @@ -826,10 +901,12 @@ raise raise error.ParseError(err) + def evalinteger(context, mapping, arg, err=None): thing = evalrawexp(context, mapping, arg) return unwrapinteger(context, mapping, thing, err) + def unwrapinteger(context, mapping, thing, err=None): thing = unwrapvalue(context, mapping, thing) try: @@ -837,9 +914,11 @@ except (TypeError, ValueError): raise error.ParseError(err or _('not an integer')) + def evalstring(context, mapping, arg): return stringify(context, mapping, evalrawexp(context, mapping, arg)) + def evalstringliteral(context, mapping, arg): """Evaluate given argument as string template, but returns symbol name if it is unknown""" @@ -850,6 +929,7 @@ thing = func(context, mapping, data) return stringify(context, mapping, thing) + _unwrapfuncbytype = { None: unwrapvalue, bytes: stringify, @@ -857,6 +937,7 @@ int: unwrapinteger, } + def unwrapastype(context, mapping, thing, typ): """Move the inner value object out of the wrapper and coerce its type""" try: @@ -865,17 +946,22 @@ raise error.ProgrammingError('invalid type specified: %r' % typ) return f(context, mapping, thing) + def runinteger(context, mapping, data): return int(data) + def runstring(context, mapping, data): return data + def _recursivesymbolblocker(key): def showrecursion(context, mapping): raise error.Abort(_("recursive reference '%s' in template") % key) + return showrecursion + def runsymbol(context, mapping, key, default=''): v = context.symbol(mapping, key) if v is None: @@ -896,10 +982,12 @@ return None return v + def runtemplate(context, mapping, template): for arg in template: yield evalrawexp(context, mapping, arg) + def runfilter(context, mapping, data): arg, filt = data thing = evalrawexp(context, mapping, arg) @@ -910,13 +998,17 @@ except error.ParseError as e: raise error.ParseError(bytes(e), hint=_formatfiltererror(arg, filt)) + def _formatfiltererror(arg, filt): fn = pycompat.sysbytes(filt.__name__) sym = findsymbolicname(arg) if not sym: return _("incompatible use of template filter '%s'") % fn - return (_("template filter '%s' is not compatible with keyword '%s'") - % (fn, sym)) + return _("template filter '%s' is not compatible with keyword '%s'") % ( + fn, + sym, + ) + def _iteroverlaymaps(context, origmapping, newmappings): """Generate combined mappings from the original mapping and an iterable @@ -926,6 +1018,7 @@ lm['index'] = i yield lm + def _applymap(context, mapping, d, darg, targ): try: diter = d.itermaps(context) @@ -938,11 +1031,13 @@ for lm in _iteroverlaymaps(context, mapping, diter): yield evalrawexp(context, lm, targ) + def runmap(context, mapping, data): darg, targ = data d = evalwrapped(context, mapping, darg) return mappedgenerator(_applymap, args=(mapping, d, darg, targ)) + def runmember(context, mapping, data): darg, memb = data d = evalwrapped(context, mapping, darg) @@ -958,22 +1053,28 @@ hint = _("keyword '%s' does not support member operation") % sym raise error.ParseError(bytes(err), hint=hint) + def runnegate(context, mapping, data): - data = evalinteger(context, mapping, data, - _('negation needs an integer argument')) + data = evalinteger( + context, mapping, data, _('negation needs an integer argument') + ) return -data + def runarithmetic(context, mapping, data): func, left, right = data - left = evalinteger(context, mapping, left, - _('arithmetic only defined on integers')) - right = evalinteger(context, mapping, right, - _('arithmetic only defined on integers')) + left = evalinteger( + context, mapping, left, _('arithmetic only defined on integers') + ) + right = evalinteger( + context, mapping, right, _('arithmetic only defined on integers') + ) try: return func(left, right) except ZeroDivisionError: raise error.Abort(_('division by zero is not defined')) + def joinitems(itemiter, sep): """Join items with the separator; Returns generator of bytes""" first = True