Skip to content

Commit f162d45

Browse files
committed
add python-venv-stubber.sh
This allows us to build a python-venv ourselves and add stubbers at the end as necessary.
1 parent 499184a commit f162d45

File tree

2 files changed

+71
-58
lines changed

2 files changed

+71
-58
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/bin/sh
2+
# python virtual-envs are not relocatable
3+
# our only working choice is to rewrite these files and symlinks every time
4+
# because we promise that tea is relocatable *at any time*
5+
#FIXME requiring sed is a bit lame
6+
7+
if test -z "$VIRTUAL_ENV"; then
8+
echo "error: VIRTUAL_ENV not set" >&2
9+
exit 1
10+
fi
11+
12+
mkdir -p "$VIRTUAL_ENV/../bin"
13+
14+
CMD_NAME="$1"
15+
16+
cat <<EOF > "$VIRTUAL_ENV"/../bin/"$CMD_NAME"
17+
#!/usr/bin/env python
18+
19+
import os
20+
import sys
21+
import glob
22+
import shutil
23+
from pathlib import Path
24+
25+
# Determine directories and paths
26+
script_dir = os.path.dirname(os.path.realpath(__file__))
27+
virtual_env = os.path.normpath(os.path.join(script_dir, '..', 'venv'))
28+
arg0 = os.path.basename(sys.argv[0])
29+
python_path = shutil.which('python')
30+
python_home = os.path.dirname(python_path)
31+
32+
# Write pyvenv.cfg file
33+
pyvenv_cfg_path = os.path.join(virtual_env, 'pyvenv.cfg')
34+
with open(pyvenv_cfg_path, 'w') as f:
35+
f.write(f"home = {python_home}\ninclude-system-site-packages = false\nexecutable = {python_path}\n")
36+
37+
new_first_line = b"#!" + os.path.join(virtual_env, 'bin', 'python').encode('utf-8') + b"\n"
38+
39+
# Go through files in the bin directory
40+
for filepath in glob.glob(os.path.join(virtual_env, 'bin', '*')):
41+
if os.path.isfile(filepath) and not os.path.islink(filepath):
42+
with open(filepath, 'rb+') as f:
43+
first_two_chars = f.read(2)
44+
45+
if first_two_chars == b'#!':
46+
old_first_line = first_two_chars + f.readline() # Read the rest of the first line
47+
48+
if old_first_line != new_first_line:
49+
rest_of_file = f.read()
50+
f.seek(0)
51+
f.write(new_first_line + rest_of_file)
52+
f.truncate()
53+
54+
# Create symlink to the specified Python version in the virtual environment
55+
python_symlink = os.path.join(virtual_env, 'bin', 'python')
56+
57+
# Remove the symbolic link if it already exists
58+
if os.path.islink(python_symlink) or os.path.exists(python_symlink):
59+
os.remove(python_symlink)
60+
61+
os.symlink(python_path, python_symlink)
62+
63+
# Execute the corresponding script in the virtual environment
64+
arg0 = os.path.join(virtual_env, 'bin', arg0)
65+
args = sys.argv[1:]
66+
args.insert(0, arg0)
67+
os.execv(arg0, args)
68+
EOF
69+
70+
chmod +x "$VIRTUAL_ENV/../bin/$CMD_NAME"

share/brewkit/python-venv.sh

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -41,61 +41,4 @@ TMPDIR=$SRCROOT/xyz.tea.python.build \
4141
# our only working choice is to rewrite these files and symlinks every time
4242
# because we promise that tea is relocatable *at any time*
4343

44-
mkdir -p ../bin
45-
46-
#FIXME requiring sed is a bit lame
47-
cat <<EOF > ../bin/"$CMD_NAME"
48-
#!/usr/bin/env python
49-
50-
import os
51-
import sys
52-
import glob
53-
import shutil
54-
from pathlib import Path
55-
56-
# Determine directories and paths
57-
script_dir = os.path.dirname(os.path.realpath(__file__))
58-
virtual_env = os.path.normpath(os.path.join(script_dir, '..', 'venv'))
59-
arg0 = os.path.basename(sys.argv[0])
60-
python_path = shutil.which('python')
61-
python_home = os.path.dirname(python_path)
62-
63-
# Write pyvenv.cfg file
64-
pyvenv_cfg_path = os.path.join(virtual_env, 'pyvenv.cfg')
65-
with open(pyvenv_cfg_path, 'w') as f:
66-
f.write(f"home = {python_home}\ninclude-system-site-packages = false\nexecutable = {python_path}\n")
67-
68-
new_first_line = b"#!" + os.path.join(virtual_env, 'bin', 'python').encode('utf-8') + b"\n"
69-
70-
# Go through files in the bin directory
71-
for filepath in glob.glob(os.path.join(virtual_env, 'bin', '*')):
72-
if os.path.isfile(filepath) and not os.path.islink(filepath):
73-
with open(filepath, 'rb+') as f:
74-
first_two_chars = f.read(2)
75-
76-
if first_two_chars == b'#!':
77-
old_first_line = first_two_chars + f.readline() # Read the rest of the first line
78-
79-
if old_first_line != new_first_line:
80-
rest_of_file = f.read()
81-
f.seek(0)
82-
f.write(new_first_line + rest_of_file)
83-
f.truncate()
84-
85-
# Create symlink to the specified Python version in the virtual environment
86-
python_symlink = os.path.join(virtual_env, 'bin', 'python')
87-
88-
# Remove the symbolic link if it already exists
89-
if os.path.islink(python_symlink) or os.path.exists(python_symlink):
90-
os.remove(python_symlink)
91-
92-
os.symlink(python_path, python_symlink)
93-
94-
# Execute the corresponding script in the virtual environment
95-
arg0 = os.path.join(virtual_env, 'bin', arg0)
96-
args = sys.argv[1:]
97-
args.insert(0, arg0)
98-
os.execv(arg0, args)
99-
EOF
100-
101-
chmod +x ../bin/"$CMD_NAME"
44+
"$(dirname "$0")"/python-venv-stubber.sh "$CMD_NAME"

0 commit comments

Comments
 (0)