bpo-37027: Return a proxy socket object from transp.get_extra_info('s… · python/cpython@8cd5165
1+import socket
2+import warnings
3+4+5+class TransportSocket:
6+7+"""A socket-like wrapper for exposing real transport sockets.
8+9+ These objects can be safely returned by APIs like
10+ `transport.get_extra_info('socket')`. All potentially disruptive
11+ operations (like "socket.close()") are banned.
12+ """
13+14+__slots__ = ('_sock',)
15+16+def __init__(self, sock: socket.socket):
17+self._sock = sock
18+19+def _na(self, what):
20+warnings.warn(
21+f"Using {what} on sockets returned from get_extra_info('socket') "
22+f"will be prohibited in asyncio 3.9. Please report your use case "
23+f"to bugs.python.org.",
24+DeprecationWarning, source=self)
25+26+@property
27+def family(self):
28+return self._sock.family
29+30+@property
31+def type(self):
32+return self._sock.type
33+34+@property
35+def proto(self):
36+return self._sock.proto
37+38+def __repr__(self):
39+s = (
40+f"<asyncio.TransportSocket fd={self.fileno()}, "
41+f"family={self.family!s}, type={self.type!s}, "
42+f"proto={self.proto}"
43+ )
44+45+if self.fileno() != -1:
46+try:
47+laddr = self.getsockname()
48+if laddr:
49+s = f"{s}, laddr={laddr}"
50+except socket.error:
51+pass
52+try:
53+raddr = self.getpeername()
54+if raddr:
55+s = f"{s}, raddr={raddr}"
56+except socket.error:
57+pass
58+59+return f"{s}>"
60+61+def __getstate__(self):
62+raise TypeError("Cannot serialize asyncio.TransportSocket object")
63+64+def fileno(self):
65+return self._sock.fileno()
66+67+def dup(self):
68+return self._sock.dup()
69+70+def get_inheritable(self):
71+return self._sock.get_inheritable()
72+73+def shutdown(self, how):
74+# asyncio doesn't currently provide a high-level transport API
75+# to shutdown the connection.
76+self._sock.shutdown(how)
77+78+def getsockopt(self, *args, **kwargs):
79+return self._sock.getsockopt(*args, **kwargs)
80+81+def setsockopt(self, *args, **kwargs):
82+self._sock.setsockopt(*args, **kwargs)
83+84+def getpeername(self):
85+return self._sock.getpeername()
86+87+def getsockname(self):
88+return self._sock.getsockname()
89+90+def getsockbyname(self):
91+return self._sock.getsockbyname()
92+93+def accept(self):
94+self._na('accept() method')
95+return self._sock.accept()
96+97+def connect(self, *args, **kwargs):
98+self._na('connect() method')
99+return self._sock.connect(*args, **kwargs)
100+101+def connect_ex(self, *args, **kwargs):
102+self._na('connect_ex() method')
103+return self._sock.connect_ex(*args, **kwargs)
104+105+def bind(self, *args, **kwargs):
106+self._na('bind() method')
107+return self._sock.bind(*args, **kwargs)
108+109+def ioctl(self, *args, **kwargs):
110+self._na('ioctl() method')
111+return self._sock.ioctl(*args, **kwargs)
112+113+def listen(self, *args, **kwargs):
114+self._na('listen() method')
115+return self._sock.listen(*args, **kwargs)
116+117+def makefile(self):
118+self._na('makefile() method')
119+return self._sock.makefile()
120+121+def sendfile(self, *args, **kwargs):
122+self._na('sendfile() method')
123+return self._sock.sendfile(*args, **kwargs)
124+125+def close(self):
126+self._na('close() method')
127+return self._sock.close()
128+129+def detach(self):
130+self._na('detach() method')
131+return self._sock.detach()
132+133+def sendmsg_afalg(self, *args, **kwargs):
134+self._na('sendmsg_afalg() method')
135+return self._sock.sendmsg_afalg(*args, **kwargs)
136+137+def sendmsg(self, *args, **kwargs):
138+self._na('sendmsg() method')
139+return self._sock.sendmsg(*args, **kwargs)
140+141+def sendto(self, *args, **kwargs):
142+self._na('sendto() method')
143+return self._sock.sendto(*args, **kwargs)
144+145+def send(self, *args, **kwargs):
146+self._na('send() method')
147+return self._sock.send(*args, **kwargs)
148+149+def sendall(self, *args, **kwargs):
150+self._na('sendall() method')
151+return self._sock.sendall(*args, **kwargs)
152+153+def set_inheritable(self, *args, **kwargs):
154+self._na('set_inheritable() method')
155+return self._sock.set_inheritable(*args, **kwargs)
156+157+def share(self, process_id):
158+self._na('share() method')
159+return self._sock.share(process_id)
160+161+def recv_into(self, *args, **kwargs):
162+self._na('recv_into() method')
163+return self._sock.recv_into(*args, **kwargs)
164+165+def recvfrom_into(self, *args, **kwargs):
166+self._na('recvfrom_into() method')
167+return self._sock.recvfrom_into(*args, **kwargs)
168+169+def recvmsg_into(self, *args, **kwargs):
170+self._na('recvmsg_into() method')
171+return self._sock.recvmsg_into(*args, **kwargs)
172+173+def recvmsg(self, *args, **kwargs):
174+self._na('recvmsg() method')
175+return self._sock.recvmsg(*args, **kwargs)
176+177+def recvfrom(self, *args, **kwargs):
178+self._na('recvfrom() method')
179+return self._sock.recvfrom(*args, **kwargs)
180+181+def recv(self, *args, **kwargs):
182+self._na('recv() method')
183+return self._sock.recv(*args, **kwargs)
184+185+def settimeout(self, value):
186+if value == 0:
187+return
188+raise ValueError(
189+'settimeout(): only 0 timeout is allowed on transport sockets')
190+191+def gettimeout(self):
192+return 0
193+194+def setblocking(self, flag):
195+if not flag:
196+return
197+raise ValueError(
198+'setblocking(): transport sockets cannot be blocking')
199+200+def __enter__(self):
201+self._na('context manager protocol')
202+return self._sock.__enter__()
203+204+def __exit__(self, *err):
205+self._na('context manager protocol')
206+return self._sock.__exit__(*err)