python-socks 2.5.3__py3-none-any.whl → 2.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python_socks/_abc.py +3 -26
- python_socks/_connectors/factory_async.py +4 -3
- python_socks/_connectors/factory_sync.py +4 -3
- python_socks/_connectors/http_async.py +3 -2
- python_socks/_connectors/http_sync.py +3 -2
- python_socks/_connectors/socks4_async.py +3 -2
- python_socks/_connectors/socks4_sync.py +3 -2
- python_socks/_connectors/socks5_async.py +4 -3
- python_socks/_connectors/socks5_sync.py +4 -3
- python_socks/_helpers.py +17 -10
- python_socks/_protocols/http.py +3 -2
- python_socks/_protocols/socks4.py +2 -1
- python_socks/_protocols/socks5.py +7 -7
- python_socks/_version.py +1 -1
- python_socks/async_/_proxy_chain.py +9 -4
- python_socks/async_/anyio/_chain.py +6 -0
- python_socks/async_/anyio/_connect.py +2 -1
- python_socks/async_/anyio/_proxy.py +21 -10
- python_socks/async_/anyio/v2/_chain.py +6 -0
- python_socks/async_/anyio/v2/_connect.py +2 -1
- python_socks/async_/anyio/v2/_proxy.py +16 -10
- python_socks/async_/asyncio/_connect.py +1 -1
- python_socks/async_/asyncio/_proxy.py +35 -40
- python_socks/async_/asyncio/v2/_chain.py +6 -0
- python_socks/async_/asyncio/v2/_connect.py +1 -1
- python_socks/async_/asyncio/v2/_proxy.py +23 -16
- python_socks/async_/asyncio/v2/_stream.py +5 -45
- python_socks/async_/curio/_proxy.py +22 -9
- python_socks/async_/trio/_proxy.py +22 -9
- python_socks/async_/trio/v2/_chain.py +6 -0
- python_socks/async_/trio/v2/_connect.py +2 -2
- python_socks/async_/trio/v2/_proxy.py +16 -10
- python_socks/py.typed +0 -0
- python_socks/sync/_chain.py +8 -5
- python_socks/sync/_connect.py +1 -1
- python_socks/sync/_proxy.py +20 -9
- python_socks/sync/v2/_connect.py +1 -1
- python_socks/sync/v2/_proxy.py +14 -11
- {python_socks-2.5.3.dist-info → python_socks-2.6.1.dist-info}/METADATA +35 -16
- python_socks-2.6.1.dist-info/RECORD +77 -0
- {python_socks-2.5.3.dist-info → python_socks-2.6.1.dist-info}/WHEEL +1 -1
- python_socks-2.5.3.dist-info/RECORD +0 -76
- {python_socks-2.5.3.dist-info → python_socks-2.6.1.dist-info}/LICENSE.txt +0 -0
- {python_socks-2.5.3.dist-info → python_socks-2.6.1.dist-info}/top_level.txt +0 -0
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import socket
|
|
3
3
|
import sys
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import asyncio as async_timeout
|
|
7
|
-
else:
|
|
8
|
-
import async_timeout
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
import warnings
|
|
9
6
|
|
|
10
7
|
from ..._types import ProxyType
|
|
11
8
|
from ..._helpers import parse_proxy_url
|
|
@@ -17,21 +14,25 @@ from ..._protocols.errors import ReplyError
|
|
|
17
14
|
from ..._connectors.factory_async import create_connector
|
|
18
15
|
|
|
19
16
|
from ._connect import connect_tcp
|
|
20
|
-
|
|
17
|
+
|
|
18
|
+
if sys.version_info >= (3, 11):
|
|
19
|
+
import asyncio as async_timeout # pylint:disable=reimported
|
|
20
|
+
else:
|
|
21
|
+
import async_timeout
|
|
21
22
|
|
|
22
23
|
DEFAULT_TIMEOUT = 60
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
class AsyncioProxy
|
|
26
|
+
class AsyncioProxy:
|
|
26
27
|
def __init__(
|
|
27
28
|
self,
|
|
28
29
|
proxy_type: ProxyType,
|
|
29
30
|
host: str,
|
|
30
31
|
port: int,
|
|
31
|
-
username: str = None,
|
|
32
|
-
password: str = None,
|
|
33
|
-
rdns: bool = None,
|
|
34
|
-
loop: asyncio.AbstractEventLoop = None,
|
|
32
|
+
username: Optional[str] = None,
|
|
33
|
+
password: Optional[str] = None,
|
|
34
|
+
rdns: Optional[bool] = None,
|
|
35
|
+
loop: Optional[asyncio.AbstractEventLoop] = None,
|
|
35
36
|
):
|
|
36
37
|
if loop is None:
|
|
37
38
|
loop = asyncio.get_event_loop()
|
|
@@ -51,29 +52,46 @@ class AsyncioProxy(abc.AsyncProxy):
|
|
|
51
52
|
self,
|
|
52
53
|
dest_host: str,
|
|
53
54
|
dest_port: int,
|
|
54
|
-
timeout: float = None,
|
|
55
|
-
|
|
55
|
+
timeout: Optional[float] = None,
|
|
56
|
+
**kwargs: Any,
|
|
56
57
|
) -> socket.socket:
|
|
57
58
|
if timeout is None:
|
|
58
59
|
timeout = DEFAULT_TIMEOUT
|
|
59
60
|
|
|
61
|
+
_socket = kwargs.get('_socket')
|
|
62
|
+
if _socket is not None:
|
|
63
|
+
warnings.warn(
|
|
64
|
+
"The '_socket' argument is deprecated and will be removed in the future",
|
|
65
|
+
DeprecationWarning,
|
|
66
|
+
stacklevel=2,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
local_addr = kwargs.get('local_addr')
|
|
60
70
|
try:
|
|
61
71
|
async with async_timeout.timeout(timeout):
|
|
62
72
|
return await self._connect(
|
|
63
73
|
dest_host=dest_host,
|
|
64
74
|
dest_port=dest_port,
|
|
65
75
|
_socket=_socket,
|
|
76
|
+
local_addr=local_addr,
|
|
66
77
|
)
|
|
67
78
|
except asyncio.TimeoutError as e:
|
|
68
79
|
raise ProxyTimeoutError(f'Proxy connection timed out: {timeout}') from e
|
|
69
80
|
|
|
70
|
-
async def _connect(
|
|
81
|
+
async def _connect(
|
|
82
|
+
self,
|
|
83
|
+
dest_host,
|
|
84
|
+
dest_port,
|
|
85
|
+
_socket=None,
|
|
86
|
+
local_addr=None,
|
|
87
|
+
) -> socket.socket:
|
|
71
88
|
if _socket is None:
|
|
72
89
|
try:
|
|
73
90
|
_socket = await connect_tcp(
|
|
74
91
|
host=self._proxy_host,
|
|
75
92
|
port=self._proxy_port,
|
|
76
93
|
loop=self._loop,
|
|
94
|
+
local_addr=local_addr,
|
|
77
95
|
)
|
|
78
96
|
except OSError as e:
|
|
79
97
|
msg = 'Could not connect to proxy {}:{} [{}]'.format(
|
|
@@ -100,36 +118,13 @@ class AsyncioProxy(abc.AsyncProxy):
|
|
|
100
118
|
)
|
|
101
119
|
|
|
102
120
|
return _socket
|
|
103
|
-
except asyncio.CancelledError: # pragma: no cover
|
|
104
|
-
# https://bugs.python.org/issue30064
|
|
105
|
-
# https://bugs.python.org/issue34795
|
|
106
|
-
if self._can_be_closed_safely():
|
|
107
|
-
await stream.close()
|
|
108
|
-
raise
|
|
109
121
|
except ReplyError as e:
|
|
110
122
|
await stream.close()
|
|
111
123
|
raise ProxyError(e, error_code=e.error_code)
|
|
112
|
-
except Exception: # pragma: no cover
|
|
124
|
+
except (asyncio.CancelledError, Exception): # pragma: no cover
|
|
113
125
|
await stream.close()
|
|
114
126
|
raise
|
|
115
127
|
|
|
116
|
-
def _can_be_closed_safely(self): # pragma: no cover
|
|
117
|
-
def is_proactor_event_loop():
|
|
118
|
-
try:
|
|
119
|
-
from asyncio import ProactorEventLoop # noqa
|
|
120
|
-
except ImportError:
|
|
121
|
-
return False
|
|
122
|
-
return isinstance(self._loop, ProactorEventLoop)
|
|
123
|
-
|
|
124
|
-
def is_uvloop_event_loop():
|
|
125
|
-
try:
|
|
126
|
-
from uvloop import Loop # noqa
|
|
127
|
-
except ImportError:
|
|
128
|
-
return False
|
|
129
|
-
return isinstance(self._loop, Loop)
|
|
130
|
-
|
|
131
|
-
return sys.version_info[:2] >= (3, 8) or is_proactor_event_loop() or is_uvloop_event_loop()
|
|
132
|
-
|
|
133
128
|
@property
|
|
134
129
|
def proxy_host(self):
|
|
135
130
|
return self._proxy_host
|
|
@@ -139,10 +134,10 @@ class AsyncioProxy(abc.AsyncProxy):
|
|
|
139
134
|
return self._proxy_port
|
|
140
135
|
|
|
141
136
|
@classmethod
|
|
142
|
-
def create(cls, *args, **kwargs):
|
|
137
|
+
def create(cls, *args, **kwargs): # for backward compatibility
|
|
143
138
|
return cls(*args, **kwargs)
|
|
144
139
|
|
|
145
140
|
@classmethod
|
|
146
|
-
def from_url(cls, url: str, **kwargs):
|
|
141
|
+
def from_url(cls, url: str, **kwargs) -> 'AsyncioProxy':
|
|
147
142
|
url_args = parse_proxy_url(url)
|
|
148
143
|
return cls(*url_args, **kwargs)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
from typing import Sequence
|
|
2
|
+
import warnings
|
|
2
3
|
from ._proxy import AsyncioProxy
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class ProxyChain:
|
|
6
7
|
def __init__(self, proxies: Sequence[AsyncioProxy]):
|
|
8
|
+
warnings.warn(
|
|
9
|
+
'This implementation of ProxyChain is deprecated and will be removed in the future',
|
|
10
|
+
DeprecationWarning,
|
|
11
|
+
stacklevel=2,
|
|
12
|
+
)
|
|
7
13
|
self._proxies = proxies
|
|
8
14
|
|
|
9
15
|
async def connect(
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import ssl
|
|
3
|
+
from typing import Any, Optional, Tuple
|
|
3
4
|
import warnings
|
|
4
5
|
import sys
|
|
5
6
|
|
|
6
7
|
|
|
7
|
-
if sys.version_info >= (3, 11):
|
|
8
|
-
import asyncio as async_timeout
|
|
9
|
-
else:
|
|
10
|
-
import async_timeout
|
|
11
|
-
|
|
12
8
|
from ...._types import ProxyType
|
|
13
9
|
from ...._helpers import parse_proxy_url
|
|
14
10
|
from ...._errors import ProxyConnectionError, ProxyTimeoutError, ProxyError
|
|
@@ -20,6 +16,12 @@ from .._resolver import Resolver
|
|
|
20
16
|
from ._stream import AsyncioSocketStream
|
|
21
17
|
from ._connect import connect_tcp
|
|
22
18
|
|
|
19
|
+
if sys.version_info >= (3, 11):
|
|
20
|
+
import asyncio as async_timeout # pylint:disable=reimported
|
|
21
|
+
else:
|
|
22
|
+
import async_timeout
|
|
23
|
+
|
|
24
|
+
|
|
23
25
|
DEFAULT_TIMEOUT = 60
|
|
24
26
|
|
|
25
27
|
|
|
@@ -29,12 +31,12 @@ class AsyncioProxy:
|
|
|
29
31
|
proxy_type: ProxyType,
|
|
30
32
|
host: str,
|
|
31
33
|
port: int,
|
|
32
|
-
username: str = None,
|
|
33
|
-
password: str = None,
|
|
34
|
-
rdns: bool = None,
|
|
35
|
-
proxy_ssl: ssl.SSLContext = None,
|
|
36
|
-
forward: 'AsyncioProxy' = None,
|
|
37
|
-
loop: asyncio.AbstractEventLoop = None,
|
|
34
|
+
username: Optional[str] = None,
|
|
35
|
+
password: Optional[str] = None,
|
|
36
|
+
rdns: Optional[bool] = None,
|
|
37
|
+
proxy_ssl: Optional[ssl.SSLContext] = None,
|
|
38
|
+
forward: Optional['AsyncioProxy'] = None,
|
|
39
|
+
loop: Optional[asyncio.AbstractEventLoop] = None,
|
|
38
40
|
):
|
|
39
41
|
if loop is not None: # pragma: no cover
|
|
40
42
|
warnings.warn(
|
|
@@ -64,18 +66,21 @@ class AsyncioProxy:
|
|
|
64
66
|
self,
|
|
65
67
|
dest_host: str,
|
|
66
68
|
dest_port: int,
|
|
67
|
-
dest_ssl: ssl.SSLContext = None,
|
|
68
|
-
timeout: float = None,
|
|
69
|
+
dest_ssl: Optional[ssl.SSLContext] = None,
|
|
70
|
+
timeout: Optional[float] = None,
|
|
71
|
+
**kwargs: Any,
|
|
69
72
|
) -> AsyncioSocketStream:
|
|
70
73
|
if timeout is None:
|
|
71
74
|
timeout = DEFAULT_TIMEOUT
|
|
72
75
|
|
|
76
|
+
local_addr = kwargs.get('local_addr')
|
|
73
77
|
try:
|
|
74
78
|
async with async_timeout.timeout(timeout):
|
|
75
79
|
return await self._connect(
|
|
76
80
|
dest_host=dest_host,
|
|
77
81
|
dest_port=dest_port,
|
|
78
82
|
dest_ssl=dest_ssl,
|
|
83
|
+
local_addr=local_addr,
|
|
79
84
|
)
|
|
80
85
|
except asyncio.TimeoutError as e:
|
|
81
86
|
raise ProxyTimeoutError('Proxy connection timed out: {}'.format(timeout)) from e
|
|
@@ -84,7 +89,8 @@ class AsyncioProxy:
|
|
|
84
89
|
self,
|
|
85
90
|
dest_host: str,
|
|
86
91
|
dest_port: int,
|
|
87
|
-
dest_ssl: ssl.SSLContext = None,
|
|
92
|
+
dest_ssl: Optional[ssl.SSLContext] = None,
|
|
93
|
+
local_addr: Optional[Tuple[str, int]] = None,
|
|
88
94
|
) -> AsyncioSocketStream:
|
|
89
95
|
if self._forward is None:
|
|
90
96
|
try:
|
|
@@ -92,6 +98,7 @@ class AsyncioProxy:
|
|
|
92
98
|
host=self._proxy_host,
|
|
93
99
|
port=self._proxy_port,
|
|
94
100
|
loop=self._loop,
|
|
101
|
+
local_addr=local_addr,
|
|
95
102
|
)
|
|
96
103
|
except OSError as e:
|
|
97
104
|
raise ProxyConnectionError(
|
|
@@ -141,10 +148,10 @@ class AsyncioProxy:
|
|
|
141
148
|
return stream
|
|
142
149
|
|
|
143
150
|
@classmethod
|
|
144
|
-
def create(cls, *args, **kwargs):
|
|
151
|
+
def create(cls, *args, **kwargs): # for backward compatibility
|
|
145
152
|
return cls(*args, **kwargs)
|
|
146
153
|
|
|
147
154
|
@classmethod
|
|
148
|
-
def from_url(cls, url: str, **kwargs):
|
|
155
|
+
def from_url(cls, url: str, **kwargs) -> 'AsyncioProxy':
|
|
149
156
|
url_args = parse_proxy_url(url)
|
|
150
157
|
return cls(*url_args, **kwargs)
|
|
@@ -6,48 +6,10 @@ from .... import _abc as abc
|
|
|
6
6
|
DEFAULT_RECEIVE_SIZE = 65536
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
# noinspection PyUnusedLocal
|
|
10
|
-
async def backport_start_tls(
|
|
11
|
-
transport,
|
|
12
|
-
protocol,
|
|
13
|
-
ssl_context,
|
|
14
|
-
*,
|
|
15
|
-
server_side=False,
|
|
16
|
-
server_hostname=None,
|
|
17
|
-
ssl_handshake_timeout=None,
|
|
18
|
-
): # pragma: no cover
|
|
19
|
-
"""
|
|
20
|
-
Python 3.6 asyncio doesn't have a start_tls() method on the loop,
|
|
21
|
-
so we use this function in place of the loop's start_tls() method.
|
|
22
|
-
Adapted from this comment:
|
|
23
|
-
https://github.com/urllib3/urllib3/issues/1323#issuecomment-362494839
|
|
24
|
-
"""
|
|
25
|
-
import asyncio.sslproto
|
|
26
|
-
|
|
27
|
-
loop = asyncio.get_event_loop()
|
|
28
|
-
waiter = loop.create_future()
|
|
29
|
-
ssl_protocol = asyncio.sslproto.SSLProtocol(
|
|
30
|
-
loop,
|
|
31
|
-
protocol,
|
|
32
|
-
ssl_context,
|
|
33
|
-
waiter,
|
|
34
|
-
server_side=False,
|
|
35
|
-
server_hostname=server_hostname,
|
|
36
|
-
call_connection_made=False,
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
transport.set_protocol(ssl_protocol)
|
|
40
|
-
loop.call_soon(ssl_protocol.connection_made, transport)
|
|
41
|
-
loop.call_soon(transport.resume_reading) # type: ignore
|
|
42
|
-
|
|
43
|
-
await waiter
|
|
44
|
-
return ssl_protocol._app_transport # noqa
|
|
45
|
-
|
|
46
|
-
|
|
47
9
|
class AsyncioSocketStream(abc.AsyncSocketStream):
|
|
48
|
-
_loop: asyncio.AbstractEventLoop
|
|
49
|
-
_reader: asyncio.StreamReader
|
|
50
|
-
_writer: asyncio.StreamWriter
|
|
10
|
+
_loop: asyncio.AbstractEventLoop
|
|
11
|
+
_reader: asyncio.StreamReader
|
|
12
|
+
_writer: asyncio.StreamWriter
|
|
51
13
|
|
|
52
14
|
def __init__(
|
|
53
15
|
self,
|
|
@@ -86,9 +48,7 @@ class AsyncioSocketStream(abc.AsyncSocketStream):
|
|
|
86
48
|
reader = asyncio.StreamReader()
|
|
87
49
|
protocol = asyncio.StreamReaderProtocol(reader)
|
|
88
50
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
transport = await loop_start_tls(
|
|
51
|
+
transport: asyncio.Transport = await self._loop.start_tls(
|
|
92
52
|
self._writer.transport, # type: ignore
|
|
93
53
|
protocol,
|
|
94
54
|
ssl_context,
|
|
@@ -115,7 +75,7 @@ class AsyncioSocketStream(abc.AsyncSocketStream):
|
|
|
115
75
|
# When we return a new SocketStream with new StreamReader/StreamWriter instances
|
|
116
76
|
# we need to keep references to the old StreamReader/StreamWriter so that they
|
|
117
77
|
# are not garbage collected and closed while we're still using them.
|
|
118
|
-
stream._inner = self # type: ignore
|
|
78
|
+
stream._inner = self # type: ignore # pylint:disable=W0212,W0201
|
|
119
79
|
return stream
|
|
120
80
|
|
|
121
81
|
async def close(self):
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
import warnings
|
|
1
3
|
import curio
|
|
2
4
|
import curio.io
|
|
3
5
|
|
|
@@ -12,20 +14,19 @@ from ._connect import connect_tcp
|
|
|
12
14
|
from ..._protocols.errors import ReplyError
|
|
13
15
|
from ..._connectors.factory_async import create_connector
|
|
14
16
|
|
|
15
|
-
from ... import _abc as abc
|
|
16
17
|
|
|
17
18
|
DEFAULT_TIMEOUT = 60
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
class CurioProxy
|
|
21
|
+
class CurioProxy:
|
|
21
22
|
def __init__(
|
|
22
23
|
self,
|
|
23
24
|
proxy_type: ProxyType,
|
|
24
25
|
host: str,
|
|
25
26
|
port: int,
|
|
26
|
-
username: str = None,
|
|
27
|
-
password: str = None,
|
|
28
|
-
rdns: bool = None,
|
|
27
|
+
username: Optional[str] = None,
|
|
28
|
+
password: Optional[str] = None,
|
|
29
|
+
rdns: Optional[bool] = None,
|
|
29
30
|
):
|
|
30
31
|
self._proxy_type = proxy_type
|
|
31
32
|
self._proxy_host = host
|
|
@@ -40,12 +41,21 @@ class CurioProxy(abc.AsyncProxy):
|
|
|
40
41
|
self,
|
|
41
42
|
dest_host: str,
|
|
42
43
|
dest_port: int,
|
|
43
|
-
timeout: float = None,
|
|
44
|
-
|
|
44
|
+
timeout: Optional[float] = None,
|
|
45
|
+
**kwargs: Any,
|
|
45
46
|
) -> curio.io.Socket:
|
|
46
47
|
if timeout is None:
|
|
47
48
|
timeout = DEFAULT_TIMEOUT
|
|
48
49
|
|
|
50
|
+
_socket = kwargs.get('_socket')
|
|
51
|
+
if _socket is not None:
|
|
52
|
+
warnings.warn(
|
|
53
|
+
"The '_socket' argument is deprecated and will be removed in the future",
|
|
54
|
+
DeprecationWarning,
|
|
55
|
+
stacklevel=2,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
local_addr = kwargs.get('local_addr')
|
|
49
59
|
try:
|
|
50
60
|
return await curio.timeout_after(
|
|
51
61
|
timeout,
|
|
@@ -53,6 +63,7 @@ class CurioProxy(abc.AsyncProxy):
|
|
|
53
63
|
dest_host,
|
|
54
64
|
dest_port,
|
|
55
65
|
_socket,
|
|
66
|
+
local_addr,
|
|
56
67
|
)
|
|
57
68
|
except curio.TaskTimeout as e:
|
|
58
69
|
raise ProxyTimeoutError(f'Proxy connection timed out: {timeout}') from e
|
|
@@ -62,12 +73,14 @@ class CurioProxy(abc.AsyncProxy):
|
|
|
62
73
|
dest_host: str,
|
|
63
74
|
dest_port: int,
|
|
64
75
|
_socket=None,
|
|
76
|
+
local_addr=None,
|
|
65
77
|
):
|
|
66
78
|
if _socket is None:
|
|
67
79
|
try:
|
|
68
80
|
_socket = await connect_tcp(
|
|
69
81
|
host=self._proxy_host,
|
|
70
82
|
port=self._proxy_port,
|
|
83
|
+
local_addr=local_addr,
|
|
71
84
|
)
|
|
72
85
|
except OSError as e:
|
|
73
86
|
msg = 'Could not connect to proxy {}:{} [{}]'.format(
|
|
@@ -110,10 +123,10 @@ class CurioProxy(abc.AsyncProxy):
|
|
|
110
123
|
return self._proxy_port
|
|
111
124
|
|
|
112
125
|
@classmethod
|
|
113
|
-
def create(cls, *args, **kwargs):
|
|
126
|
+
def create(cls, *args, **kwargs): # for backward compatibility
|
|
114
127
|
return cls(*args, **kwargs)
|
|
115
128
|
|
|
116
129
|
@classmethod
|
|
117
|
-
def from_url(cls, url: str, **kwargs):
|
|
130
|
+
def from_url(cls, url: str, **kwargs) -> 'CurioProxy':
|
|
118
131
|
url_args = parse_proxy_url(url)
|
|
119
132
|
return cls(*url_args, **kwargs)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
import warnings
|
|
1
3
|
import trio
|
|
2
4
|
|
|
3
5
|
from ..._types import ProxyType
|
|
@@ -11,20 +13,19 @@ from ._connect import connect_tcp
|
|
|
11
13
|
from ..._protocols.errors import ReplyError
|
|
12
14
|
from ..._connectors.factory_async import create_connector
|
|
13
15
|
|
|
14
|
-
from ... import _abc as abc
|
|
15
16
|
|
|
16
17
|
DEFAULT_TIMEOUT = 60
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
class TrioProxy
|
|
20
|
+
class TrioProxy:
|
|
20
21
|
def __init__(
|
|
21
22
|
self,
|
|
22
23
|
proxy_type: ProxyType,
|
|
23
24
|
host: str,
|
|
24
25
|
port: int,
|
|
25
|
-
username: str = None,
|
|
26
|
-
password: str = None,
|
|
27
|
-
rdns: bool = None,
|
|
26
|
+
username: Optional[str] = None,
|
|
27
|
+
password: Optional[str] = None,
|
|
28
|
+
rdns: Optional[bool] = None,
|
|
28
29
|
):
|
|
29
30
|
self._proxy_type = proxy_type
|
|
30
31
|
self._proxy_host = host
|
|
@@ -39,18 +40,28 @@ class TrioProxy(abc.AsyncProxy):
|
|
|
39
40
|
self,
|
|
40
41
|
dest_host: str,
|
|
41
42
|
dest_port: int,
|
|
42
|
-
timeout: float = None,
|
|
43
|
-
|
|
43
|
+
timeout: Optional[float] = None,
|
|
44
|
+
**kwargs: Any,
|
|
44
45
|
) -> trio.socket.SocketType:
|
|
45
46
|
if timeout is None:
|
|
46
47
|
timeout = DEFAULT_TIMEOUT
|
|
47
48
|
|
|
49
|
+
_socket = kwargs.get('_socket')
|
|
50
|
+
if _socket is not None:
|
|
51
|
+
warnings.warn(
|
|
52
|
+
"The '_socket' argument is deprecated and will be removed in the future",
|
|
53
|
+
DeprecationWarning,
|
|
54
|
+
stacklevel=2,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
local_addr = kwargs.get('local_addr')
|
|
48
58
|
try:
|
|
49
59
|
with trio.fail_after(timeout):
|
|
50
60
|
return await self._connect(
|
|
51
61
|
dest_host=dest_host,
|
|
52
62
|
dest_port=dest_port,
|
|
53
63
|
_socket=_socket,
|
|
64
|
+
local_addr=local_addr,
|
|
54
65
|
)
|
|
55
66
|
except trio.TooSlowError as e:
|
|
56
67
|
raise ProxyTimeoutError('Proxy connection timed out: {}'.format(timeout)) from e
|
|
@@ -60,12 +71,14 @@ class TrioProxy(abc.AsyncProxy):
|
|
|
60
71
|
dest_host: str,
|
|
61
72
|
dest_port: int,
|
|
62
73
|
_socket=None,
|
|
74
|
+
local_addr=None,
|
|
63
75
|
) -> trio.socket.SocketType:
|
|
64
76
|
if _socket is None:
|
|
65
77
|
try:
|
|
66
78
|
_socket = await connect_tcp(
|
|
67
79
|
host=self._proxy_host,
|
|
68
80
|
port=self._proxy_port,
|
|
81
|
+
local_addr=local_addr,
|
|
69
82
|
)
|
|
70
83
|
except OSError as e:
|
|
71
84
|
msg = 'Could not connect to proxy {}:{} [{}]'.format(
|
|
@@ -109,10 +122,10 @@ class TrioProxy(abc.AsyncProxy):
|
|
|
109
122
|
return self._proxy_port
|
|
110
123
|
|
|
111
124
|
@classmethod
|
|
112
|
-
def create(cls, *args, **kwargs):
|
|
125
|
+
def create(cls, *args, **kwargs): # for backward compatibility
|
|
113
126
|
return cls(*args, **kwargs)
|
|
114
127
|
|
|
115
128
|
@classmethod
|
|
116
|
-
def from_url(cls, url: str, **kwargs):
|
|
129
|
+
def from_url(cls, url: str, **kwargs) -> 'TrioProxy':
|
|
117
130
|
url_args = parse_proxy_url(url)
|
|
118
131
|
return cls(*url_args, **kwargs)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
from typing import Sequence
|
|
2
|
+
import warnings
|
|
2
3
|
from ._proxy import TrioProxy
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class ProxyChain:
|
|
6
7
|
def __init__(self, proxies: Sequence[TrioProxy]):
|
|
8
|
+
warnings.warn(
|
|
9
|
+
'This implementation of ProxyChain is deprecated and will be removed in the future',
|
|
10
|
+
DeprecationWarning,
|
|
11
|
+
stacklevel=2,
|
|
12
|
+
)
|
|
7
13
|
self._proxies = proxies
|
|
8
14
|
|
|
9
15
|
async def connect(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Optional
|
|
1
|
+
from typing import Optional
|
|
2
2
|
|
|
3
3
|
import trio
|
|
4
4
|
from ._stream import TrioSocketStream
|
|
@@ -7,7 +7,7 @@ from ._stream import TrioSocketStream
|
|
|
7
7
|
async def connect_tcp(
|
|
8
8
|
host: str,
|
|
9
9
|
port: int,
|
|
10
|
-
local_addr: Optional[
|
|
10
|
+
local_addr: Optional[str] = None,
|
|
11
11
|
) -> TrioSocketStream:
|
|
12
12
|
trio_stream = await trio.open_tcp_stream(
|
|
13
13
|
host=host,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import ssl
|
|
2
|
+
from typing import Any, Optional
|
|
2
3
|
|
|
3
4
|
import trio
|
|
4
5
|
|
|
@@ -22,11 +23,11 @@ class TrioProxy:
|
|
|
22
23
|
proxy_type: ProxyType,
|
|
23
24
|
host: str,
|
|
24
25
|
port: int,
|
|
25
|
-
username: str = None,
|
|
26
|
-
password: str = None,
|
|
27
|
-
rdns: bool = None,
|
|
28
|
-
proxy_ssl: ssl.SSLContext = None,
|
|
29
|
-
forward: 'TrioProxy' = None,
|
|
26
|
+
username: Optional[str] = None,
|
|
27
|
+
password: Optional[str] = None,
|
|
28
|
+
rdns: Optional[bool] = None,
|
|
29
|
+
proxy_ssl: Optional[ssl.SSLContext] = None,
|
|
30
|
+
forward: Optional['TrioProxy'] = None,
|
|
30
31
|
):
|
|
31
32
|
self._proxy_type = proxy_type
|
|
32
33
|
self._proxy_host = host
|
|
@@ -44,18 +45,21 @@ class TrioProxy:
|
|
|
44
45
|
self,
|
|
45
46
|
dest_host: str,
|
|
46
47
|
dest_port: int,
|
|
47
|
-
dest_ssl: ssl.SSLContext = None,
|
|
48
|
-
timeout: float = None,
|
|
48
|
+
dest_ssl: Optional[ssl.SSLContext] = None,
|
|
49
|
+
timeout: Optional[float] = None,
|
|
50
|
+
**kwargs: Any,
|
|
49
51
|
) -> TrioSocketStream:
|
|
50
52
|
if timeout is None:
|
|
51
53
|
timeout = DEFAULT_TIMEOUT
|
|
52
54
|
|
|
55
|
+
local_addr = kwargs.get('local_addr')
|
|
53
56
|
try:
|
|
54
57
|
with trio.fail_after(timeout):
|
|
55
58
|
return await self._connect(
|
|
56
59
|
dest_host=dest_host,
|
|
57
60
|
dest_port=dest_port,
|
|
58
61
|
dest_ssl=dest_ssl,
|
|
62
|
+
local_addr=local_addr,
|
|
59
63
|
)
|
|
60
64
|
except trio.TooSlowError as e:
|
|
61
65
|
raise ProxyTimeoutError(f'Proxy connection timed out: {timeout}') from e
|
|
@@ -64,13 +68,15 @@ class TrioProxy:
|
|
|
64
68
|
self,
|
|
65
69
|
dest_host: str,
|
|
66
70
|
dest_port: int,
|
|
67
|
-
dest_ssl: ssl.SSLContext = None,
|
|
71
|
+
dest_ssl: Optional[ssl.SSLContext] = None,
|
|
72
|
+
local_addr: Optional[str] = None,
|
|
68
73
|
) -> TrioSocketStream:
|
|
69
74
|
if self._forward is None:
|
|
70
75
|
try:
|
|
71
76
|
stream = await connect_tcp(
|
|
72
77
|
host=self._proxy_host,
|
|
73
78
|
port=self._proxy_port,
|
|
79
|
+
local_addr=local_addr,
|
|
74
80
|
)
|
|
75
81
|
except OSError as e:
|
|
76
82
|
raise ProxyConnectionError(
|
|
@@ -120,10 +126,10 @@ class TrioProxy:
|
|
|
120
126
|
return stream
|
|
121
127
|
|
|
122
128
|
@classmethod
|
|
123
|
-
def create(cls, *args, **kwargs):
|
|
129
|
+
def create(cls, *args, **kwargs): # for backward compatibility
|
|
124
130
|
return cls(*args, **kwargs)
|
|
125
131
|
|
|
126
132
|
@classmethod
|
|
127
|
-
def from_url(cls, url: str, **kwargs):
|
|
133
|
+
def from_url(cls, url: str, **kwargs) -> 'TrioProxy':
|
|
128
134
|
url_args = parse_proxy_url(url)
|
|
129
135
|
return cls(*url_args, **kwargs)
|
python_socks/py.typed
ADDED
|
File without changes
|
python_socks/sync/_chain.py
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
from typing import Iterable
|
|
2
|
+
import warnings
|
|
2
3
|
from ._proxy import SyncProxy
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class ProxyChain:
|
|
6
7
|
def __init__(self, proxies: Iterable[SyncProxy]):
|
|
8
|
+
warnings.warn(
|
|
9
|
+
'This implementation of ProxyChain is deprecated and will be removed in the future',
|
|
10
|
+
DeprecationWarning,
|
|
11
|
+
stacklevel=2,
|
|
12
|
+
)
|
|
7
13
|
self._proxies = proxies
|
|
8
14
|
|
|
9
15
|
def connect(self, dest_host, dest_port, timeout=None):
|
|
@@ -16,14 +22,11 @@ class ProxyChain:
|
|
|
16
22
|
dest_host=proxies[i + 1].proxy_host,
|
|
17
23
|
dest_port=proxies[i + 1].proxy_port,
|
|
18
24
|
timeout=timeout,
|
|
19
|
-
_socket=curr_socket
|
|
25
|
+
_socket=curr_socket,
|
|
20
26
|
)
|
|
21
27
|
|
|
22
28
|
curr_socket = proxies[length].connect(
|
|
23
|
-
dest_host=dest_host,
|
|
24
|
-
dest_port=dest_port,
|
|
25
|
-
timeout=timeout,
|
|
26
|
-
_socket=curr_socket
|
|
29
|
+
dest_host=dest_host, dest_port=dest_port, timeout=timeout, _socket=curr_socket
|
|
27
30
|
)
|
|
28
31
|
|
|
29
32
|
return curr_socket
|
python_socks/sync/_connect.py
CHANGED