66Protocol version 3.0 client and tools.
77"""
88import os
9- from traceback import format_exception_only
9+ from . buffer import pq_message_stream
1010from . import element3 as element
1111from . import xact3 as xact
12- from .buffer import pq_message_stream
13- from .typstruct import long_pack
14-
15- def cat_messages (messages ):
16- blen = bytes .__len__
17- lpack = long_pack
18- return b'' .join ([
19- x .bytes () if x .__class__ is not bytes else (
20- b'd' + lpack (blen (x ) + 4 ) + x
21- ) for x in messages
22- ])
12+
13+ __all__ = ('Connection' ,)
14+
2315try :
2416 from .optimized import cat_messages
2517except ImportError :
26- pass
18+ from .typstruct import long_pack
19+ def cat_messages (messages , lpack = long_pack , blen = bytes .__len__ ):
20+ return b'' .join ([
21+ x .bytes () if x .__class__ is not bytes else (
22+ b'd' + lpack (blen (x ) + 4 ) + x
23+ ) for x in messages
24+ ])
25+ del long_pack
26+
27+ client_detected_protocol_error = element .ClientError ((
28+ (b'S' , 'FATAL' ),
29+ (b'C' , '08P01' ),
30+ (b'M' , "wire-data caused exception in protocol transaction" ),
31+ (b'H' , "Protocol error detected." ),
32+ ))
33+
34+ client_connect_timeout = element .ClientError ((
35+ (b'S' , 'FATAL' ),
36+ (b'C' , '--TOE' ),
37+ (b'M' , "connect timed out" ),
38+ ))
39+
40+ not_pq_error = element .ClientError ((
41+ # ProtocolError
42+ (b'S' , 'FATAL' ),
43+ (b'C' , '08P01' ),
44+ (b'M' , 'server did not support SSL negotiation' ),
45+ (b'H' , 'The server is probably not PostgreSQL.' ),
46+ ))
47+
48+ no_ssl_error = element .ClientError ((
49+ (b'S' , 'FATAL' ),
50+ # InsecurityError
51+ (b'C' , '--SEC' ),
52+ (b'M' , 'SSL was required, and the server could not accommodate' ),
53+ ))
54+
55+ # Details in __context__
56+ ssl_failed_error = element .ClientError ((
57+ (b'S' , 'FATAL' ),
58+ # InsecurityError
59+ (b'C' , '--SEC' ),
60+ (b'M' , 'SSL negotiation caused exception' ),
61+ ))
62+
63+ # failed to complete the connection, but no error set.
64+ # indicates a programmer error.
65+ partial_connection_error = element .ClientError ((
66+ (b'S' , 'FATAL' ),
67+ (b'C' , '--XXX' ),
68+ (b'M' , "failed to complete negotiation" ),
69+ (b'H' , "Negotiation failed to completed, but no " \
70+ "error was attributed on the connection." ),
71+ ))
72+
73+ eof_error = element .ClientError ((
74+ (b'S' , 'FATAL' ),
75+ (b'C' , '08006' ),
76+ (b'M' , 'unexpected EOF from server' ),
77+ (b'D' , "Zero-length read from the connection's socket." ),
78+ ))
2779
2880class Connection (object ):
2981 """
@@ -103,11 +155,7 @@ def connect(self, ssl = None, timeout = None):
103155 self .xact .fatal = True
104156 self .xact .exception = err
105157 if self .socket_factory .timed_out (err ):
106- self .xact .error_message = element .ClientError ((
107- (b'S' , 'FATAL' ),
108- (b'C' , '--TOE' ),
109- (b'M' , "connect timed out (%s seconds)" % (timeout ,)),
110- ))
158+ self .xact .error_message = client_connect_timeout
111159 else :
112160 errmsg = self .socket_factory .fatal_exception_message (err )
113161 # It's an error that occurred during socket creation/connection.
@@ -132,13 +180,7 @@ def connect(self, ssl = None, timeout = None):
132180 # probably not PQv3..
133181 self .socket .close ()
134182 self .xact .fatal = True
135- self .xact .error_message = element .ClientError ((
136- # ProtocolError
137- (b'S' , 'FATAL' ),
138- (b'C' , '08P01' ),
139- (b'M' , 'server did not support SSL negotiation' ),
140- (b'H' , 'The server is probably not PostgreSQL.' ),
141- ))
183+ self .xact .error_message = not_pq_error
142184 self .xact .state = xact .Complete
143185 return
144186
@@ -147,12 +189,7 @@ def connect(self, ssl = None, timeout = None):
147189 # ssl is required..
148190 self .socket .close ()
149191 self .xact .fatal = True
150- self .xact .error_message = element .ClientError ((
151- (b'S' , 'FATAL' ),
152- # InsecurityError
153- (b'C' , '--SEC' ),
154- (b'M' , 'SSL was required, and the server could not accommodate' ),
155- ))
192+ self .xact .error_message = no_ssl_error
156193 self .xact .state = xact .Complete
157194 return
158195
@@ -166,12 +203,7 @@ def connect(self, ssl = None, timeout = None):
166203 self .xact .exception = err
167204 self .xact .fatal = True
168205 self .xact .state = xact .Complete
169- self .xact .error_message = element .ClientError ((
170- (b'S' , 'FATAL' ),
171- # InsecurityError
172- (b'C' , '--SEC' ),
173- (b'M' , 'SSL negotiation caused exception' ),
174- ))
206+ self .xact .error_message = ssl_failed_error
175207 return
176208 # time to negotiate
177209 negxact = self .xact
@@ -185,13 +217,7 @@ def connect(self, ssl = None, timeout = None):
185217 self .socket .close ()
186218 self .xact .fatal = True
187219 self .xact .state = xact .Complete
188- self .xact .error_message = element .ClientError ((
189- (b'S' , 'FATAL' ),
190- (b'C' , '--XXX' ),
191- (b'M' , "failed to complete negotiation" ),
192- (b'H' , "Negotiation failed to completed, but no " \
193- "error was attributed on the connection." ),
194- ))
220+ self .xact .error_message = partial_connection_error
195221
196222 def negotiate_ssl (self ) -> (bool , None ):
197223 """
@@ -253,13 +279,7 @@ def read_into(self):
253279 self .socket .close ()
254280 self .xact .state = xact .Complete
255281 self .xact .fatal = True
256- self .xact .error_message = element .ClientError ((
257- (b'S' , 'FATAL' ),
258- (b'C' , '08006' ),
259- (b'M' , 'unexpected EOF from server' ),
260- (b'D' , "Zero-length read " \
261- "from the connection's socket." ),
262- ))
282+ self .xact .error_message = eof_error
263283 return False
264284
265285 # Got data. Put it in the buffer and clear read_data.
@@ -463,12 +483,7 @@ def complete(self):
463483 x .fatal = True
464484 x .state = xact .Complete
465485 x .exception = proto_exc
466- x .error_message = element .ClientError ((
467- (b'S' , 'FATAL' ),
468- (b'C' , '08P01' ),
469- (b'M' , "wire-data caused exception in protocol transaction" ),
470- (b'H' , "Protocol error detected." ),
471- ))
486+ x .error_message = client_detected_protocol_error
472487 self .state = b''
473488 return
474489 self .state = getattr (x , 'last_ready' , self .state )
0 commit comments