mirror of
				https://github.com/psycopg/psycopg2.git
				synced 2025-10-31 07:47:30 +03:00 
			
		
		
		
	Validate output result from make_dsn()
The output is not necessarily munged anyway: if no keyword is passed, validate the input but return it untouched.
This commit is contained in:
		
							parent
							
								
									7155d06cdc
								
							
						
					
					
						commit
						7aab934ae5
					
				|  | @ -493,15 +493,19 @@ Other functions | |||
| 
 | ||||
| .. function:: make_dsn(dsn=None, \*\*kwargs) | ||||
| 
 | ||||
|     Create a connection string from arguments. | ||||
|     Create a valid connection string from arguments. | ||||
| 
 | ||||
|     Put together the arguments in *kwargs* into a connection string. If *dsn* | ||||
|     is specified too, merge the arguments coming from both the sources. If the | ||||
|     same argument is specified in both the sources, the *kwargs* version | ||||
|     overrides the *dsn* version | ||||
|     overrides the *dsn* version. | ||||
| 
 | ||||
|     At least one param is required (either *dsn* or any keyword). Note that | ||||
|     the empty string is a valid connection string. | ||||
|     At least one parameter is required (either *dsn* or any keyword). Note | ||||
|     that the empty string is a valid connection string. | ||||
| 
 | ||||
|     The input arguments are validated: the output should always be a valid | ||||
|     connection string (as far as `parse_dsn()` is concerned). If not raise | ||||
|     `~psycopg2.ProgrammingError`. | ||||
| 
 | ||||
|     Example:: | ||||
| 
 | ||||
|  | @ -516,17 +520,27 @@ Other functions | |||
| 
 | ||||
|     Parse connection string into a dictionary of keywords and values. | ||||
| 
 | ||||
|     Uses libpq's ``PQconninfoParse`` to parse the string according to | ||||
|     accepted format(s) and check for supported keywords. | ||||
|     Parsing is delegated to the libpq: different versions of the client | ||||
|     library may support different formats or parameters (for example, | ||||
|     `connection URIs`__ are only supported from libpq 9.2).  Raise | ||||
|     `~psycopg2.ProgrammingError` if the *dsn* is not valid. | ||||
| 
 | ||||
|     .. __: http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING | ||||
| 
 | ||||
|     Example:: | ||||
| 
 | ||||
|         >>> from psycopg2.extensions import parse_dsn | ||||
|         >>> parse_dsn('dbname=test user=postgres password=secret') | ||||
|         {'password': 'secret', 'user': 'postgres', 'dbname': 'test'} | ||||
|         >>> parse_dsn("postgresql://someone@example.com/somedb?connect_timeout=10") | ||||
|         {'host': 'example.com', 'user': 'someone', 'dbname': 'somedb', 'connect_timeout': '10'} | ||||
| 
 | ||||
|     .. versionadded:: 2.7 | ||||
| 
 | ||||
|     .. seealso:: libpq docs for `PQconninfoParse()`__. | ||||
| 
 | ||||
|         .. __: http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PQCONNINFOPARSE | ||||
| 
 | ||||
| 
 | ||||
| .. function:: quote_ident(str, scope) | ||||
| 
 | ||||
|  |  | |||
|  | @ -160,8 +160,9 @@ def make_dsn(dsn=None, **kwargs): | |||
|     if dsn is None and not kwargs: | ||||
|         raise TypeError('missing dsn and no parameters') | ||||
| 
 | ||||
|     # If no kwarg is specified don't mung the dsn | ||||
|     # If no kwarg is specified don't mung the dsn, but verify it | ||||
|     if not kwargs: | ||||
|         parse_dsn(dsn) | ||||
|         return dsn | ||||
| 
 | ||||
|     # Override the dsn with the parameters | ||||
|  | @ -178,6 +179,10 @@ def make_dsn(dsn=None, **kwargs): | |||
| 
 | ||||
|     dsn = " ".join(["%s=%s" % (k, _param_escape(str(v))) | ||||
|         for (k, v) in kwargs.iteritems()]) | ||||
| 
 | ||||
|     # verify that the returned dsn is valid | ||||
|     parse_dsn(dsn) | ||||
| 
 | ||||
|     return dsn | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -133,7 +133,7 @@ psyco_parse_dsn(PyObject *self, PyObject *args, PyObject *kwargs) | |||
|     options = PQconninfoParse(Bytes_AS_STRING(dsn), &err); | ||||
|     if (options == NULL) { | ||||
|         if (err != NULL) { | ||||
|             PyErr_Format(ProgrammingError, "error parsing the dsn: %s", err); | ||||
|             PyErr_Format(ProgrammingError, "invalid dsn: %s", err); | ||||
|             PQfreemem(err); | ||||
|         } else { | ||||
|             PyErr_SetString(OperationalError, "PQconninfoParse() failed"); | ||||
|  |  | |||
|  | @ -388,53 +388,64 @@ class MakeDsnTestCase(ConnectingTestCase): | |||
|         dsn = ext.make_dsn('') | ||||
|         self.assertEqual(dsn, '') | ||||
| 
 | ||||
|     def test_params_validation(self): | ||||
|         self.assertRaises(psycopg2.ProgrammingError, | ||||
|             ext.make_dsn, 'dbnamo=a') | ||||
|         self.assertRaises(psycopg2.ProgrammingError, | ||||
|             ext.make_dsn, dbnamo='a') | ||||
|         self.assertRaises(psycopg2.ProgrammingError, | ||||
|             ext.make_dsn, 'dbname=a', nosuchparam='b') | ||||
| 
 | ||||
|     def test_empty_param(self): | ||||
|         dsn = ext.make_dsn(database='sony', password='') | ||||
|         dsn = ext.make_dsn(dbname='sony', password='') | ||||
|         self.assertDsnEqual(dsn, "dbname=sony password=''") | ||||
| 
 | ||||
|     def test_escape(self): | ||||
|         dsn = ext.make_dsn(database='hello world') | ||||
|         dsn = ext.make_dsn(dbname='hello world') | ||||
|         self.assertEqual(dsn, "dbname='hello world'") | ||||
| 
 | ||||
|         dsn = ext.make_dsn(database=r'back\slash') | ||||
|         dsn = ext.make_dsn(dbname=r'back\slash') | ||||
|         self.assertEqual(dsn, r"dbname=back\\slash") | ||||
| 
 | ||||
|         dsn = ext.make_dsn(database="quo'te") | ||||
|         dsn = ext.make_dsn(dbname="quo'te") | ||||
|         self.assertEqual(dsn, r"dbname=quo\'te") | ||||
| 
 | ||||
|         dsn = ext.make_dsn(database="with\ttab") | ||||
|         dsn = ext.make_dsn(dbname="with\ttab") | ||||
|         self.assertEqual(dsn, "dbname='with\ttab'") | ||||
| 
 | ||||
|         dsn = ext.make_dsn(database=r"\every thing'") | ||||
|         dsn = ext.make_dsn(dbname=r"\every thing'") | ||||
|         self.assertEqual(dsn, r"dbname='\\every thing\''") | ||||
| 
 | ||||
|     def test_database_is_a_keyword(self): | ||||
|         self.assertEqual(ext.make_dsn(database='sigh'), "dbname=sigh") | ||||
| 
 | ||||
|     def test_params_merging(self): | ||||
|         dsn = ext.make_dsn('dbname=foo', database='bar') | ||||
|         self.assertEqual(dsn, 'dbname=bar') | ||||
|         dsn = ext.make_dsn('dbname=foo host=bar', host='baz') | ||||
|         self.assertDsnEqual(dsn, 'dbname=foo host=baz') | ||||
| 
 | ||||
|         dsn = ext.make_dsn('dbname=foo', user='postgres') | ||||
|         self.assertDsnEqual(dsn, 'dbname=foo user=postgres') | ||||
| 
 | ||||
|     def test_no_dsn_munging(self): | ||||
|         dsn = ext.make_dsn('nosuchparam=whatevs') | ||||
|         self.assertEqual(dsn, 'nosuchparam=whatevs') | ||||
| 
 | ||||
|         dsn = ext.make_dsn(nosuchparam='whatevs') | ||||
|         self.assertEqual(dsn, 'nosuchparam=whatevs') | ||||
| 
 | ||||
|         self.assertRaises(psycopg2.ProgrammingError, | ||||
|             ext.make_dsn, 'nosuchparam=whatevs', andthis='either') | ||||
|         dsnin = 'dbname=a host=b user=c password=d' | ||||
|         dsn = ext.make_dsn(dsnin) | ||||
|         self.assertEqual(dsn, dsnin) | ||||
| 
 | ||||
|     @skip_before_libpq(9, 2) | ||||
|     def test_url_is_cool(self): | ||||
|         dsn = ext.make_dsn('postgresql://tester:secret@/test') | ||||
|         self.assertEqual(dsn, 'postgresql://tester:secret@/test') | ||||
|         url = 'postgresql://tester:secret@/test?application_name=wat' | ||||
|         dsn = ext.make_dsn(url) | ||||
|         self.assertEqual(dsn, url) | ||||
| 
 | ||||
|         dsn = ext.make_dsn('postgresql://tester:secret@/test', | ||||
|             application_name='woot') | ||||
|         dsn = ext.make_dsn(url, application_name='woot') | ||||
|         self.assertDsnEqual(dsn, | ||||
|             'dbname=test user=tester password=secret application_name=woot') | ||||
| 
 | ||||
|         self.assertRaises(psycopg2.ProgrammingError, | ||||
|             ext.make_dsn, 'postgresql://tester:secret@/test?nosuch=param') | ||||
|         self.assertRaises(psycopg2.ProgrammingError, | ||||
|             ext.make_dsn, url, nosuch="param") | ||||
| 
 | ||||
| 
 | ||||
| class IsolationLevelsTestCase(ConnectingTestCase): | ||||
| 
 | ||||
|  |  | |||
|  | @ -62,8 +62,8 @@ class ConnectTestCase(unittest.TestCase): | |||
|         self.assertEqual(self.args[2], False) | ||||
| 
 | ||||
|     def test_dsn(self): | ||||
|         psycopg2.connect('dbname=blah x=y') | ||||
|         self.assertEqual(self.args[0], 'dbname=blah x=y') | ||||
|         psycopg2.connect('dbname=blah host=y') | ||||
|         self.assertEqual(self.args[0], 'dbname=blah host=y') | ||||
|         self.assertEqual(self.args[1], None) | ||||
|         self.assertEqual(self.args[2], False) | ||||
| 
 | ||||
|  | @ -88,31 +88,31 @@ class ConnectTestCase(unittest.TestCase): | |||
|         self.assertEqual(len(self.args[0].split()), 4) | ||||
| 
 | ||||
|     def test_generic_keywords(self): | ||||
|         psycopg2.connect(foo='bar') | ||||
|         self.assertEqual(self.args[0], 'foo=bar') | ||||
|         psycopg2.connect(options='stuff') | ||||
|         self.assertEqual(self.args[0], 'options=stuff') | ||||
| 
 | ||||
|     def test_factory(self): | ||||
|         def f(dsn, async=False): | ||||
|             pass | ||||
| 
 | ||||
|         psycopg2.connect(database='foo', bar='baz', connection_factory=f) | ||||
|         self.assertDsnEqual(self.args[0], 'dbname=foo bar=baz') | ||||
|         psycopg2.connect(database='foo', host='baz', connection_factory=f) | ||||
|         self.assertDsnEqual(self.args[0], 'dbname=foo host=baz') | ||||
|         self.assertEqual(self.args[1], f) | ||||
|         self.assertEqual(self.args[2], False) | ||||
| 
 | ||||
|         psycopg2.connect("dbname=foo bar=baz", connection_factory=f) | ||||
|         self.assertDsnEqual(self.args[0], 'dbname=foo bar=baz') | ||||
|         psycopg2.connect("dbname=foo host=baz", connection_factory=f) | ||||
|         self.assertDsnEqual(self.args[0], 'dbname=foo host=baz') | ||||
|         self.assertEqual(self.args[1], f) | ||||
|         self.assertEqual(self.args[2], False) | ||||
| 
 | ||||
|     def test_async(self): | ||||
|         psycopg2.connect(database='foo', bar='baz', async=1) | ||||
|         self.assertDsnEqual(self.args[0], 'dbname=foo bar=baz') | ||||
|         psycopg2.connect(database='foo', host='baz', async=1) | ||||
|         self.assertDsnEqual(self.args[0], 'dbname=foo host=baz') | ||||
|         self.assertEqual(self.args[1], None) | ||||
|         self.assert_(self.args[2]) | ||||
| 
 | ||||
|         psycopg2.connect("dbname=foo bar=baz", async=True) | ||||
|         self.assertDsnEqual(self.args[0], 'dbname=foo bar=baz') | ||||
|         psycopg2.connect("dbname=foo host=baz", async=True) | ||||
|         self.assertDsnEqual(self.args[0], 'dbname=foo host=baz') | ||||
|         self.assertEqual(self.args[1], None) | ||||
|         self.assert_(self.args[2]) | ||||
| 
 | ||||
|  | @ -143,16 +143,6 @@ class ConnectTestCase(unittest.TestCase): | |||
|         psycopg2.connect('dbname=foo', user='postgres') | ||||
|         self.assertDsnEqual(self.args[0], 'dbname=foo user=postgres') | ||||
| 
 | ||||
|     def test_no_dsn_munging(self): | ||||
|         psycopg2.connect('nosuchparam=whatevs') | ||||
|         self.assertEqual(self.args[0], 'nosuchparam=whatevs') | ||||
| 
 | ||||
|         psycopg2.connect(nosuchparam='whatevs') | ||||
|         self.assertEqual(self.args[0], 'nosuchparam=whatevs') | ||||
| 
 | ||||
|         self.assertRaises(psycopg2.ProgrammingError, | ||||
|             psycopg2.connect, 'nosuchparam=whatevs', andthis='either') | ||||
| 
 | ||||
| 
 | ||||
| class ExceptionsTestCase(ConnectingTestCase): | ||||
|     def test_attributes(self): | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user