Skip to content

Commit 549fb87

Browse files
authored
Merge branch 'develop' into dependabot/pip/blacksheep-1.2.2
2 parents 6830f4e + f2c88bb commit 549fb87

File tree

13 files changed

+85
-72
lines changed

13 files changed

+85
-72
lines changed

helper/benchmark.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ run_benchmark
6464

6565
POST_RUN_OPEN_FILES=$(./helper/monitor_open_files.sh)
6666

67-
echo $output
68-
6967
echo "Open files diff:"
7068
diff <( echo "$PRE_RUN_OPEN_FILES" ) <( echo "$POST_RUN_OPEN_FILES" )
7169

proxy/common/flag.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from ._compat import IS_WINDOWS # noqa: WPS436
2323
from .plugins import Plugins
2424
from .types import IpAddress
25-
from .utils import bytes_, is_py2, set_open_file_limit
25+
from .utils import bytes_, is_py2, is_threadless, set_open_file_limit
2626
from .constants import COMMA, DEFAULT_DATA_DIRECTORY_PATH, DEFAULT_NUM_ACCEPTORS, DEFAULT_NUM_WORKERS
2727
from .constants import DEFAULT_DEVTOOLS_WS_PATH, DEFAULT_DISABLE_HEADERS, PY2_DEPRECATION_MESSAGE
2828
from .constants import PLUGIN_DASHBOARD, PLUGIN_DEVTOOLS_PROTOCOL, DEFAULT_MIN_COMPRESSION_LIMIT
@@ -186,7 +186,7 @@ def initialize(
186186
for p in FlagParser.get_default_plugins(args)
187187
]
188188
requested_plugins = Plugins.resolve_plugin_flag(
189-
args.plugins, opts.get('plugins', None),
189+
args.plugins, opts.get('plugins'),
190190
)
191191
plugins = Plugins.load(
192192
default_plugins + auth_plugins + requested_plugins,
@@ -340,21 +340,29 @@ def initialize(
340340
),
341341
)
342342
args.timeout = cast(int, opts.get('timeout', args.timeout))
343-
args.threadless = cast(bool, opts.get('threadless', args.threadless))
344-
args.threaded = cast(bool, opts.get('threaded', args.threaded))
345-
args.pid_file = cast(
346-
Optional[str], opts.get(
347-
'pid_file',
348-
args.pid_file,
349-
),
350-
)
351343
args.local_executor = cast(
352344
bool,
353345
opts.get(
354346
'local_executor',
355347
args.local_executor,
356348
),
357349
)
350+
args.threaded = cast(bool, opts.get('threaded', args.threaded))
351+
# Pre-evaluate threadless values based upon environment and config
352+
#
353+
# --threadless is now default mode of execution
354+
# but we still have exceptions based upon OS config.
355+
# Make sure executors are not started if is_threadless
356+
# evaluates to False.
357+
args.threadless = cast(bool, opts.get('threadless', args.threadless))
358+
args.threadless = is_threadless(args.threadless, args.threaded)
359+
360+
args.pid_file = cast(
361+
Optional[str], opts.get(
362+
'pid_file',
363+
args.pid_file,
364+
),
365+
)
358366

359367
args.proxy_py_data_dir = DEFAULT_DATA_DIRECTORY_PATH
360368
os.makedirs(args.proxy_py_data_dir, exist_ok=True)

proxy/common/pki.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -298,16 +298,16 @@ def run_openssl_command(command: List[str], timeout: int) -> bool:
298298
', '.join(available_actions),
299299
)
300300
sys.exit(1)
301-
if args.action in ('gen_private_key', 'gen_public_key'):
302-
if args.private_key_path is None:
303-
logger.error('--private-key-path is required for ' + args.action)
304-
sys.exit(1)
305-
if args.action == 'gen_public_key':
306-
if args.public_key_path is None:
307-
logger.error(
308-
'--public-key-file is required for private key generation',
309-
)
310-
sys.exit(1)
301+
if args.action in ('gen_private_key', 'gen_public_key') and \
302+
args.private_key_path is None:
303+
logger.error('--private-key-path is required for ' + args.action)
304+
sys.exit(1)
305+
if args.action == 'gen_public_key' and \
306+
args.public_key_path is None:
307+
logger.error(
308+
'--public-key-file is required for private key generation',
309+
)
310+
sys.exit(1)
311311

312312
# Execute
313313
if args.action == 'gen_private_key':

proxy/common/plugins.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,18 @@ def load(
7474
mro = list(inspect.getmro(klass))
7575
mro.reverse()
7676
iterator = iter(mro)
77-
while next(iterator) is not abc.ABC:
78-
pass
79-
base_klass = next(iterator)
80-
if klass not in p[bytes_(base_klass.__name__)]:
81-
p[bytes_(base_klass.__name__)].append(klass)
82-
logger.info('Loaded plugin %s.%s', module_name, klass.__name__)
77+
try:
78+
while next(iterator) is not abc.ABC:
79+
pass
80+
base_klass = next(iterator)
81+
if klass not in p[bytes_(base_klass.__name__)]:
82+
p[bytes_(base_klass.__name__)].append(klass)
83+
logger.info('Loaded plugin %s.%s', module_name, klass.__name__)
84+
except StopIteration:
85+
logger.warn(
86+
'%s is NOT a valid plugin',
87+
text_(plugin_),
88+
)
8389
return p
8490

8591
@staticmethod

proxy/common/utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def build_http_response(
9999
headers = {}
100100
has_content_length = False
101101
has_transfer_encoding = False
102-
for k in headers:
102+
for k, _ in headers.items():
103103
if k.lower() == b'content-length':
104104
has_content_length = True
105105
if k.lower() == b'transfer-encoding':
@@ -124,8 +124,8 @@ def build_http_pkt(
124124
"""Build and returns a HTTP request or response packet."""
125125
pkt = WHITESPACE.join(line) + CRLF
126126
if headers is not None:
127-
for k in headers:
128-
pkt += build_http_header(k, headers[k]) + CRLF
127+
for k, v in headers.items():
128+
pkt += build_http_header(k, v) + CRLF
129129
pkt += CRLF
130130
if body:
131131
pkt += body

proxy/core/acceptor/acceptor.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
from typing import List, Optional, Tuple
2727

2828
from ...common.flag import flags
29-
from ...common.utils import is_threadless
3029
from ...common.logger import Logger
3130
from ...common.backports import NonBlockingQueue
3231
from ...common.constants import DEFAULT_LOCAL_EXECUTOR
@@ -113,17 +112,17 @@ def accept(
113112
) -> List[Tuple[socket.socket, Optional[Tuple[str, int]]]]:
114113
works = []
115114
for _, mask in events:
116-
if mask & selectors.EVENT_READ:
117-
if self.sock is not None:
118-
try:
119-
conn, addr = self.sock.accept()
120-
logging.debug(
121-
'Accepting new work#{0}'.format(conn.fileno()),
122-
)
123-
works.append((conn, addr or None))
124-
except BlockingIOError:
125-
# logger.info('blocking io error')
126-
pass
115+
if mask & selectors.EVENT_READ and \
116+
self.sock is not None:
117+
try:
118+
conn, addr = self.sock.accept()
119+
logging.debug(
120+
'Accepting new work#{0}'.format(conn.fileno()),
121+
)
122+
works.append((conn, addr or None))
123+
except BlockingIOError:
124+
# logger.info('blocking io error')
125+
pass
127126
return works
128127

129128
def run_once(self) -> None:
@@ -207,7 +206,7 @@ def _stop_local(self) -> None:
207206

208207
def _work(self, conn: socket.socket, addr: Optional[Tuple[str, int]]) -> None:
209208
self._total = self._total or 0
210-
if is_threadless(self.flags.threadless, self.flags.threaded):
209+
if self.flags.threadless:
211210
# Index of worker to which this work should be dispatched
212211
# Use round-robin strategy by default.
213212
#

proxy/core/acceptor/executors.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
from ..event import EventQueue, eventNames
2727

2828
from ...common.flag import flags
29-
from ...common.utils import is_threadless
3029
from ...common.constants import DEFAULT_NUM_WORKERS, DEFAULT_THREADLESS
3130

3231
logger = logging.getLogger(__name__)
@@ -150,7 +149,7 @@ def start_threaded_work(
150149

151150
def setup(self) -> None:
152151
"""Setup threadless processes."""
153-
if is_threadless(self.flags.threadless, self.flags.threaded):
152+
if self.flags.threadless:
154153
for index in range(self.flags.num_workers):
155154
self._start_worker(index)
156155
logger.info(
@@ -161,7 +160,7 @@ def setup(self) -> None:
161160

162161
def shutdown(self) -> None:
163162
"""Shutdown threadless processes."""
164-
if is_threadless(self.flags.threadless, self.flags.threaded):
163+
if self.flags.threadless:
165164
self._shutdown_workers()
166165
logger.info(
167166
'Stopped {0} threadless workers'.format(

proxy/core/base/tcp_server.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ async def handle_writables(self, writables: Writables) -> bool:
9999
'Flushing buffer to client {0}'.format(self.work.address),
100100
)
101101
self.work.flush()
102-
if self.must_flush_before_shutdown is True:
103-
if not self.work.has_buffer():
104-
teardown = True
105-
self.must_flush_before_shutdown = False
102+
if self.must_flush_before_shutdown is True and \
103+
not self.work.has_buffer():
104+
teardown = True
105+
self.must_flush_before_shutdown = False
106106
return teardown
107107

108108
async def handle_readables(self, readables: Readables) -> bool:

proxy/http/handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from .exception import HttpProtocolException
2424

2525
from ..common.types import Readables, Writables
26-
from ..common.utils import wrap_socket, is_threadless
26+
from ..common.utils import wrap_socket
2727
from ..core.base import BaseTcpServerHandler
2828
from ..core.connection import TcpClientConnection
2929
from ..common.flag import flags
@@ -76,7 +76,7 @@ def __init__(self, *args: Any, **kwargs: Any):
7676
enable_proxy_protocol=self.flags.enable_proxy_protocol,
7777
)
7878
self.selector: Optional[selectors.DefaultSelector] = None
79-
if not is_threadless(self.flags.threadless, self.flags.threaded):
79+
if not self.flags.threadless:
8080
self.selector = selectors.DefaultSelector()
8181
self.plugins: Dict[str, HttpProtocolHandlerPlugin] = {}
8282

proxy/http/websocket/frame.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
Websocket
1717
"""
1818
import io
19-
import hashlib
2019
import base64
2120
import struct
21+
import hashlib
2222
import secrets
2323
import logging
2424

proxy/proxy.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,9 @@ def setup(self) -> None:
171171
event_queue = self.event_manager.queue \
172172
if self.event_manager is not None \
173173
else None
174-
# Setup remote executors
175-
if not self.flags.local_executor:
174+
# Setup remote executors only if
175+
# --local-executor mode isn't enabled.
176+
if self.remote_executors_enabled:
176177
self.executors = ThreadlessPool(
177178
flags=self.flags,
178179
event_queue=event_queue,
@@ -193,7 +194,7 @@ def setup(self) -> None:
193194
def shutdown(self) -> None:
194195
assert self.acceptors
195196
self.acceptors.shutdown()
196-
if not self.flags.local_executor:
197+
if self.remote_executors_enabled:
197198
assert self.executors
198199
self.executors.shutdown()
199200
if self.flags.enable_events:
@@ -214,14 +215,18 @@ def _delete_pid_file(self) -> None:
214215
if self.flags.pid_file and os.path.exists(self.flags.pid_file):
215216
os.remove(self.flags.pid_file)
216217

218+
@property
219+
def remote_executors_enabled(self) -> bool:
220+
return self.flags.threadless and not self.flags.local_executor
221+
217222

218223
def main(**opts: Any) -> None:
219-
try:
220-
with Proxy(sys.argv[1:], **opts):
221-
while True:
224+
with Proxy(sys.argv[1:], **opts):
225+
while True:
226+
try:
222227
time.sleep(1)
223-
except KeyboardInterrupt:
224-
pass
228+
except KeyboardInterrupt:
229+
break
225230

226231

227232
def entry_point() -> None:

proxy/testing/test_case.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class TestCase(unittest.TestCase):
2323
"""Base TestCase class that automatically setup and tear down proxy.py."""
2424

2525
DEFAULT_PROXY_PY_STARTUP_FLAGS = [
26+
'--hostname', '127.0.0.1',
2627
'--port', '0',
2728
'--num-workers', '1',
2829
'--num-acceptors', '1',
@@ -37,16 +38,10 @@ def setUpClass(cls) -> None:
3738
cls.INPUT_ARGS = getattr(cls, 'PROXY_PY_STARTUP_FLAGS') \
3839
if hasattr(cls, 'PROXY_PY_STARTUP_FLAGS') \
3940
else cls.DEFAULT_PROXY_PY_STARTUP_FLAGS
40-
cls.INPUT_ARGS.append('--hostname')
41-
cls.INPUT_ARGS.append('0.0.0.0')
42-
cls.INPUT_ARGS.append('--port')
43-
cls.INPUT_ARGS.append('0')
44-
4541
cls.PROXY = Proxy(cls.INPUT_ARGS)
4642
cls.PROXY.flags.plugins[b'HttpProxyBasePlugin'].append(
4743
CacheResponsesPlugin,
4844
)
49-
5045
cls.PROXY.__enter__()
5146
assert cls.PROXY.acceptors
5247
cls.wait_for_server(cls.PROXY.flags.port)

tests/test_main.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from unittest import mock
1616

1717
from proxy.proxy import main, entry_point
18+
from proxy.common.constants import _env_threadless_compliant # noqa: WPS450
1819
from proxy.common.utils import bytes_
1920

2021
from proxy.common.constants import DEFAULT_ENABLE_DASHBOARD, DEFAULT_LOCAL_EXECUTOR, DEFAULT_LOG_LEVEL, DEFAULT_LOG_FILE
@@ -244,8 +245,9 @@ def test_enable_dashboard(
244245
mock_event_manager.assert_called_once()
245246
mock_event_manager.return_value.setup.assert_called_once()
246247
mock_event_manager.return_value.shutdown.assert_called_once()
247-
mock_executor_pool.assert_called_once()
248-
mock_executor_pool.return_value.setup.assert_called_once()
248+
if _env_threadless_compliant():
249+
mock_executor_pool.assert_called_once()
250+
mock_executor_pool.return_value.setup.assert_called_once()
249251
mock_acceptor_pool.assert_called_once()
250252
mock_acceptor_pool.return_value.setup.assert_called_once()
251253
mock_listener.return_value.setup.assert_called_once()
@@ -283,8 +285,9 @@ def test_enable_devtools(
283285
mock_parse_args.assert_called_once()
284286
# Currently --enable-devtools flag alone doesn't enable eventing core
285287
mock_event_manager.assert_not_called()
286-
mock_executor_pool.assert_called_once()
287-
mock_executor_pool.return_value.setup.assert_called_once()
288+
if _env_threadless_compliant():
289+
mock_executor_pool.assert_called_once()
290+
mock_executor_pool.return_value.setup.assert_called_once()
288291
mock_acceptor_pool.assert_called_once()
289292
mock_acceptor_pool.return_value.setup.assert_called_once()
290293
mock_listener.return_value.setup.assert_called_once()

0 commit comments

Comments
 (0)