diff --git a/sexpdata.py b/sexpdata.py index 153a31b..d5a75b2 100644 --- a/sexpdata.py +++ b/sexpdata.py @@ -77,7 +77,12 @@ ] import re -from collections import namedtuple, Iterable, Mapping, Sequence +from collections import namedtuple +try: + from collections.abc import Iterable, Mapping, Sequence +except ImportError: + # Python < 3.3 + from collections import Iterable, Mapping, Sequence from itertools import chain from string import whitespace @@ -446,6 +451,14 @@ def __eq__(self, other): def __ne__(self, other): return not self == other + def __hash__(self): + """ + >>> D = {'a': 1, String('a'): 2, Symbol('a'): 3} + >>> len(D) + 3 + """ + return unicode.__hash__(self) + _lisp_quoted_specials = [ # from Pymacs ('\\', '\\\\'), # must come first to avoid doubly quoting "\" ('"', '\\"'), ('\b', '\\b'), ('\f', '\\f'), diff --git a/test_sexpdata.py b/test_sexpdata.py index ec33f88..481e11f 100644 --- a/test_sexpdata.py +++ b/test_sexpdata.py @@ -88,6 +88,17 @@ def test_parse_special_symbols(self): r'\ ', r'\.', r'\,', r'\?', r'\;', r'\#']: self.assert_parse(s, Symbol(Symbol.unquote(s))) + def test_hashable_and_distinct(self): + d = { + String("A"): "StrA", + Symbol("A"): "SymA", + "A": "strA", + } + self.assertEqual(3, len(d)) + self.assertEqual("StrA", d[String("A")]) + self.assertEqual("SymA", d[Symbol("A")]) + self.assertEqual("strA", d["A"]) + class TestParseFluctuation(BaseTestCase):