def test_adapt_9(self): if self.conn.server_version < 90000: return self.skipTest("skipping dict adaptation with PG 9 syntax") from psycopg2.extras import HstoreAdapter o = {'a': '1', 'b': "'", 'c': None} if self.conn.encoding == 'UTF8': o['d'] = u'\xe0' a = HstoreAdapter(o) a.prepare(self.conn) q = a.getquoted() m = re.match(r'hstore\(ARRAY\[([^\]]+)\], ARRAY\[([^\]]+)\]\)', q) self.assert_(m, repr(q)) kk = m.group(1).split(", ") vv = m.group(2).split(", ") ii = zip(kk, vv) ii.sort() self.assertEqual(len(ii), len(o)) self.assertEqual(ii[0], ("E'a'", "E'1'")) self.assertEqual(ii[1], ("E'b'", "E''''")) self.assertEqual(ii[2], ("E'c'", "NULL")) if 'd' in o: encc = u'\xe0'.encode(psycopg2.extensions.encodings[self.conn.encoding]) self.assertEqual(ii[3], ("E'd'", "E'%s'" % encc))
def test_adapt_9(self): if self.conn.server_version < 90000: return self.skipTest("skipping dict adaptation with PG 9 syntax") from psycopg2.extras import HstoreAdapter o = {"a": "1", "b": "'", "c": None} if self.conn.encoding == "UTF8": o["d"] = u"\xe0" a = HstoreAdapter(o) a.prepare(self.conn) q = a.getquoted() m = re.match(b(r"hstore\(ARRAY\[([^\]]+)\], ARRAY\[([^\]]+)\]\)"), q) self.assert_(m, repr(q)) kk = m.group(1).split(b(", ")) vv = m.group(2).split(b(", ")) ii = zip(kk, vv) ii.sort() def f(*args): return tuple([filter_scs(self.conn, s) for s in args]) self.assertEqual(len(ii), len(o)) self.assertEqual(ii[0], f(b("E'a'"), b("E'1'"))) self.assertEqual(ii[1], f(b("E'b'"), b("E''''"))) self.assertEqual(ii[2], f(b("E'c'"), b("NULL"))) if "d" in o: encc = u"\xe0".encode(psycopg2.extensions.encodings[self.conn.encoding]) self.assertEqual(ii[3], f(b("E'd'"), b("E'") + encc + b("'")))
def test_adapt_8(self): if self.conn.server_version >= 90000: return self.skipTest("skipping dict adaptation with PG pre-9 syntax") from psycopg2.extras import HstoreAdapter o = {"a": "1", "b": "'", "c": None} if self.conn.encoding == "UTF8": o["d"] = u"\xe0" a = HstoreAdapter(o) a.prepare(self.conn) q = a.getquoted() self.assert_(q.startswith(b("((")), q) ii = q[1:-1].split(b("||")) ii.sort() self.assertEqual(len(ii), len(o)) self.assertEqual(ii[0], filter_scs(self.conn, b("(E'a' => E'1')"))) self.assertEqual(ii[1], filter_scs(self.conn, b("(E'b' => E'''')"))) self.assertEqual(ii[2], filter_scs(self.conn, b("(E'c' => NULL)"))) if "d" in o: encc = u"\xe0".encode(psycopg2.extensions.encodings[self.conn.encoding]) self.assertEqual(ii[3], filter_scs(self.conn, b("(E'd' => E'") + encc + b("')")))
def test_adapt_8(self): if self.conn.server_version >= 90000: return self.skipTest("skipping dict adaptation with PG pre-9 syntax") from psycopg2.extras import HstoreAdapter o = {'a': '1', 'b': "'", 'c': None} if self.conn.encoding == 'UTF8': o['d'] = u'\xe0' a = HstoreAdapter(o) a.prepare(self.conn) q = a.getquoted() self.assert_(q.startswith("(("), q) self.assert_(q.endswith("))"), q) ii = q[1:-1].split("||") ii.sort() self.assertEqual(len(ii), len(o)) self.assertEqual(ii[0], filter_scs(self.conn, "(E'a' => E'1')")) self.assertEqual(ii[1], filter_scs(self.conn, "(E'b' => E'''')")) self.assertEqual(ii[2], filter_scs(self.conn, "(E'c' => NULL)")) if 'd' in o: encc = u'\xe0'.encode(psycopg2.extensions.encodings[self.conn.encoding]) self.assertEqual(ii[3], filter_scs(self.conn, "(E'd' => E'%s')" % encc))
def __str__(self): if self.connection: result = self.dumps() from psycopg2.extras import HstoreAdapter value = HstoreAdapter(result) value.prepare(self.connection.connection) return value.getquoted() else: return super(HStoreDict, self).__str__()
def test_register_globally(self): HstoreAdapter.get_oids(self.conn) register_hstore(self.conn, globally=True) conn2 = self.connect() try: cur2 = self.conn.cursor() cur2.execute("select 'a => b'::hstore") r = cur2.fetchone() self.assert_(isinstance(r[0], dict)) finally: conn2.close()
def __init__(self, adapted): ## remember value to be adaptated - a Python dict self.adapted = adapted ## remember type field of dict-value to be adapted if adapted.has_key('type'): self._type = adapted['type'] #del(adapted['type']) else: self._type = None ## create adapter to hstore if requested if self._type == 'hstore': self._hstoreAdapter = HstoreAdapter(adapted)
def skip_if_no_hstore_(self): from psycopg2.extras import HstoreAdapter oids = HstoreAdapter.get_oids(self.conn) if oids is None or not oids[0]: return self.skipTest("hstore not available in test database") return f(self)
class DictAdapter(object): """ A dictionary adapter converting Python dicts to PostgreSQL JSON, Hstore or Composite Types depending on the dict field 'type'. """ def __init__(self, adapted): ## remember value to be adaptated - a Python dict self.adapted = adapted ## remember type field of dict-value to be adapted if adapted.has_key('type'): self._type = adapted['type'] #del(adapted['type']) else: self._type = None ## create adapter to hstore if requested if self._type == 'hstore': self._hstoreAdapter = HstoreAdapter(adapted) def prepare(self, conn): self._conn = conn if self._type == 'hstore': self._hstoreAdapter.prepare(conn) def getquoted(self): if self._type is not None: if self._type == 'json': return adapt(Json(self.adapted)).getquoted() + '::json' elif self._type == 'hstore': return self._hstoreAdapter.getquoted() elif casters.has_key(self._type): c = casters[self._type] v = [] for n in c.attnames: v.append(self.adapted.get(n, None)) a = adapt(tuple(v)) a.prepare(self._conn) return a.getquoted() + '::' + self._type else: raise psycopg2.ProgrammingError( "unknown type %s in dictionary type hint" % self._type) else: raise psycopg2.ProgrammingError( "dictionary is missing type hint")
class DictAdapter(object): """ A dictionary adapter converting Python dicts to PostgreSQL JSON, Hstore or Composite Types depending on the dict field 'type'. """ def __init__(self, adapted): ## remember value to be adaptated - a Python dict self.adapted = adapted ## remember type field of dict-value to be adapted if adapted.has_key('type'): self._type = adapted['type'] #del(adapted['type']) else: self._type = None ## create adapter to hstore if requested if self._type == 'hstore': self._hstoreAdapter = HstoreAdapter(adapted) def prepare(self, conn): self._conn = conn if self._type == 'hstore': self._hstoreAdapter.prepare(conn) def getquoted(self): if self._type is not None: if self._type == 'json': return adapt(Json(self.adapted)).getquoted() + '::json' elif self._type == 'hstore': return self._hstoreAdapter.getquoted() elif casters.has_key(self._type): c = casters[self._type] v = [] for n in c.attnames: v.append(self.adapted.get(n, None)) a = adapt(tuple(v)) a.prepare(self._conn) return a.getquoted() + '::' + self._type else: raise psycopg2.ProgrammingError("unknown type %s in dictionary type hint" % self._type) else: raise psycopg2.ProgrammingError("dictionary is missing type hint")
def register_hstore_on_connection_creation(connection, sender, *args, **kwargs): dbname = connection.alias if dbname not in _oids: oids1, oids2 = HstoreAdapter.get_oids(connection.connection) if not oids1 and not oids2: raise DatabaseError("hstore isn't installed on this database") _oids[dbname] = (oids1[0], oids2[0]) oid, array_oid = _oids[dbname] register_hstore(connection.connection, globally=True, oid=oid, array_oid=array_oid)
def register_hstore(conn_or_curs, globally=False, _unicode=False, oid=None, array_oid=None): from psycopg2.extras import HstoreAdapter from psycopg2 import extensions as _ext import psycopg2 import sys import re as regex from .fields import HStoreDict def cast(s, cur, _bsdec=regex.compile(r"\\(.)")): if sys.version_info[0] < 3 and _unicode: result = HstoreAdapter.parse_unicode(s, cur) else: result = HstoreAdapter.parse(s, cur, _bsdec) return HStoreDict(result) if oid is None: oid = HstoreAdapter.get_oids(conn_or_curs) if oid is None or not oid[0]: raise psycopg2.ProgrammingError( "hstore type not found in the database. " "please install it from your 'contrib/hstore.sql' file") else: array_oid = oid[1] oid = oid[0] if isinstance(oid, int): oid = (oid, ) if array_oid is not None: if isinstance(array_oid, int): array_oid = (array_oid, ) else: array_oid = tuple([x for x in array_oid if x]) HSTORE = _ext.new_type(oid, str("HSTORE"), cast) _ext.register_type(HSTORE, not globally and conn_or_curs or None) _ext.register_adapter(dict, HstoreAdapter) if array_oid: HSTOREARRAY = _ext.new_array_type(array_oid, str("HSTOREARRAY"), HSTORE) _ext.register_type(HSTOREARRAY, not globally and conn_or_curs or None)
def register_hstore(conn_or_curs, globally=False, unicode=False, oid=None, array_oid=None): from psycopg2.extras import HstoreAdapter from psycopg2 import extensions as _ext import psycopg2 import sys import re as regex from .fields import HStoreDict def cast(s, cur, _bsdec=regex.compile(r"\\(.)")): if sys.version_info[0] < 3 and unicode: result = HstoreAdapter.parse_unicode(s, cur) else: result = HstoreAdapter.parse(s, cur, _bsdec) return HStoreDict(result) if oid is None: oid = HstoreAdapter.get_oids(conn_or_curs) if oid is None or not oid[0]: raise psycopg2.ProgrammingError( "hstore type not found in the database. " "please install it from your 'contrib/hstore.sql' file") else: array_oid = oid[1] oid = oid[0] if isinstance(oid, int): oid = (oid,) if array_oid is not None: if isinstance(array_oid, int): array_oid = (array_oid,) else: array_oid = tuple([x for x in array_oid if x]) HSTORE = _ext.new_type(oid, str("HSTORE"), cast) _ext.register_type(HSTORE, not globally and conn_or_curs or None) _ext.register_adapter(dict, HstoreAdapter) if array_oid: HSTOREARRAY = _ext.new_array_type(array_oid, str("HSTOREARRAY"), HSTORE) _ext.register_type(HSTOREARRAY, not globally and conn_or_curs or None)
def register_hstore_on_connection_creation(connection, sender, *args, **kwargs): oid = HstoreAdapter.get_oids(connection.connection) if oid is None or not oid[0]: if connection.connection.server_version < 90000: raise psycopg2.ProgrammingError("Database version not supported") elif connection.connection.server_version < 90100: pg_config = subprocess.Popen(["pg_config", "--sharedir"], stdout=subprocess.PIPE) share_dir = pg_config.communicate()[0].strip('\r\n ') hstore_sql = os.path.join(share_dir, 'contrib', 'hstore.sql') statements = re.compile(r";[ \t]*$", re.M) cursor = connection.cursor() with open(hstore_sql, 'U') as fp: for statement in statements.split(fp.read().decode(settings.FILE_CHARSET)): statement = re.sub(ur"--.*([\n\Z]|$)", "", statement).strip() if statement: cursor.execute(statement + u";") else: cursor = connection.cursor() cursor.execute("CREATE EXTENSION hstore;") register_hstore(connection.connection, globally=True)
def test_register_globally(self): from psycopg2.extras import register_hstore, HstoreAdapter oids = HstoreAdapter.get_oids(self.conn) try: register_hstore(self.conn, globally=True) conn2 = psycopg2.connect(dsn) try: cur2 = self.conn.cursor() cur2.execute("select 'a => b'::hstore") r = cur2.fetchone() self.assert_(isinstance(r[0], dict)) finally: conn2.close() finally: psycopg2.extensions.string_types.pop(oids[0][0]) # verify the caster is not around anymore cur = self.conn.cursor() cur.execute("select 'a => b'::hstore") r = cur.fetchone() self.assert_(isinstance(r[0], str))
def test_register_globally(self): from psycopg2.extras import register_hstore, HstoreAdapter oids = HstoreAdapter.get_oids(self.conn) try: register_hstore(self.conn, globally=True) conn2 = psycopg2.connect(dsn) try: cur2 = self.conn.cursor() cur2.execute("select 'a => b'::hstore") r = cur2.fetchone() self.assertTrue(isinstance(r[0], dict)) finally: conn2.close() finally: psycopg2.extensions.string_types.pop(oids[0][0]) # verify the caster is not around anymore cur = self.conn.cursor() cur.execute("select 'a => b'::hstore") r = cur.fetchone() self.assertTrue(isinstance(r[0], str))
def register_hstore_on_connection_creation(connection, sender, *args, **kwargs): oid = HstoreAdapter.get_oids(connection.connection) if oid is None or not oid[0]: if connection.connection.server_version < 90000: raise psycopg2.ProgrammingError("Database version not supported") elif connection.connection.server_version < 90100: pg_config = subprocess.Popen(["pg_config", "--sharedir"], stdout=subprocess.PIPE) share_dir = pg_config.communicate()[0].strip('\r\n ') hstore_sql = os.path.join(share_dir, 'contrib', 'hstore.sql') statements = re.compile(r";[ \t]*$", re.M) cursor = connection.cursor() with open(hstore_sql, 'U') as fp: for statement in statements.split(fp.read().decode( settings.FILE_CHARSET)): statement = re.sub(ur"--.*([\n\Z]|$)", "", statement).strip() if statement: cursor.execute(statement + u";") else: cursor = connection.cursor() cursor.execute("CREATE EXTENSION hstore;") register_hstore(connection.connection, globally=True)
def hstore(self, _dict): return HstoreAdapter(_dict)
def ok(s, d): self.assertEqual(HstoreAdapter.parse(s, None), d)
def cast(s, cur, _bsdec=regex.compile(r"\\(.)")): if sys.version_info[0] < 3 and _unicode: result = HstoreAdapter.parse_unicode(s, cur) else: result = HstoreAdapter.parse(s, cur, _bsdec) return HStoreDict(result)
def cast(s, cur, _bsdec=regex.compile(r"\\(.)")): if sys.version_info[0] < 3 and unicode: result = HstoreAdapter.parse_unicode(s, cur) else: result = HstoreAdapter.parse(s, cur, _bsdec) return HStoreDict(result, loaded=False)
def hstore_text_to_dict(text): return HstoreAdapter.parse(text, None)