mirror of
				https://github.com/psycopg/psycopg2.git
				synced 2025-11-04 09:47:30 +03:00 
			
		
		
		
	Merge branch 'none-in-composite' into python2
This commit is contained in:
		
						commit
						f9be48d89e
					
				
							
								
								
									
										7
									
								
								NEWS-2.3
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								NEWS-2.3
									
									
									
									
									
								
							| 
						 | 
					@ -1,3 +1,10 @@
 | 
				
			||||||
 | 
					What's new in psycopg 2.3.3
 | 
				
			||||||
 | 
					---------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - Fixed adaptation of None in composite types (ticket #26). Bug report by
 | 
				
			||||||
 | 
					    Karsten Hilbert.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What's new in psycopg 2.3.2
 | 
					What's new in psycopg 2.3.2
 | 
				
			||||||
---------------------------
 | 
					---------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,6 +82,7 @@ from _psycopg import __version__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import psycopg2.extensions as _ext
 | 
					import psycopg2.extensions as _ext
 | 
				
			||||||
_ext.register_adapter(tuple, _ext.SQL_IN)
 | 
					_ext.register_adapter(tuple, _ext.SQL_IN)
 | 
				
			||||||
 | 
					_ext.register_adapter(type(None), _ext.NoneAdapter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__all__ = filter(lambda k: not k.startswith('_'), locals().keys())
 | 
					__all__ = filter(lambda k: not k.startswith('_'), locals().keys())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,4 +128,17 @@ class SQL_IN(object):
 | 
				
			||||||
    __str__ = getquoted
 | 
					    __str__ = getquoted
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NoneAdapter(object):
 | 
				
			||||||
 | 
					    """Adapt None to NULL.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This adapter is not used normally as a fast path in mogrify uses NULL,
 | 
				
			||||||
 | 
					    but it makes easier to adapt composite types.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def __init__(self, obj):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getquoted(self):
 | 
				
			||||||
 | 
					        return "NULL"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__all__ = filter(lambda k: not k.startswith('_'), locals().keys())
 | 
					__all__ = filter(lambda k: not k.startswith('_'), locals().keys())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,11 +136,6 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
 | 
				
			||||||
       because the ISQLQuote type is abstract and there is no way to get a
 | 
					       because the ISQLQuote type is abstract and there is no way to get a
 | 
				
			||||||
       quotable object to be its instance */
 | 
					       quotable object to be its instance */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* None is always adapted to NULL */
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (obj == Py_None)
 | 
					 | 
				
			||||||
        return PyString_FromString("NULL");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Dprintf("microprotocols_adapt: trying to adapt %s", obj->ob_type->tp_name);
 | 
					    Dprintf("microprotocols_adapt: trying to adapt %s", obj->ob_type->tp_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* look for an adapter in the registry */
 | 
					    /* look for an adapter in the registry */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -349,6 +349,42 @@ class HstoreTestCase(unittest.TestCase):
 | 
				
			||||||
        ok(dict(zip(ab, ab)))
 | 
					        ok(dict(zip(ab, ab)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AdaptTypeTestCase(unittest.TestCase):
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        self.conn = psycopg2.connect(tests.dsn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def tearDown(self):
 | 
				
			||||||
 | 
					        self.conn.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_none_in_record(self):
 | 
				
			||||||
 | 
					        curs = self.conn.cursor()
 | 
				
			||||||
 | 
					        s = curs.mogrify("SELECT %s;", [(42, None)])
 | 
				
			||||||
 | 
					        self.assertEqual("SELECT (42, NULL);", s)
 | 
				
			||||||
 | 
					        curs.execute("SELECT %s;", [(42, None)])
 | 
				
			||||||
 | 
					        d = curs.fetchone()[0]
 | 
				
			||||||
 | 
					        self.assertEqual("(42,)", d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_none_fast_path(self):
 | 
				
			||||||
 | 
					        # the None adapter is not actually invoked in regular adaptation
 | 
				
			||||||
 | 
					        ext = psycopg2.extensions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class WonkyAdapter(object):
 | 
				
			||||||
 | 
					            def __init__(self, obj): pass
 | 
				
			||||||
 | 
					            def getquoted(self): return "NOPE!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        curs = self.conn.cursor()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        orig_adapter = ext.adapters[type(None), ext.ISQLQuote]
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            ext.register_adapter(type(None), WonkyAdapter)
 | 
				
			||||||
 | 
					            self.assertEqual(ext.adapt(None).getquoted(), "NOPE!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            s = curs.mogrify("SELECT %s;", (None,))
 | 
				
			||||||
 | 
					            self.assertEqual("SELECT NULL;", s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            ext.register_adapter(type(None), orig_adapter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_suite():
 | 
					def test_suite():
 | 
				
			||||||
    return unittest.TestLoader().loadTestsFromName(__name__)
 | 
					    return unittest.TestLoader().loadTestsFromName(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user