portal 3.2.1__tar.gz → 3.2.3__tar.gz
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.
- {portal-3.2.1/portal.egg-info → portal-3.2.3}/PKG-INFO +1 -1
- {portal-3.2.1 → portal-3.2.3}/portal/__init__.py +1 -1
- {portal-3.2.1 → portal-3.2.3}/portal/client_socket.py +13 -12
- {portal-3.2.1 → portal-3.2.3}/portal/contextlib.py +7 -1
- {portal-3.2.1 → portal-3.2.3}/portal/utils.py +8 -2
- {portal-3.2.1 → portal-3.2.3/portal.egg-info}/PKG-INFO +1 -1
- {portal-3.2.1 → portal-3.2.3}/tests/test_client.py +17 -0
- {portal-3.2.1 → portal-3.2.3}/tests/test_server.py +2 -2
- {portal-3.2.1 → portal-3.2.3}/LICENSE +0 -0
- {portal-3.2.1 → portal-3.2.3}/MANIFEST.in +0 -0
- {portal-3.2.1 → portal-3.2.3}/README.md +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/batching.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/buffers.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/client.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/packlib.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/poollib.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/process.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/server.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/server_socket.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/sharray.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal/thread.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal.egg-info/SOURCES.txt +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal.egg-info/dependency_links.txt +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal.egg-info/requires.txt +0 -0
- {portal-3.2.1 → portal-3.2.3}/portal.egg-info/top_level.txt +0 -0
- {portal-3.2.1 → portal-3.2.3}/pyproject.toml +0 -0
- {portal-3.2.1 → portal-3.2.3}/requirements.txt +0 -0
- {portal-3.2.1 → portal-3.2.3}/setup.cfg +0 -0
- {portal-3.2.1 → portal-3.2.3}/setup.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/tests/test_batching.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/tests/test_errfile.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/tests/test_pack.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/tests/test_process.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/tests/test_socket.py +0 -0
- {portal-3.2.1 → portal-3.2.3}/tests/test_thread.py +0 -0
@@ -34,11 +34,11 @@ class Options:
|
|
34
34
|
class ClientSocket:
|
35
35
|
|
36
36
|
def __init__(self, host, port=None, name='Client', start=True, **kwargs):
|
37
|
-
assert
|
37
|
+
assert port or ':' in host, (host, port)
|
38
|
+
assert '://' not in host, (host, port)
|
38
39
|
if port is None:
|
39
40
|
host, port = host.rsplit(':', 1)
|
40
|
-
port
|
41
|
-
assert host, host
|
41
|
+
assert host and port, (host, port)
|
42
42
|
self.addr = (host, port)
|
43
43
|
self.name = name
|
44
44
|
self.options = Options(**{**contextlib.context.clientkw, **kwargs})
|
@@ -179,16 +179,19 @@ class ClientSocket:
|
|
179
179
|
sock.close()
|
180
180
|
|
181
181
|
def _connect(self):
|
182
|
-
|
183
|
-
self._log(f'Connecting to {host}:{port}')
|
182
|
+
self._log(f'Connecting to {self.addr[0]}:{self.addr[1]}')
|
184
183
|
once = True
|
185
184
|
while self.running:
|
186
|
-
|
185
|
+
# We need to resolve the address regularly.
|
186
|
+
host, port = self.addr
|
187
|
+
if contextlib.context.resolver:
|
188
|
+
host, port = contextlib.context.resolver((host, port))
|
189
|
+
assert isinstance(host, str), (host, port)
|
190
|
+
assert isinstance(port, int), (host, port)
|
191
|
+
addr = (host, port, 0, 0) if self.options.ipv6 else (host, port)
|
192
|
+
sock = self._create()
|
187
193
|
error = None
|
188
194
|
try:
|
189
|
-
# We need to resolve the address regularly.
|
190
|
-
if contextlib.context.resolver:
|
191
|
-
addr = contextlib.context.resolver(addr)
|
192
195
|
sock.settimeout(10)
|
193
196
|
sock.connect(addr)
|
194
197
|
sock.settimeout(0)
|
@@ -210,10 +213,8 @@ class ClientSocket:
|
|
210
213
|
def _create(self):
|
211
214
|
if self.options.ipv6:
|
212
215
|
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
213
|
-
addr = (*self.addr, 0, 0)
|
214
216
|
else:
|
215
217
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
216
|
-
addr = self.addr
|
217
218
|
# sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
218
219
|
after = self.options.keepalive_after
|
219
220
|
every = self.options.keepalive_every
|
@@ -231,7 +232,7 @@ class ClientSocket:
|
|
231
232
|
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPALIVE, every)
|
232
233
|
if sys.platform == 'win32':
|
233
234
|
sock.ioctl(socket.SIO_KEEPALIVE_VALS, (1, after * 1000, every * 1000))
|
234
|
-
return sock
|
235
|
+
return sock
|
235
236
|
|
236
237
|
def _log(self, *args):
|
237
238
|
if not self.options.logging:
|
@@ -4,6 +4,7 @@ import pathlib
|
|
4
4
|
import sys
|
5
5
|
import threading
|
6
6
|
import traceback
|
7
|
+
import warnings
|
7
8
|
|
8
9
|
import cloudpickle
|
9
10
|
import psutil
|
@@ -143,7 +144,12 @@ class Context:
|
|
143
144
|
return
|
144
145
|
if hasattr(worker, 'thread'):
|
145
146
|
assert current != worker.thread
|
146
|
-
|
147
|
+
try:
|
148
|
+
current.children.append(worker)
|
149
|
+
except AttributeError:
|
150
|
+
warnings.warn(
|
151
|
+
'Using Portal from plain Python threads is discouraged because ' +
|
152
|
+
'they can cause hangs during shutdown.')
|
147
153
|
|
148
154
|
def children(self, thread):
|
149
155
|
current = thread or threading.current_thread()
|
@@ -8,6 +8,8 @@ import time
|
|
8
8
|
|
9
9
|
import psutil
|
10
10
|
|
11
|
+
from . import contextlib
|
12
|
+
|
11
13
|
|
12
14
|
def run(workers, duration=None):
|
13
15
|
[None if x.started else x.start() for x in workers]
|
@@ -96,9 +98,13 @@ def free_port():
|
|
96
98
|
# Return a port that is currently free. This function is not thread or
|
97
99
|
# process safe, because there is no way to guarantee that the port will still
|
98
100
|
# be free at the time it will be used.
|
99
|
-
|
101
|
+
if contextlib.context.serverkw.get('ipv6', False):
|
102
|
+
family, addr = socket.AF_INET6, ('localhost', 0, 0, 0)
|
103
|
+
else:
|
104
|
+
family, addr = socket.AF_INET, ('localhost', 0)
|
105
|
+
sock = socket.socket(family, socket.SOCK_STREAM)
|
100
106
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
101
|
-
sock.bind(
|
107
|
+
sock.bind(addr)
|
102
108
|
port = sock.getsockname()[1]
|
103
109
|
sock.close()
|
104
110
|
return port
|
@@ -321,3 +321,20 @@ class TestClient:
|
|
321
321
|
portal.Thread(server),
|
322
322
|
portal.Thread(client),
|
323
323
|
])
|
324
|
+
|
325
|
+
def test_resolver(self):
|
326
|
+
portnum = portal.free_port()
|
327
|
+
|
328
|
+
def client(portnum):
|
329
|
+
def resolver(host, portstr):
|
330
|
+
assert portstr == 'name'
|
331
|
+
return host, portnum
|
332
|
+
portal.setup(resolver=resolver)
|
333
|
+
client = portal.Client('localhost:name')
|
334
|
+
assert client.fn(42).result() == 42
|
335
|
+
|
336
|
+
server = portal.Server(portnum)
|
337
|
+
server.bind('fn', lambda x: x)
|
338
|
+
server.start(block=False)
|
339
|
+
portal.Process(client, portnum, start=True).join()
|
340
|
+
server.close()
|
@@ -199,7 +199,7 @@ class TestServer:
|
|
199
199
|
def test_shared_pool(self, repeat, Server):
|
200
200
|
|
201
201
|
def slow(x):
|
202
|
-
time.sleep(0.
|
202
|
+
time.sleep(0.5)
|
203
203
|
return x
|
204
204
|
|
205
205
|
def fast(x):
|
@@ -226,7 +226,7 @@ class TestServer:
|
|
226
226
|
def test_separate_pools(self, repeat, Server):
|
227
227
|
|
228
228
|
def slow(x):
|
229
|
-
time.sleep(0.
|
229
|
+
time.sleep(0.5)
|
230
230
|
return x
|
231
231
|
|
232
232
|
def fast(x):
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|