--- a/mercurial/templateutil.py Sun Jun 10 12:24:53 2018 +0900
+++ b/mercurial/templateutil.py Mon Mar 19 00:16:12 2018 +0900
@@ -47,6 +47,16 @@
"""
@abc.abstractmethod
+ def getmin(self, context, mapping):
+ """Return the smallest item, which may be either a wrapped or a pure
+ value depending on the self type"""
+
+ @abc.abstractmethod
+ def getmax(self, context, mapping):
+ """Return the largest item, which may be either a wrapped or a pure
+ value depending on the self type"""
+
+ @abc.abstractmethod
def itermaps(self, context):
"""Yield each template mapping"""
@@ -85,6 +95,17 @@
raise error.ParseError(_('%r is not a dictionary')
% pycompat.bytestr(self._value))
+ def getmin(self, context, mapping):
+ return self._getby(context, mapping, min)
+
+ def getmax(self, context, mapping):
+ return self._getby(context, mapping, max)
+
+ def _getby(self, context, mapping, func):
+ if not self._value:
+ raise error.ParseError(_('empty string'))
+ return func(pycompat.iterbytestr(self._value))
+
def itermaps(self, context):
raise error.ParseError(_('%r is not iterable of mappings')
% pycompat.bytestr(self._value))
@@ -107,6 +128,12 @@
def getmember(self, context, mapping, key):
raise error.ParseError(_('%r is not a dictionary') % self._value)
+ def getmin(self, context, mapping):
+ raise error.ParseError(_("%r is not iterable") % self._value)
+
+ def getmax(self, context, mapping):
+ raise error.ParseError(_("%r is not iterable") % self._value)
+
def itermaps(self, context):
raise error.ParseError(_('%r is not iterable of mappings')
% self._value)
@@ -151,6 +178,18 @@
key = unwrapastype(context, mapping, key, self.keytype)
return self._wrapvalue(key, self._values.get(key))
+ def getmin(self, context, mapping):
+ return self._getby(context, mapping, min)
+
+ def getmax(self, context, mapping):
+ return self._getby(context, mapping, max)
+
+ def _getby(self, context, mapping, func):
+ if not self._values:
+ raise error.ParseError(_('empty sequence'))
+ val = func(self._values)
+ return self._wrapvalue(val, val)
+
def _wrapvalue(self, key, val):
if val is None:
return
@@ -217,6 +256,14 @@
w = makewrapped(context, mapping, self._value)
return w.getmember(context, mapping, key)
+ def getmin(self, context, mapping):
+ w = makewrapped(context, mapping, self._value)
+ return w.getmin(context, mapping)
+
+ def getmax(self, context, mapping):
+ w = makewrapped(context, mapping, self._value)
+ return w.getmax(context, mapping)
+
def itermaps(self, context):
yield self.tomap()
@@ -255,6 +302,12 @@
def getmember(self, context, mapping, key):
raise error.ParseError(_('not a dictionary'))
+ def getmin(self, context, mapping):
+ raise error.ParseError(_('not comparable'))
+
+ def getmax(self, context, mapping):
+ raise error.ParseError(_('not comparable'))
+
def join(self, context, mapping, sep):
mapsiter = _iteroverlaymaps(context, mapping, self.itermaps(context))
if self._name:
@@ -321,6 +374,18 @@
def getmember(self, context, mapping, key):
raise error.ParseError(_('not a dictionary'))
+ def getmin(self, context, mapping):
+ return self._getby(context, mapping, min)
+
+ def getmax(self, context, mapping):
+ return self._getby(context, mapping, max)
+
+ def _getby(self, context, mapping, func):
+ xs = self.tovalue(context, mapping)
+ if not xs:
+ raise error.ParseError(_('empty sequence'))
+ return func(xs)
+
def itermaps(self, context):
raise error.ParseError(_('list of strings is not mappable'))