[PATCH 1 of 2] util: add method to hash nested combination of python data structures
Matt Mackall
mpm at selenic.com
Wed Jul 1 20:30:55 CDT 2015
On Wed, 2015-07-01 at 17:05 -0700, Laurent Charignon wrote:
> # HG changeset patch
> # User Laurent Charignon <lcharignon at fb.com>
> # Date 1435794507 25200
> # Wed Jul 01 16:48:27 2015 -0700
> # Node ID 6a7e4701a5214f3a6143ced979896ff51b6ea331
> # Parent 2748bf78a5bf610da4f2d90fd1eea19a3b360c04
> util: add method to hash nested combination of python data structures
>
> The goal of this series of patches is to have a method to compute the hash of
> config objects. This will enable restarting the command server when the config
> change.
> This patch adds a method to compute the hash of nested combination of basic
> data structure, it will be used to enable computing the hash of a sortdict and
> in turn compute the hash of a config.
>
> Implementation modified from:
> http://stackoverflow.com/questions/5884066/hashing-a-python-dictionary
>
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -21,6 +21,7 @@ import re as remod
> import os, time, datetime, calendar, textwrap, signal, collections
> import imp, socket, urllib
> import gc
> +import copy
>
> if os.name == 'nt':
> import windows as platform
> @@ -2333,6 +2334,25 @@ class dirs(object):
> if safehasattr(parsers, 'dirs'):
> dirs = parsers.dirs
>
> +def makehash(o):
> + """
> + Makes a hash from a dictionary, list, tuple or set to any level, containing
> + only other hashable types (including any lists, tuples, sets, and
> + dictionaries).
> + """
> +
> + if isinstance(o, (set, tuple, list)):
> + return hash(tuple([makehash(e) for e in o]))
> +
> + elif not isinstance(o, dict):
> + return hash(o)
> +
> + new_o = copy.deepcopy(o)
> + for k, v in new_o.items():
> + new_o[k] = makehash(v)
> +
> + return hash(tuple(frozenset(sorted(new_o.items()))))
Wants a doctest. Also, we can implement this without doing a deep copy
pretty easily:
if isinstance(x, dict):
return makehash(x.iteritems())
if hasattr(x, '__iter__'):
return sum(makehash(i) for i in x)
return hash(x)
--
Mathematics is the supreme nostalgia of our time.
More information about the Mercurial-devel
mailing list