Skip to content

Commit b66c0db

Browse files
committed
Add bootstrap script/wheel module for flit_core
1 parent a452475 commit b66c0db

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

flit_core/bootstrap.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""Install flit_core without using any other tools.
2+
3+
Normally, you would install flit_core with pip like any other Python package.
4+
This script is meant to help with 'bootstrapping' other packaging
5+
systems, where you may need flit_core to build other packaging tools.
6+
7+
Pass a path to the site-packages directory or equivalent where the package
8+
should be placed. If omitted, this defaults to the site-packages directory
9+
of the Python running the script.
10+
"""
11+
import argparse
12+
import sys
13+
import sysconfig
14+
from pathlib import Path
15+
from tempfile import TemporaryDirectory
16+
from zipfile import ZipFile
17+
18+
from flit_core.wheel import add_wheel_arguments, build_flit_wheel
19+
20+
srcdir = Path(__file__).parent.resolve()
21+
22+
def extract_wheel(whl_path, dest):
23+
print("Installing to", dest.resolve())
24+
with ZipFile(whl_path) as zf:
25+
zf.extractall(dest)
26+
27+
def add_install_arguments(parser):
28+
parser.add_argument(
29+
'--wheeldir',
30+
'-w',
31+
type=str,
32+
help=f'wheel dist directory (defaults to {srcdir.joinpath("dist").resolve()})',
33+
)
34+
site_packages = Path(sysconfig.get_path('purelib'))
35+
parser.add_argument(
36+
'--installdir',
37+
'-i',
38+
type=Path,
39+
default=site_packages,
40+
help=f'installdir directory (defaults to {site_packages.resolve()}',
41+
)
42+
return parser
43+
44+
def get_dist_wheel(wheeldir):
45+
wheel_path = Path(wheeldir) if wheeldir is not None else srcdir.joinpath('dist')
46+
wheel_glob = wheel_path.glob('flit_core-*.whl')
47+
return next(wheel_glob, None)
48+
49+
def build(args):
50+
print("Building wheel")
51+
outdir = srcdir.joinpath('dist') if args.outdir is None else Path(args.outdir)
52+
whl_fname = build_flit_wheel(srcdir, outdir)
53+
print("Wheel built", outdir.joinpath(whl_fname).resolve())
54+
55+
def install(args):
56+
dist_wheel = get_dist_wheel(args.wheeldir)
57+
58+
# User asked to install wheel but none was found
59+
if dist_wheel is None and args.wheeldir is not None:
60+
print(f"No wheel found in {Path(args.wheeldir).resolve()}")
61+
sys.exit(1)
62+
63+
if dist_wheel is not None:
64+
print("Installing from wheel", dist_wheel.resolve())
65+
# Extract the prebuilt wheel
66+
extract_wheel(dist_wheel, args.installdir)
67+
else:
68+
# No prebuilt wheel found, build in temp dir
69+
with TemporaryDirectory(prefix='flit_core-bootstrap-') as td:
70+
whl_fname = build_flit_wheel(srcdir, Path(td))
71+
whl_path = Path(td).joinpath(whl_fname)
72+
extract_wheel(whl_path, args.installdir)
73+
74+
if __name__ == "__main__":
75+
parser = argparse.ArgumentParser()
76+
subparsers = parser.add_subparsers()
77+
78+
build_parser = subparsers.add_parser('build')
79+
build_parser = add_wheel_arguments(build_parser, srcdir)
80+
build_parser.set_defaults(func=build)
81+
82+
install_parser = subparsers.add_parser('install')
83+
install_parser = add_install_arguments(install_parser)
84+
install_parser.set_defaults(func=install)
85+
86+
args = parser.parse_args()
87+
args.func(args)

flit_core/flit_core/wheel.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import argparse
12
from base64 import urlsafe_b64encode
23
import contextlib
34
from datetime import datetime
@@ -8,6 +9,7 @@
89
import os.path as osp
910
import stat
1011
import tempfile
12+
from pathlib import Path
1113
from types import SimpleNamespace
1214
from typing import Optional
1315
import zipfile
@@ -215,3 +217,40 @@ def make_wheel_in(ini_path, wheel_directory, editable=False):
215217

216218
log.info("Built wheel: %s", wheel_path)
217219
return SimpleNamespace(builder=wb, file=wheel_path)
220+
221+
def add_wheel_arguments(parser, srcdir=None):
222+
if srcdir is None:
223+
srcdir = Path.cwd()
224+
parser.add_argument(
225+
'--srcdir',
226+
'-s',
227+
type=Path,
228+
default=Path.cwd(),
229+
help='source directory (defaults to current directory)',
230+
)
231+
232+
parser.add_argument(
233+
'--outdir',
234+
'-o',
235+
type=Path,
236+
default=srcdir.joinpath('dist'),
237+
help=f'output directory (defaults to {srcdir.joinpath("dist").resolve()})',
238+
)
239+
return parser
240+
241+
def build_flit_wheel(srcdir, outdir):
242+
"""Builds a wheel, places it in outdir"""
243+
pyproj_toml = Path(srcdir).joinpath('pyproject.toml')
244+
outdir.mkdir(parents=True, exist_ok=True)
245+
info = make_wheel_in(pyproj_toml, Path(outdir))
246+
return info.file.name
247+
248+
if __name__ == "__main__":
249+
parser = argparse.ArgumentParser()
250+
parser = add_wheel_arguments(parser)
251+
args = parser.parse_args()
252+
srcdir = Path.cwd() if args.srcdir is None else Path(args.srcdir)
253+
outdir = args.outdir
254+
print("Building wheel")
255+
whl_fname = build_flit_wheel(srcdir, outdir)
256+
print("Wheel built", outdir.joinpath(whl_fname).resolve())

flit_core/pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ dynamic = ["version"]
1919

2020
[project.urls]
2121
Source = "https://github.com/pypa/flit"
22+
23+
[tool.flit.sdist]
24+
include = ["bootstrap.py"]

0 commit comments

Comments
 (0)