From fef9727cce1f73b1ab3b307d3577d32f8b6ced1f Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 26 Sep 2010 21:59:54 +0100 Subject: [PATCH] parse_hstore converted in class method. --- lib/extras.py | 86 ++++++++++++++++++++++--------------------- tests/types_extras.py | 7 ++-- 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/lib/extras.py b/lib/extras.py index 4b20bb64..7bfede5e 100644 --- a/lib/extras.py +++ b/lib/extras.py @@ -35,7 +35,7 @@ try: except: logging = None -from psycopg2 import DATETIME, DataError, InterfaceError +import psycopg2 from psycopg2 import extensions as _ext from psycopg2.extensions import cursor as _cursor from psycopg2.extensions import connection as _connection @@ -515,55 +515,57 @@ class HstoreAdapter(object): v.prepare(self.conn) return "hstore(%s, %s)" % (k.getquoted(), v.getquoted()) -_re_hstore = regex.compile(r""" - # hstore key: - "( # catch in quotes - (?: # many of - [^"] # either not a quote - # or a quote escaped, i.e. preceded by an odd number of backslashes - | [^\\] (?:\\\\)* \\" - )* - )" - \s*=>\s* # hstore value - (?: - NULL # the value can be null - not catched - # or the same quoted string of the key - | "((?:[^"] | [^\\] (?:\\\\)* \\" )*)" - ) - (?:\s*,\s*|$) # pairs separated by comma or end of string. -""", regex.VERBOSE) + _re_hstore = regex.compile(r""" + # hstore key: + "( # catch in quotes + (?: # many of + [^"] # either not a quote + # or a quote escaped, i.e. preceded by an odd number of backslashes + | [^\\] (?:\\\\)* \\" + )* + )" + \s*=>\s* # hstore value + (?: + NULL # the value can be null - not catched + # or the same quoted string of the key + | "((?:[^"] | [^\\] (?:\\\\)* \\" )*)" + ) + (?:\s*,\s*|$) # pairs separated by comma or end of string. + """, regex.VERBOSE) -def parse_hstore(s, cur): - """Parse an hstore representation in a Python string. + def parse(self, s, cur): + """Parse an hstore representation in a Python string. - The hstore is represented as something like:: + The hstore is represented as something like:: - "a"=>"1", "b"=>"2" + "a"=>"1", "b"=>"2" - with backslash-escaped strings. - """ - if s is None: - return None + with backslash-escaped strings. + """ + if s is None: + return None - rv = {} - start = 0 - for m in _re_hstore.finditer(s): - if m is None or m.start() != start: - raise InterfaceError( - "error parsing hstore pair at char %d" % start) - k = m.group(1).decode("string_escape") - v = m.group(2) - if v is not None: - v = v.decode("string_escape") + rv = {} + start = 0 + for m in self._re_hstore.finditer(s): + if m is None or m.start() != start: + raise psycopg2.InterfaceError( + "error parsing hstore pair at char %d" % start) + k = m.group(1).decode("string_escape") + v = m.group(2) + if v is not None: + v = v.decode("string_escape") - rv[k] = v - start = m.end() + rv[k] = v + start = m.end() - if start < len(s): - raise InterfaceError( - "error parsing hstore: unparsed data after char %d" % start) + if start < len(s): + raise psycopg2.InterfaceError( + "error parsing hstore: unparsed data after char %d" % start) - return rv + return rv + + parse = classmethod(parse) __all__ = filter(lambda k: not k.startswith('_'), locals().keys()) diff --git a/tests/types_extras.py b/tests/types_extras.py index 559e6950..480312ba 100644 --- a/tests/types_extras.py +++ b/tests/types_extras.py @@ -158,10 +158,10 @@ class HstoreTestCase(unittest.TestCase): self.assertEqual(ii[3], ("E'd'", "E'%s'" % encc)) def test_parse(self): - from psycopg2.extras import parse_hstore + from psycopg2.extras import HstoreAdapter def ok(s, d): - self.assertEqual(parse_hstore(s, None), d) + self.assertEqual(HstoreAdapter.parse(s, None), d) ok(None, None) ok('', {}) @@ -176,7 +176,8 @@ class HstoreTestCase(unittest.TestCase): ok(r'"a\\\\\""=>"1"', {r'a\\"': '1'}) def ko(s): - self.assertRaises(psycopg2.InterfaceError, parse_hstore, s, None) + self.assertRaises(psycopg2.InterfaceError, + HstoreAdapter.parse, s, None) ko('a') ko('"a"')