Skip to content

Commit 3c8a629

Browse files
committed
Perform pip install as part of bootstrap.py
Also, install pip packages in local `out/python_deps` directory instead of installing system wide. This means we can consistently expect dev dependencies to be available in test code without needing to include an opt out mechanism. We were already doing this for `psutil`, but for `websockify` we made it optional. This means that only python scripts that explicitly add `out/python_deps` to their python path will be able use the packages, and in particular it means that the emscripten compiler itself won't end up implicitly/accidentally depending on them.
1 parent 5d2b2f1 commit 3c8a629

File tree

5 files changed

+27
-53
lines changed

5 files changed

+27
-53
lines changed

.circleci/config.yml

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,10 @@ commands:
6161
- run: ./bootstrap
6262
pip-install:
6363
description: "pip install"
64-
parameters:
65-
python:
66-
description: "Python executable to use"
67-
type: string
68-
default: python3
6964
steps:
7065
- run:
7166
name: pip install
72-
command: << parameters.python >> -m pip install -r requirements-dev.txt
67+
command: python3 -m pip install -r requirements-dev.txt
7368
install-rust:
7469
steps:
7570
- run:
@@ -186,7 +181,6 @@ commands:
186181
name: clear cache
187182
command: |
188183
./emcc --clear-cache
189-
- pip-install
190184
- run: apt-get install -q -y ninja-build ccache
191185
- run:
192186
name: Ccache stats and configuration
@@ -266,7 +260,6 @@ commands:
266260
- checkout
267261
- emsdk-env
268262
- bootstrap
269-
- pip-install
270263
- when:
271264
# We only set EMTEST_RETRY_FLAKY on pull requests. When we run
272265
# normal CI jobs on branches like main we still want to be able to
@@ -871,7 +864,6 @@ jobs:
871864
executor: linux-python
872865
steps:
873866
- checkout
874-
- pip-install
875867
- install-emsdk
876868
- run:
877869
name: install jsc
@@ -893,7 +885,6 @@ jobs:
893885
executor: linux-python
894886
steps:
895887
- checkout
896-
- pip-install
897888
- install-emsdk
898889
- run:
899890
name: install spidermonkey
@@ -920,7 +911,6 @@ jobs:
920911
EMTEST_SKIP_V8: "1"
921912
steps:
922913
- checkout
923-
- pip-install
924914
- install-emsdk
925915
# `install-node-version` only changes the NODE_JS_TEST (the version of
926916
# node used to run test), not NODE_JS (the version of node used to run the
@@ -1078,7 +1068,6 @@ jobs:
10781068
EMTEST_LACKS_WEBGPU: "1"
10791069
steps:
10801070
- checkout
1081-
- pip-install
10821071
- install-emsdk
10831072
- run-tests-chrome:
10841073
title: "browser"
@@ -1162,7 +1151,6 @@ jobs:
11621151
executor: focal
11631152
steps:
11641153
- checkout
1165-
- pip-install
11661154
- install-emsdk
11671155
- run-tests-firefox:
11681156
title: "browser64"
@@ -1191,8 +1179,6 @@ jobs:
11911179
name: Add python to bash path
11921180
command: echo "export PATH=\"$PATH:/c/Python27amd64/\"" >> $BASH_ENV
11931181
- install-emsdk
1194-
- pip-install:
1195-
python: "$EMSDK_PYTHON"
11961182
- run-tests-firefox-windows:
11971183
title: "browser on firefox on windows"
11981184
# skip browser.test_glbook, as it requires mingw32-make, which is not
@@ -1256,8 +1242,6 @@ jobs:
12561242
# note we do *not* build all libraries and freeze the cache; as we run
12571243
# only limited tests here, it's more efficient to build on demand
12581244
- install-emsdk
1259-
- pip-install:
1260-
python: "$EMSDK_PYTHON"
12611245
- run-tests:
12621246
title: "crossplatform tests"
12631247
test_targets: "--crossplatform-only"
@@ -1285,8 +1269,6 @@ jobs:
12851269
steps:
12861270
- setup-macos
12871271
- install-emsdk
1288-
- pip-install:
1289-
python: "$EMSDK_PYTHON"
12901272
- freeze-cache
12911273
- run-tests:
12921274
title: "crossplatform tests"

bootstrap.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
'test/third_party/googletest',
4040
'test/third_party/wasi-test-suite',
4141
], ['git', 'submodule', 'update', '--init']),
42+
('pip install', [
43+
'requirements-dev.txt',
44+
], [sys.executable, '-m', 'pip', 'install', '--root', 'out/python_deps', '-r', 'requirements-dev.txt']),
4245
]
4346

4447

@@ -84,6 +87,10 @@ def main(args):
8487
shutil.copy(utils.path_from_root(src), dst)
8588
return 0
8689

90+
env = os.environ.copy()
91+
env['PATH'] += os.pathsep + utils.path_from_root('out/python_deps')
92+
env['PYTHONPATH'] = utils.path_from_root('out/python_deps')
93+
8794
for name, deps, cmd in actions:
8895
if check_deps(name, deps):
8996
print('Up-to-date: %s' % name)
@@ -99,7 +106,7 @@ def main(args):
99106
if not cmd[0]:
100107
utils.exit_with_error(f'command not found: {orig_exe}')
101108
print(' -> %s' % ' '.join(cmd))
102-
subprocess.run(cmd, check=True, text=True, encoding='utf-8', cwd=utils.path_from_root())
109+
subprocess.run(cmd, check=True, text=True, encoding='utf-8', cwd=utils.path_from_root(), env=env)
103110
utils.safe_ensure_dirs(STAMP_DIR)
104111
utils.write_file(stamp_file, 'Timestamp file created by bootstrap.py')
105112
return 0

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ mypy_path = "third_party/,third_party/ply,third_party/websockify"
8686
files = [ "." ]
8787
exclude = '''
8888
(?x)(
89+
out |
8990
cache |
9091
third_party |
9192
conf\.py |

test/runner.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,24 @@
3232
import unittest
3333
from functools import cmp_to_key
3434

35-
# Setup
36-
3735
__rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
3836
sys.path.insert(0, __rootpath__)
3937

38+
# Before we do anthing else, check that the bootstrap script has been run.
39+
import bootstrap # noqa: I001
40+
bootstrap.check()
41+
42+
# Add `out/python_deps` to the python path. This is where the bootstrap
43+
# script install our python dev dependencis.
44+
sys.path.insert(0, os.path.join(__rootpath__, 'out', 'python_deps'))
45+
# Verify that we can import these dev dependencies and early exit if they
46+
# are missing
47+
try:
48+
import psutil # noqa: F401
49+
import websockify # type: ignore # noqa: F401
50+
except ModuleNotFoundError as e:
51+
raise Exception('Unable to import python dev dependencies (psutil/websockify). Run "./bootstrap" (or "python3 -m pip -r requirements-dev.txt --target out/python_deps") to install') from e
52+
4053
import browser_common
4154
import common
4255
import jsrun

test/test_sockets.py

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from subprocess import Popen
1313
from typing import List
1414

15+
import websockify # type: ignore
16+
1517
if __name__ == '__main__':
1618
raise Exception('do not run this file directly; do something like: test/runner sockets')
1719

@@ -34,22 +36,9 @@
3436

3537
npm_checked = False
3638

37-
EMTEST_SKIP_PYTHON_DEV_PACKAGES = int(os.getenv('EMTEST_SKIP_PYTHON_DEV_PACKAGES', '0'))
3839
EMTEST_SKIP_NODE_DEV_PACKAGES = int(os.getenv('EMTEST_SKIP_NODE_DEV_PACKAGES', '0'))
3940

4041

41-
def requires_python_dev_packages(func):
42-
assert callable(func)
43-
44-
@common.wraps(func)
45-
def decorated(self, *args, **kwargs):
46-
if EMTEST_SKIP_PYTHON_DEV_PACKAGES:
47-
return self.skipTest('python websockify based tests are disabled by EMTEST_SKIP_PYTHON_DEV_PACKAGES=1')
48-
return func(self, *args, **kwargs)
49-
50-
return decorated
51-
52-
5342
def clean_processes(processes):
5443
for p in processes:
5544
if getattr(p, 'exitcode', None) is None and getattr(p, 'returncode', None) is None:
@@ -86,11 +75,6 @@ def __enter__(self):
8675
process = Popen([os.path.abspath('server')])
8776
self.processes.append(process)
8877

89-
try:
90-
import websockify # type: ignore # noqa: PLC0415
91-
except ModuleNotFoundError:
92-
raise Exception('Unable to import module websockify. Run "python3 -m pip install websockify" or set environment variable EMTEST_SKIP_PYTHON_DEV_PACKAGES=1 to skip this test.') from None
93-
9478
# start the websocket proxy
9579
print('running websockify on %d, forward to tcp %d' % (self.listen_port, self.target_port), file=sys.stderr)
9680
# source_is_ipv6=True here signals to websockify that it should prefer ipv6 address when
@@ -211,8 +195,6 @@ def setUpClass(cls):
211195
def test_sockets_echo(self, harness_class, port, args):
212196
if harness_class == WebsockifyServerHarness and common.EMTEST_LACKS_NATIVE_CLANG:
213197
self.skipTest('requires native clang')
214-
if harness_class == WebsockifyServerHarness and EMTEST_SKIP_PYTHON_DEV_PACKAGES:
215-
self.skipTest('requires python websockify and EMTEST_SKIP_PYTHON_DEV_PACKAGES=1')
216198
if harness_class == CompiledServerHarness and EMTEST_SKIP_NODE_DEV_PACKAGES:
217199
self.skipTest('requires node ws and EMTEST_SKIP_NODE_DEV_PACKAGES=1')
218200

@@ -239,8 +221,6 @@ def test_sdl2_sockets_echo(self):
239221
def test_sockets_async_echo(self, harness_class, port, args):
240222
if harness_class == WebsockifyServerHarness and common.EMTEST_LACKS_NATIVE_CLANG:
241223
self.skipTest('requires native clang')
242-
if harness_class == WebsockifyServerHarness and EMTEST_SKIP_PYTHON_DEV_PACKAGES:
243-
self.skipTest('requires python websockify and EMTEST_SKIP_PYTHON_DEV_PACKAGES=1')
244224
if harness_class == CompiledServerHarness and EMTEST_SKIP_NODE_DEV_PACKAGES:
245225
self.skipTest('requires node ws and EMTEST_SKIP_NODE_DEV_PACKAGES=1')
246226

@@ -261,8 +241,6 @@ def test_sockets_async_bad_port(self):
261241
def test_sockets_echo_bigdata(self, harness_class, port, args):
262242
if harness_class == WebsockifyServerHarness and common.EMTEST_LACKS_NATIVE_CLANG:
263243
self.skipTest('requires native clang')
264-
if harness_class == WebsockifyServerHarness and EMTEST_SKIP_PYTHON_DEV_PACKAGES:
265-
self.skipTest('requires python websockify and EMTEST_SKIP_PYTHON_DEV_PACKAGES=1')
266244
if harness_class == CompiledServerHarness and EMTEST_SKIP_NODE_DEV_PACKAGES:
267245
self.skipTest('requires node ws and EMTEST_SKIP_NODE_DEV_PACKAGES=1')
268246
sockets_include = '-I' + test_file('sockets')
@@ -280,7 +258,6 @@ def test_sockets_echo_bigdata(self, harness_class, port, args):
280258
self.btest_exit('test_sockets_echo_bigdata.c', cflags=[sockets_include, '-DSOCKK=%d' % harness.listen_port] + args)
281259

282260
@no_windows('This test is Unix-specific.')
283-
@requires_python_dev_packages
284261
@requires_dev_dependency('ws')
285262
def test_sockets_partial(self):
286263
for harness in [
@@ -291,7 +268,6 @@ def test_sockets_partial(self):
291268
self.btest_exit('sockets/test_sockets_partial_client.c', assert_returncode=165, cflags=['-DSOCKK=%d' % harness.listen_port])
292269

293270
@no_windows('This test is Unix-specific.')
294-
@requires_python_dev_packages
295271
@requires_dev_dependency('ws')
296272
def test_sockets_select_server_down(self):
297273
for harness in [
@@ -302,7 +278,6 @@ def test_sockets_select_server_down(self):
302278
self.btest_exit('sockets/test_sockets_select_server_down_client.c', cflags=['-DSOCKK=%d' % harness.listen_port])
303279

304280
@no_windows('This test is Unix-specific.')
305-
@requires_python_dev_packages
306281
@requires_dev_dependency('ws')
307282
def test_sockets_select_server_closes_connection_rw(self):
308283
for harness in [
@@ -335,8 +310,6 @@ def test_enet(self):
335310
def test_nodejs_sockets_echo(self, harness_class, port, args):
336311
if harness_class == WebsockifyServerHarness and common.EMTEST_LACKS_NATIVE_CLANG:
337312
self.skipTest('requires native clang')
338-
if harness_class == WebsockifyServerHarness and EMTEST_SKIP_PYTHON_DEV_PACKAGES:
339-
self.skipTest('requires python websockify and EMTEST_SKIP_PYTHON_DEV_PACKAGES=1')
340313
if harness_class == CompiledServerHarness and EMTEST_SKIP_NODE_DEV_PACKAGES:
341314
self.skipTest('requires node ws and EMTEST_SKIP_NODE_DEV_PACKAGES=1')
342315

@@ -349,7 +322,6 @@ def test_nodejs_sockets_connect_failure(self):
349322
self.do_runf('sockets/test_sockets_echo_client.c', r'connect failed: (Connection refused|Host is unreachable)', regex=True, cflags=['-DSOCKK=666'], assert_returncode=NON_ZERO)
350323

351324
@requires_native_clang
352-
@requires_python_dev_packages
353325
def test_nodejs_sockets_echo_subprotocol(self):
354326
# Test against a Websockified server with compile time configured WebSocket subprotocol. We use a Websockified
355327
# server because as long as the subprotocol list contains binary it will configure itself to accept binary
@@ -362,7 +334,6 @@ def test_nodejs_sockets_echo_subprotocol(self):
362334
self.assertContained(['connect: ws://127.0.0.1:59168, base64,binary', 'connect: ws://127.0.0.1:59168/, base64,binary'], out)
363335

364336
@requires_native_clang
365-
@requires_python_dev_packages
366337
def test_nodejs_sockets_echo_subprotocol_runtime(self):
367338
# Test against a Websockified server with runtime WebSocket configuration. We specify both url and subprotocol.
368339
# In this test we have *deliberately* used the wrong port '-DSOCKK=12345' to configure the echo_client.c, so

0 commit comments

Comments
 (0)