@@ -90,6 +90,38 @@ class ClientTestSuite(unittest.TestCase):
9090 "enable_telemetry" : False ,
9191 }
9292
93+ @patch ("%s.client.Session" % PACKAGE_NAME )
94+ def test_del_does_not_raise_when_session_never_set (self , mock_session_class ):
95+ """A constructor-stage failure must not leave __del__ raising on GC.
96+
97+ When the Session constructor raises before ``self.session`` is assigned
98+ in Connection.__init__, the original error must propagate, and __del__ on
99+ the half-constructed Connection must not raise (which Python reports as an
100+ 'Exception ignored in __del__' referencing the missing ``session``
101+ attribute). See https://github.com/databricks/databricks-sql-python/issues/746
102+ """
103+ mock_session_class .side_effect = ValueError ("bad auth" )
104+
105+ unraisable = []
106+ original_hook = sys .unraisablehook
107+ sys .unraisablehook = lambda args : unraisable .append (args )
108+ try :
109+ with self .assertRaises (ValueError ):
110+ client .Connection (** self .DUMMY_CONNECTION_ARGS )
111+
112+ # Force collection of the half-constructed Connection so __del__ runs.
113+ gc .collect ()
114+ finally :
115+ sys .unraisablehook = original_hook
116+
117+ messages = [
118+ "{}: {}" .format (type (u .exc_value ).__name__ , u .exc_value )
119+ for u in unraisable
120+ ]
121+ self .assertEqual (
122+ unraisable , [], "Exception(s) raised in __del__: {}" .format (messages )
123+ )
124+
93125 @patch ("%s.session.ThriftDatabricksClient" % PACKAGE_NAME )
94126 def test_closing_connection_closes_commands (self , mock_thrift_client_class ):
95127 """Test that closing a connection properly closes commands.
0 commit comments