Skip to content

Commit 7cb889a

Browse files
committed
Use pyenv-based wheel builder.
1 parent 0f1727d commit 7cb889a

File tree

8 files changed

+194
-157
lines changed

8 files changed

+194
-157
lines changed

Diff for: .github/workflows/ci.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
on: [push]
2+
3+
jobs:
4+
build:
5+
strategy:
6+
matrix:
7+
os: [ubuntu-latest, macos-latest, windows-latest]
8+
runs-on: ${{ matrix.os }}
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: configure
12+
shell: bash
13+
run: cat ./bootstrap.sh | bash

Diff for: .gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
__pycache__
2+
.env*
23
.hypothesis
34
.mypy_cache
5+
.patchelf
6+
.pyenv
47
.pytest_cache
58
.vscode
69
build

Diff for: .travis.yml

-152
This file was deleted.

Diff for: bootstrap.sh

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/bash
2+
PYTHON_VERSION="3.8.0"
3+
export MACOSX_DEPLOYMENT_TARGET="10.9"
4+
export PYENV_ROOT="$HOME/.pyenv"
5+
case $OSTYPE in
6+
linux-*) # TODO: Just install patchelf in pythonland
7+
PYENV_REPO="https://github.com/pyenv/pyenv.git"
8+
PATCHELF_REPO="https://github.com/nixos/patchelf.git"
9+
PATCHELF_ROOT=".patchelf"
10+
test -d "$PATCHELF_ROOT" && git -C "$PATCHELF_ROOT" pull || git clone "$PATCHELF_REPO" "$PATCHELF_ROOT" && \
11+
cd "$PATCHELF_ROOT" && ./bootstrap.sh && ./configure && make && cd -
12+
export PATH="$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PATCHELF_ROOT/src:$PATH"
13+
;;
14+
msys)
15+
PYENV_REPO="https://github.com/pyenv-win/pyenv-win.git"
16+
export PYENV="$PYENV_ROOT/pyenv-win"
17+
export PATH="$PYENV/bin:$PYENV/shims:$PATH"
18+
;;
19+
*)
20+
PYENV_REPO="https://github.com/pyenv/pyenv.git"
21+
export PATH="$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PYENV_ROOT/libexec:$PATH"
22+
;;
23+
esac
24+
test -d "$PYENV_ROOT" && git -C "$PYENV_ROOT" pull || git clone "$PYENV_REPO" "$PYENV_ROOT" && \
25+
test $OSTYPE != msys && eval "$(pyenv init -)" || true && \
26+
test $OSTYPE != msys && pyenv install --skip-existing "$PYTHON_VERSION" || pyenv install --quiet --skip-existing "$PYTHON_VERSION" && \
27+
pyenv global "$PYTHON_VERSION" && pyenv exec python -m venv .envbs && \
28+
test $OSTYPE != msys && source .envbs/bin/activate || source .envbs/Scripts/activate && \
29+
python build_wheels.py

Diff for: build_wheels.py

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
from configparser import ConfigParser
2+
from glob import glob
3+
from os import environ, makedirs
4+
from os.path import dirname
5+
from shutil import copy, rmtree
6+
from subprocess import CalledProcessError, run
7+
from sys import platform
8+
from tempfile import TemporaryDirectory
9+
import venv
10+
from sys import stdout, stderr
11+
12+
13+
# TODO: 32-bit Windows?
14+
15+
16+
LINUX = platform == "linux"
17+
MACOS = platform == "darwin"
18+
19+
PYENV_INSTALL_ARGS = "--skip-existing" if LINUX or MACOS else "--quiet --skip-existing"
20+
21+
WHEELS = {"3.5.4", "3.6.1", "3.7.0", "3.8.0"}
22+
DEFAULTS = {
23+
"python": "3.8.0",
24+
"test": "pip install --requirement requirements.txt && pytest",
25+
"test-if": 'true',
26+
"upload": "pip install --upgrade twine && twine upload --skip-existing dist/*",
27+
"upload-if": 'test "$TRAVIS_TAG"',
28+
"wheels": " ".join(sorted(WHEELS)),
29+
"windows": '32 64'
30+
}
31+
32+
33+
def _shell(command: str, *, version: str = "", echo: bool = False) -> None:
34+
if echo:
35+
print(f"\033[1m{command}\033[0m")
36+
run(f'pyenv install {PYENV_INSTALL_ARGS} {version or "3.8.0"}', check=True, shell=True)
37+
# with open(".exec.sh", "w") as file:
38+
# file.write(command)
39+
if LINUX or MACOS:
40+
run(f"bash -c 'eval \"$(pyenv init -)\" && pyenv shell {version or '3.8.0'} && python -m venv .env{version} && source .env{version}/bin/activate && {command}'", check=True, shell=True)
41+
else:
42+
run(f'pyenv global {version or "3.8.0"}', check=True, shell=True)
43+
run(f'pyenv exec python -m venv .env{version}', check=True, shell=True)
44+
# makedirs(f'.env{version}/bin', exist_ok=True)
45+
# try:
46+
# copy(f"{dirname(venv.__file__)}/scripts/common/activate", f'.env{version}/bin')
47+
# except OSError:
48+
# pass
49+
run(f'bash -c "source .env{version}/Scripts/activate && {command}"', check=True, shell=True)
50+
stderr.flush()
51+
stdout.flush()
52+
53+
54+
def main() -> None:
55+
parser = ConfigParser()
56+
parser.read("setup.cfg")
57+
config = DEFAULTS.copy()
58+
if "wheel" in parser:
59+
config.update(parser["wheel"])
60+
if unknown := config.keys() - DEFAULTS.keys():
61+
raise RuntimeError(
62+
f"Unknown config option{'' if len(unknown) == 1 else 's'}: {'/'.join(sorted(unknown))}! Expected {'/'.join(sorted(DEFAULTS))}."
63+
)
64+
wheels = set(config["wheels"].split())
65+
if not LINUX and not MACOS:
66+
windows = set(map(int, config['windows'].split()))
67+
if 64 in windows:
68+
for wheel in tuple(wheels):
69+
wheels.add(f'{wheel}-amd64')
70+
if 32 not in windows:
71+
for wheel in tuple(wheels):
72+
if not wheel.endswith('-amd64'):
73+
wheels.remove(wheel)
74+
# if unknown := WHEELS < wheels:
75+
# raise RuntimeError(
76+
# f"Unknown wheel version{'' if len(unknown) == 1 else 's'}: {'/'.join(sorted(unknown))}! Expected {'/'.join(sorted(WHEELS))}."
77+
# )
78+
# config["wheels"] = [f"{wheel}.0" for wheel in sorted(wheels)]
79+
config["wheels"] = sorted(wheels)
80+
rmtree("dist", ignore_errors=True)
81+
_shell("python -m pip install --upgrade pip")
82+
_shell("pip install --upgrade setuptools")
83+
_shell("python setup.py sdist --dist-dir=dist")
84+
with TemporaryDirectory() as dist:
85+
for version in config["wheels"]:
86+
_shell("python -m pip install --upgrade pip", version=version)
87+
if config["test"]:
88+
_shell("python setup.py develop", version=version)
89+
banner = f"Test: Python {version}"
90+
line = "=" * len(banner)
91+
print(f"\n{line}\n{banner}\n{line}\n")
92+
try:
93+
_shell(config["test-if"], version=version, echo=True)
94+
except CalledProcessError:
95+
pass
96+
else:
97+
_shell(config["test"], version=version, echo=True)
98+
finally:
99+
print(f"\n{line}\n")
100+
_shell("python setup.py develop --uninstall", version=version)
101+
_shell("pip install --upgrade setuptools wheel", version=version)
102+
if MACOS:
103+
# We lie for macOS, and say our 10.9 64-bit build is a 10.6
104+
# 32/64-bit one. This is because pip is conservative in what
105+
# wheels it will use, but Python installations are EXTREMELY
106+
# liberal in their macOS support. A typical user may be running
107+
# a 32/64 Python built for 10.6. In reality, we shouldn't worry
108+
# about supporting 32-bit Snow Leopard.
109+
_shell(
110+
f"python setup.py bdist_wheel --dist-dir={dist} --plat-name=macosx_10_6_intel", version=version
111+
)
112+
elif LINUX:
113+
_shell(f"python setup.py bdist_wheel --dist-dir={dist}", version=version)
114+
else:
115+
_shell(f"python setup.py bdist_wheel --dist-dir=dist", version=version)
116+
wheels = glob(f"{dist}/*")
117+
if LINUX:
118+
_shell("pip install --upgrade auditwheel")
119+
for wheel in wheels:
120+
_shell(f"auditwheel repair --wheel-dir=dist {wheel}")
121+
elif MACOS:
122+
_shell("pip install --upgrade delocate")
123+
for wheel in wheels:
124+
_shell(f"delocate-wheel --wheel-dir=dist --require-archs=intel {wheel}")
125+
# else:
126+
# for wheel in wheels:
127+
# copy(wheel, "dist")
128+
if config["upload"]:
129+
banner = "Upload"
130+
line = "=" * len(banner)
131+
print(f"\n{line}\n{banner}\n{line}\n")
132+
try:
133+
_shell(config["upload-if"], version=config["python"], echo=True)
134+
except CalledProcessError:
135+
pass
136+
else:
137+
_shell(config["upload"], version=config["python"], echo=True)
138+
finally:
139+
print(f"\n{line}\n")
140+
# _shell("python setup.py develop --uninstall", version=config["python"], )
141+
142+
print(*sorted(glob("dist/*")), sep="\n") # XXX
143+
144+
145+
if __name__ == "__main__":
146+
main()

Diff for: requirements-audit.txt

-2
This file was deleted.

Diff for: requirements.txt

-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,3 @@ black
33
hypothesis
44
invoke
55
pytest>=4.3.1
6-
setuptools>=45.0.0
7-
twine
8-
wheel>=0.33.6

Diff for: setup.cfg

+3
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
[metadata]
22
license_file = LICENSE.md
3+
4+
[wheel]
5+
wheels: 3.6.8 3.7.0 3.8.0

0 commit comments

Comments
 (0)