Mercurial > hg
changeset 36997:44467a4d472f
hgweb: refactor multirequest to be a dict of lists
... instead of a list of 2-tuples.
This makes key lookups faster. The only downside is we lose total
ordering of all entries. But we weren't relying on that before, so
it's no loss.
Differential Revision: https://phab.mercurial-scm.org/D2881
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Fri, 16 Mar 2018 09:41:21 -0700 |
parents | 1bf555cb680e |
children | 3723b42ff953 |
files | mercurial/hgweb/request.py |
diffstat | 1 files changed, 9 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/hgweb/request.py Sun Mar 04 22:35:29 2018 +0530 +++ b/mercurial/hgweb/request.py Fri Mar 16 09:41:21 2018 -0700 @@ -28,39 +28,22 @@ This is inspired by WebOb's class of the same name. """ def __init__(self): - # Stores (key, value) 2-tuples. This isn't the most efficient. But we - # don't rely on parameters that much, so it shouldn't be a perf issue. - # we can always add dict for fast lookups. - self._items = [] + self._items = {} def __getitem__(self, key): """Returns the last set value for a key.""" - for k, v in reversed(self._items): - if k == key: - return v - - raise KeyError(key) + return self._items[key][-1] def __setitem__(self, key, value): """Replace a values for a key with a new value.""" - try: - del self[key] - except KeyError: - pass - - self._items.append((key, value)) + self._items[key] = [value] def __delitem__(self, key): """Delete all values for a key.""" - oldlen = len(self._items) - - self._items[:] = [(k, v) for k, v in self._items if k != key] - - if oldlen == len(self._items): - raise KeyError(key) + del self._items[key] def __contains__(self, key): - return any(k == key for k, v in self._items) + return key in self._items def __len__(self): return len(self._items) @@ -73,21 +56,18 @@ def add(self, key, value): """Add a new value for a key. Does not replace existing values.""" - self._items.append((key, value)) + self._items.setdefault(key, []).append(value) def getall(self, key): """Obtains all values for a key.""" - return [v for k, v in self._items if k == key] + return self._items.get(key, []) def getone(self, key): """Obtain a single value for a key. Raises KeyError if key not defined or it has multiple values set. """ - vals = self.getall(key) - - if not vals: - raise KeyError(key) + vals = self._items[key] if len(vals) > 1: raise KeyError('multiple values for %r' % key) @@ -95,14 +75,7 @@ return vals[0] def asdictoflists(self): - d = {} - for k, v in self._items: - if k in d: - d[k].append(v) - else: - d[k] = [v] - - return d + return {k: list(v) for k, v in self._items.iteritems()} @attr.s(frozen=True) class parsedrequest(object):