# HG changeset patch # User Yuya Nishihara # Date 1471233513 -32400 # Node ID 4891f3b93182fb8ca2cc532774567ac1c6b1c9d1 # Parent 24991e7f775f831386d5794953282ac9b76f5808 formatter: add function to convert dict to appropriate format This will be used to process key-value pairs by formatter. The default field names and format are derived from the {extras} template keyword. Tests will be added later. diff -r 24991e7f775f -r 4891f3b93182 mercurial/formatter.py --- a/mercurial/formatter.py Mon Aug 15 17:17:39 2016 +0900 +++ b/mercurial/formatter.py Mon Aug 15 12:58:33 2016 +0900 @@ -51,6 +51,12 @@ '''convert date tuple to appropriate format''' return date @staticmethod + def formatdict(data, key='key', value='value', fmt='%s=%s', sep=' '): + '''convert dict or key-value pairs to appropriate dict format''' + # use plain dict instead of util.sortdict so that data can be + # serialized as a builtin dict in pickle output + return dict(data) + @staticmethod def formatlist(data, name, fmt='%s', sep=' '): '''convert iterable to appropriate list format''' return list(data) @@ -75,6 +81,12 @@ if self._item is not None: self._showitem() +def _iteritems(data): + '''iterate key-value pairs in stable order''' + if isinstance(data, dict): + return sorted(data.iteritems()) + return data + class plainformatter(baseformatter): '''the default text output scheme''' def __init__(self, ui, topic, opts): @@ -92,6 +104,10 @@ '''stringify date tuple in the given format''' return util.datestr(date, fmt) @staticmethod + def formatdict(data, key='key', value='value', fmt='%s=%s', sep=' '): + '''stringify key-value pairs separated by sep''' + return sep.join(fmt % (k, v) for k, v in _iteritems(data)) + @staticmethod def formatlist(data, name, fmt='%s', sep=' '): '''stringify iterable separated by sep''' return sep.join(fmt % e for e in data) @@ -129,7 +145,11 @@ self._ui.write(pickle.dumps(self._data)) def _jsonifyobj(v): - if isinstance(v, (list, tuple)): + if isinstance(v, dict): + xs = ['"%s": %s' % (encoding.jsonescape(k), _jsonifyobj(u)) + for k, u in sorted(v.iteritems())] + return '{' + ', '.join(xs) + '}' + elif isinstance(v, (list, tuple)): return '[' + ', '.join(_jsonifyobj(e) for e in v) + ']' elif v is None: return 'null' @@ -175,6 +195,14 @@ g = self._t(self._topic, ui=self._ui, **self._item) self._ui.write(templater.stringify(g)) @staticmethod + def formatdict(data, key='key', value='value', fmt='%s=%s', sep=' '): + '''build object that can be evaluated as either plain string or dict''' + data = util.sortdict(_iteritems(data)) + def f(): + yield plainformatter.formatdict(data, key, value, fmt, sep) + return templatekw._hybrid(f(), data, lambda k: {key: k, value: data[k]}, + lambda d: fmt % (d[key], d[value])) + @staticmethod def formatlist(data, name, fmt='%s', sep=' '): '''build object that can be evaluated as either plain string or list''' # name is mandatory argument for now, but it could be optional if