mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-06-29 09:13:06 +03:00
parse_hstore converted in class method.
This commit is contained in:
parent
5844e989c4
commit
fef9727cce
|
@ -35,7 +35,7 @@ try:
|
||||||
except:
|
except:
|
||||||
logging = None
|
logging = None
|
||||||
|
|
||||||
from psycopg2 import DATETIME, DataError, InterfaceError
|
import psycopg2
|
||||||
from psycopg2 import extensions as _ext
|
from psycopg2 import extensions as _ext
|
||||||
from psycopg2.extensions import cursor as _cursor
|
from psycopg2.extensions import cursor as _cursor
|
||||||
from psycopg2.extensions import connection as _connection
|
from psycopg2.extensions import connection as _connection
|
||||||
|
@ -515,55 +515,57 @@ class HstoreAdapter(object):
|
||||||
v.prepare(self.conn)
|
v.prepare(self.conn)
|
||||||
return "hstore(%s, %s)" % (k.getquoted(), v.getquoted())
|
return "hstore(%s, %s)" % (k.getquoted(), v.getquoted())
|
||||||
|
|
||||||
_re_hstore = regex.compile(r"""
|
_re_hstore = regex.compile(r"""
|
||||||
# hstore key:
|
# hstore key:
|
||||||
"( # catch in quotes
|
"( # catch in quotes
|
||||||
(?: # many of
|
(?: # many of
|
||||||
[^"] # either not a quote
|
[^"] # either not a quote
|
||||||
# or a quote escaped, i.e. preceded by an odd number of backslashes
|
# or a quote escaped, i.e. preceded by an odd number of backslashes
|
||||||
| [^\\] (?:\\\\)* \\"
|
| [^\\] (?:\\\\)* \\"
|
||||||
)*
|
)*
|
||||||
)"
|
)"
|
||||||
\s*=>\s* # hstore value
|
\s*=>\s* # hstore value
|
||||||
(?:
|
(?:
|
||||||
NULL # the value can be null - not catched
|
NULL # the value can be null - not catched
|
||||||
# or the same quoted string of the key
|
# or the same quoted string of the key
|
||||||
| "((?:[^"] | [^\\] (?:\\\\)* \\" )*)"
|
| "((?:[^"] | [^\\] (?:\\\\)* \\" )*)"
|
||||||
)
|
)
|
||||||
(?:\s*,\s*|$) # pairs separated by comma or end of string.
|
(?:\s*,\s*|$) # pairs separated by comma or end of string.
|
||||||
""", regex.VERBOSE)
|
""", regex.VERBOSE)
|
||||||
|
|
||||||
def parse_hstore(s, cur):
|
def parse(self, s, cur):
|
||||||
"""Parse an hstore representation in a Python string.
|
"""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.
|
with backslash-escaped strings.
|
||||||
"""
|
"""
|
||||||
if s is None:
|
if s is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
rv = {}
|
rv = {}
|
||||||
start = 0
|
start = 0
|
||||||
for m in _re_hstore.finditer(s):
|
for m in self._re_hstore.finditer(s):
|
||||||
if m is None or m.start() != start:
|
if m is None or m.start() != start:
|
||||||
raise InterfaceError(
|
raise psycopg2.InterfaceError(
|
||||||
"error parsing hstore pair at char %d" % start)
|
"error parsing hstore pair at char %d" % start)
|
||||||
k = m.group(1).decode("string_escape")
|
k = m.group(1).decode("string_escape")
|
||||||
v = m.group(2)
|
v = m.group(2)
|
||||||
if v is not None:
|
if v is not None:
|
||||||
v = v.decode("string_escape")
|
v = v.decode("string_escape")
|
||||||
|
|
||||||
rv[k] = v
|
rv[k] = v
|
||||||
start = m.end()
|
start = m.end()
|
||||||
|
|
||||||
if start < len(s):
|
if start < len(s):
|
||||||
raise InterfaceError(
|
raise psycopg2.InterfaceError(
|
||||||
"error parsing hstore: unparsed data after char %d" % start)
|
"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())
|
__all__ = filter(lambda k: not k.startswith('_'), locals().keys())
|
||||||
|
|
|
@ -158,10 +158,10 @@ class HstoreTestCase(unittest.TestCase):
|
||||||
self.assertEqual(ii[3], ("E'd'", "E'%s'" % encc))
|
self.assertEqual(ii[3], ("E'd'", "E'%s'" % encc))
|
||||||
|
|
||||||
def test_parse(self):
|
def test_parse(self):
|
||||||
from psycopg2.extras import parse_hstore
|
from psycopg2.extras import HstoreAdapter
|
||||||
|
|
||||||
def ok(s, d):
|
def ok(s, d):
|
||||||
self.assertEqual(parse_hstore(s, None), d)
|
self.assertEqual(HstoreAdapter.parse(s, None), d)
|
||||||
|
|
||||||
ok(None, None)
|
ok(None, None)
|
||||||
ok('', {})
|
ok('', {})
|
||||||
|
@ -176,7 +176,8 @@ class HstoreTestCase(unittest.TestCase):
|
||||||
ok(r'"a\\\\\""=>"1"', {r'a\\"': '1'})
|
ok(r'"a\\\\\""=>"1"', {r'a\\"': '1'})
|
||||||
|
|
||||||
def ko(s):
|
def ko(s):
|
||||||
self.assertRaises(psycopg2.InterfaceError, parse_hstore, s, None)
|
self.assertRaises(psycopg2.InterfaceError,
|
||||||
|
HstoreAdapter.parse, s, None)
|
||||||
|
|
||||||
ko('a')
|
ko('a')
|
||||||
ko('"a"')
|
ko('"a"')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user