Mercurial > public > mercurial-scm > hg
comparison mercurial/templateutil.py @ 38267:fb874fc1d9b4
templater: abstract ifcontains() over wrapped types
This allows us to make .keytype private.
There's a minor BC that a hybrid dict/list of keytype=None now strictly
checks the type of the needle. For example, {ifcontains(rev, files)} no longer
matches a file named "1" at the rev=1. I made this change for consistency
with the get(dict, key) function. We can restore the old behavior by making
keytype=bytes the default if desired.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Mon, 19 Mar 2018 00:23:20 +0900 |
parents | 80f423a14c90 |
children | 49ef1539b84e |
comparison
equal
deleted
inserted
replaced
38266:80f423a14c90 | 38267:fb874fc1d9b4 |
---|---|
36 """ | 36 """ |
37 | 37 |
38 __metaclass__ = abc.ABCMeta | 38 __metaclass__ = abc.ABCMeta |
39 | 39 |
40 @abc.abstractmethod | 40 @abc.abstractmethod |
41 def contains(self, context, mapping, item): | |
42 """Test if the specified item is in self | |
43 | |
44 The item argument may be a wrapped object. | |
45 """ | |
46 | |
47 @abc.abstractmethod | |
41 def getmember(self, context, mapping, key): | 48 def getmember(self, context, mapping, key): |
42 """Return a member item for the specified key | 49 """Return a member item for the specified key |
43 | 50 |
44 The key argument may be a wrapped object. | 51 The key argument may be a wrapped object. |
45 A returned object may be either a wrapped object or a pure value | 52 A returned object may be either a wrapped object or a pure value |
89 """Wrapper for byte string""" | 96 """Wrapper for byte string""" |
90 | 97 |
91 def __init__(self, value): | 98 def __init__(self, value): |
92 self._value = value | 99 self._value = value |
93 | 100 |
101 def contains(self, context, mapping, item): | |
102 item = stringify(context, mapping, item) | |
103 return item in self._value | |
104 | |
94 def getmember(self, context, mapping, key): | 105 def getmember(self, context, mapping, key): |
95 raise error.ParseError(_('%r is not a dictionary') | 106 raise error.ParseError(_('%r is not a dictionary') |
96 % pycompat.bytestr(self._value)) | 107 % pycompat.bytestr(self._value)) |
97 | 108 |
98 def getmin(self, context, mapping): | 109 def getmin(self, context, mapping): |
122 class wrappedvalue(wrapped): | 133 class wrappedvalue(wrapped): |
123 """Generic wrapper for pure non-list/dict/bytes value""" | 134 """Generic wrapper for pure non-list/dict/bytes value""" |
124 | 135 |
125 def __init__(self, value): | 136 def __init__(self, value): |
126 self._value = value | 137 self._value = value |
138 | |
139 def contains(self, context, mapping, item): | |
140 raise error.ParseError(_("%r is not iterable") % self._value) | |
127 | 141 |
128 def getmember(self, context, mapping, key): | 142 def getmember(self, context, mapping, key): |
129 raise error.ParseError(_('%r is not a dictionary') % self._value) | 143 raise error.ParseError(_('%r is not a dictionary') % self._value) |
130 | 144 |
131 def getmin(self, context, mapping): | 145 def getmin(self, context, mapping): |
168 self._gen = gen # generator or function returning generator | 182 self._gen = gen # generator or function returning generator |
169 self._values = values | 183 self._values = values |
170 self._makemap = makemap | 184 self._makemap = makemap |
171 self._joinfmt = joinfmt | 185 self._joinfmt = joinfmt |
172 self.keytype = keytype # hint for 'x in y' where type(x) is unresolved | 186 self.keytype = keytype # hint for 'x in y' where type(x) is unresolved |
187 | |
188 def contains(self, context, mapping, item): | |
189 item = unwrapastype(context, mapping, item, self.keytype) | |
190 return item in self._values | |
173 | 191 |
174 def getmember(self, context, mapping, key): | 192 def getmember(self, context, mapping, key): |
175 # TODO: maybe split hybrid list/dict types? | 193 # TODO: maybe split hybrid list/dict types? |
176 if not util.safehasattr(self._values, 'get'): | 194 if not util.safehasattr(self._values, 'get'): |
177 raise error.ParseError(_('not a dictionary')) | 195 raise error.ParseError(_('not a dictionary')) |
253 self._makemap = makemap | 271 self._makemap = makemap |
254 | 272 |
255 def tomap(self): | 273 def tomap(self): |
256 return self._makemap(self._key) | 274 return self._makemap(self._key) |
257 | 275 |
276 def contains(self, context, mapping, item): | |
277 w = makewrapped(context, mapping, self._value) | |
278 return w.contains(context, mapping, item) | |
279 | |
258 def getmember(self, context, mapping, key): | 280 def getmember(self, context, mapping, key): |
259 w = makewrapped(context, mapping, self._value) | 281 w = makewrapped(context, mapping, self._value) |
260 return w.getmember(context, mapping, key) | 282 return w.getmember(context, mapping, key) |
261 | 283 |
262 def getmin(self, context, mapping): | 284 def getmin(self, context, mapping): |
299 if name is not None and tmpl is not None: | 321 if name is not None and tmpl is not None: |
300 raise error.ProgrammingError('name and tmpl are mutually exclusive') | 322 raise error.ProgrammingError('name and tmpl are mutually exclusive') |
301 self._name = name | 323 self._name = name |
302 self._tmpl = tmpl | 324 self._tmpl = tmpl |
303 self._defaultsep = sep | 325 self._defaultsep = sep |
326 | |
327 def contains(self, context, mapping, item): | |
328 raise error.ParseError(_('not comparable')) | |
304 | 329 |
305 def getmember(self, context, mapping, key): | 330 def getmember(self, context, mapping, key): |
306 raise error.ParseError(_('not a dictionary')) | 331 raise error.ParseError(_('not a dictionary')) |
307 | 332 |
308 def getmin(self, context, mapping): | 333 def getmin(self, context, mapping): |
368 """ | 393 """ |
369 | 394 |
370 def __init__(self, make, args=()): | 395 def __init__(self, make, args=()): |
371 self._make = make | 396 self._make = make |
372 self._args = args | 397 self._args = args |
398 | |
399 def contains(self, context, mapping, item): | |
400 item = stringify(context, mapping, item) | |
401 return item in self.tovalue(context, mapping) | |
373 | 402 |
374 def _gen(self, context): | 403 def _gen(self, context): |
375 return self._make(context, *self._args) | 404 return self._make(context, *self._args) |
376 | 405 |
377 def getmember(self, context, mapping, key): | 406 def getmember(self, context, mapping, key): |