2424from opentelemetry .test .test_base import TestBase
2525
2626
27+ # pylint: disable=too-many-public-methods
2728class TestDBApiIntegration (TestBase ):
2829 def setUp (self ):
2930 super ().setUp ()
@@ -252,6 +253,7 @@ def test_executemany(self):
252253
253254 def test_executemany_comment (self ):
254255 connect_module = mock .MagicMock ()
256+ connect_module .__name__ = "test"
255257 connect_module .__version__ = mock .MagicMock ()
256258 connect_module .__libpq_version__ = 123
257259 connect_module .apilevel = 123
@@ -260,7 +262,7 @@ def test_executemany_comment(self):
260262
261263 db_integration = dbapi .DatabaseApiIntegration (
262264 "testname" ,
263- "testcomponent " ,
265+ "postgresql " ,
264266 enable_commenter = True ,
265267 commenter_options = {"db_driver" : False , "dbapi_level" : False },
266268 connect_module = connect_module ,
@@ -275,8 +277,38 @@ def test_executemany_comment(self):
275277 r"Select 1 /\*dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;" ,
276278 )
277279
280+ def test_executemany_comment_non_pep_249_compliant (self ):
281+ class MockConnectModule :
282+ def __getattr__ (self , name ):
283+ if name == "__name__" :
284+ return "test"
285+ if name == "__version__" :
286+ return mock .MagicMock ()
287+ if name == "__libpq_version__" :
288+ return 123
289+ raise AttributeError ("attribute missing" )
290+
291+ connect_module = MockConnectModule ()
292+ db_integration = dbapi .DatabaseApiIntegration (
293+ "testname" ,
294+ "postgresql" ,
295+ enable_commenter = True ,
296+ connect_module = connect_module ,
297+ commenter_options = {"db_driver" : False },
298+ )
299+ mock_connection = db_integration .wrapped_connection (
300+ mock_connect , {}, {}
301+ )
302+ cursor = mock_connection .cursor ()
303+ cursor .executemany ("Select 1;" )
304+ self .assertRegex (
305+ cursor .query ,
306+ r"Select 1 /\*dbapi_level='1.0',dbapi_threadsafety='unknown',driver_paramstyle='unknown',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;" ,
307+ )
308+
278309 def test_compatible_build_version_psycopg_psycopg2_libpq (self ):
279310 connect_module = mock .MagicMock ()
311+ connect_module .__name__ = "test"
280312 connect_module .__version__ = mock .MagicMock ()
281313 connect_module .pq = mock .MagicMock ()
282314 connect_module .pq .__build_version__ = 123
@@ -286,7 +318,7 @@ def test_compatible_build_version_psycopg_psycopg2_libpq(self):
286318
287319 db_integration = dbapi .DatabaseApiIntegration (
288320 "testname" ,
289- "testcomponent " ,
321+ "postgresql " ,
290322 enable_commenter = True ,
291323 commenter_options = {"db_driver" : False , "dbapi_level" : False },
292324 connect_module = connect_module ,
@@ -301,8 +333,150 @@ def test_compatible_build_version_psycopg_psycopg2_libpq(self):
301333 r"Select 1 /\*dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;" ,
302334 )
303335
336+ def test_executemany_psycopg2_integration_comment (self ):
337+ connect_module = mock .MagicMock ()
338+ connect_module .__name__ = "psycopg2"
339+ connect_module .__version__ = "1.2.3"
340+ connect_module .__libpq_version__ = 123
341+ connect_module .apilevel = 123
342+ connect_module .threadsafety = 123
343+ connect_module .paramstyle = "test"
344+
345+ db_integration = dbapi .DatabaseApiIntegration (
346+ "testname" ,
347+ "postgresql" ,
348+ enable_commenter = True ,
349+ commenter_options = {"db_driver" : True , "dbapi_level" : False },
350+ connect_module = connect_module ,
351+ )
352+ mock_connection = db_integration .wrapped_connection (
353+ mock_connect , {}, {}
354+ )
355+ cursor = mock_connection .cursor ()
356+ cursor .executemany ("Select 1;" )
357+ self .assertRegex (
358+ cursor .query ,
359+ r"Select 1 /\*db_driver='psycopg2%%3A1.2.3',dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;" ,
360+ )
361+
362+ def test_executemany_psycopg_integration_comment (self ):
363+ connect_module = mock .MagicMock ()
364+ connect_module .__name__ = "psycopg"
365+ connect_module .__version__ = "1.2.3"
366+ connect_module .pq = mock .MagicMock ()
367+ connect_module .pq .__build_version__ = 123
368+ connect_module .apilevel = 123
369+ connect_module .threadsafety = 123
370+ connect_module .paramstyle = "test"
371+
372+ db_integration = dbapi .DatabaseApiIntegration (
373+ "testname" ,
374+ "postgresql" ,
375+ enable_commenter = True ,
376+ commenter_options = {"db_driver" : True , "dbapi_level" : False },
377+ connect_module = connect_module ,
378+ )
379+ mock_connection = db_integration .wrapped_connection (
380+ mock_connect , {}, {}
381+ )
382+ cursor = mock_connection .cursor ()
383+ cursor .executemany ("Select 1;" )
384+ self .assertRegex (
385+ cursor .query ,
386+ r"Select 1 /\*db_driver='psycopg%%3A1.2.3',dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;" ,
387+ )
388+
389+ def test_executemany_mysqlconnector_integration_comment (self ):
390+ connect_module = mock .MagicMock ()
391+ connect_module .__name__ = "mysql.connector"
392+ connect_module .__version__ = "1.2.3"
393+ connect_module .apilevel = 123
394+ connect_module .threadsafety = 123
395+ connect_module .paramstyle = "test"
396+
397+ db_integration = dbapi .DatabaseApiIntegration (
398+ "testname" ,
399+ "mysql" ,
400+ enable_commenter = True ,
401+ commenter_options = {"db_driver" : True , "dbapi_level" : False },
402+ connect_module = connect_module ,
403+ )
404+
405+ mock_connection = db_integration .wrapped_connection (
406+ mock_connect , {}, {}
407+ )
408+ cursor = mock_connection .cursor ()
409+ cursor .executemany ("Select 1;" )
410+ self .assertRegex (
411+ cursor .query ,
412+ r"Select 1 /\*db_driver='mysql.connector%%3A1.2.3',dbapi_threadsafety=123,driver_paramstyle='test',mysql_client_version='1.2.3',traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;" ,
413+ )
414+
415+ @mock .patch ("opentelemetry.instrumentation.dbapi.util_version" )
416+ def test_executemany_mysqlclient_integration_comment (
417+ self ,
418+ mock_dbapi_util_version ,
419+ ):
420+ mock_dbapi_util_version .return_value = "1.2.3"
421+ connect_module = mock .MagicMock ()
422+ connect_module .__name__ = "MySQLdb"
423+ connect_module .__version__ = "1.2.3"
424+ connect_module .apilevel = 123
425+ connect_module .threadsafety = 123
426+ connect_module .paramstyle = "test"
427+ connect_module ._mysql = mock .MagicMock ()
428+ connect_module ._mysql .get_client_info = mock .MagicMock (
429+ return_value = "123"
430+ )
431+
432+ db_integration = dbapi .DatabaseApiIntegration (
433+ "testname" ,
434+ "mysql" ,
435+ enable_commenter = True ,
436+ commenter_options = {"db_driver" : True , "dbapi_level" : False },
437+ connect_module = connect_module ,
438+ )
439+
440+ mock_connection = db_integration .wrapped_connection (
441+ mock_connect , {}, {}
442+ )
443+ cursor = mock_connection .cursor ()
444+ cursor .executemany ("Select 1;" )
445+ self .assertRegex (
446+ cursor .query ,
447+ r"Select 1 /\*db_driver='MySQLdb%%3A1.2.3',dbapi_threadsafety=123,driver_paramstyle='test',mysql_client_version='123',traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;" ,
448+ )
449+
450+ def test_executemany_pymysql_integration_comment (self ):
451+ connect_module = mock .MagicMock ()
452+ connect_module .__name__ = "pymysql"
453+ connect_module .__version__ = "1.2.3"
454+ connect_module .apilevel = 123
455+ connect_module .threadsafety = 123
456+ connect_module .paramstyle = "test"
457+ connect_module .get_client_info = mock .MagicMock (return_value = "123" )
458+
459+ db_integration = dbapi .DatabaseApiIntegration (
460+ "testname" ,
461+ "mysql" ,
462+ enable_commenter = True ,
463+ commenter_options = {"db_driver" : True , "dbapi_level" : False },
464+ connect_module = connect_module ,
465+ )
466+
467+ mock_connection = db_integration .wrapped_connection (
468+ mock_connect , {}, {}
469+ )
470+ cursor = mock_connection .cursor ()
471+ cursor .executemany ("Select 1;" )
472+ self .assertRegex (
473+ cursor .query ,
474+ r"Select 1 /\*db_driver='pymysql%%3A1.2.3',dbapi_threadsafety=123,driver_paramstyle='test',mysql_client_version='123',traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;" ,
475+ )
476+
304477 def test_executemany_flask_integration_comment (self ):
305478 connect_module = mock .MagicMock ()
479+ connect_module .__name__ = "test"
306480 connect_module .__version__ = mock .MagicMock ()
307481 connect_module .__libpq_version__ = 123
308482 connect_module .apilevel = 123
@@ -311,7 +485,7 @@ def test_executemany_flask_integration_comment(self):
311485
312486 db_integration = dbapi .DatabaseApiIntegration (
313487 "testname" ,
314- "testcomponent " ,
488+ "postgresql " ,
315489 enable_commenter = True ,
316490 commenter_options = {"db_driver" : False , "dbapi_level" : False },
317491 connect_module = connect_module ,
@@ -332,6 +506,11 @@ def test_executemany_flask_integration_comment(self):
332506 r"Select 1 /\*dbapi_threadsafety=123,driver_paramstyle='test',flask=1,libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;" ,
333507 )
334508
509+ clear_context = context .set_value (
510+ "SQLCOMMENTER_ORM_TAGS_AND_VALUES" , {}, current_context
511+ )
512+ context .attach (clear_context )
513+
335514 def test_callproc (self ):
336515 db_integration = dbapi .DatabaseApiIntegration (
337516 "testname" , "testcomponent"
@@ -415,6 +594,12 @@ class MockCursor:
415594 def __init__ (self ) -> None :
416595 self .query = ""
417596 self .params = None
597+ # Mock mysql.connector modules and method
598+ self ._cnx = mock .MagicMock ()
599+ self ._cnx ._cmysql = mock .MagicMock ()
600+ self ._cnx ._cmysql .get_client_info = mock .MagicMock (
601+ return_value = "1.2.3"
602+ )
418603
419604 # pylint: disable=unused-argument, no-self-use
420605 def execute (self , query , params = None , throw_exception = False ):
0 commit comments