Skip to content

Commit 49faaf0

Browse files
author
Jonathan Poole
authored
Binary python_wheel() (#79)
* Allow python wheels to be ran * Fix type
1 parent ceeae99 commit 49faaf0

File tree

6 files changed

+123
-16
lines changed

6 files changed

+123
-16
lines changed

.github/workflows/plugin.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ jobs:
99
- name: Setup python
1010
uses: actions/setup-python@v2
1111
with:
12-
python-version: '3.6.9'
12+
python-version: '3.10.6'
13+
- name: Set profile
14+
run: export PLZ_CONFIG_PROFILE=ci && echo $PATH
1315
- name: Run tests
1416
run: ./pleasew test --log_file plz-out/log/test.log -e e2e
1517
- name: Run e2e test
16-
run: ./pleasew test --log_file plz-out/log/e2e.log -i e2e
18+
run: ./pleasew test --profile ci --log_file plz-out/log/e2e.log -i e2e
1719
- name: Archive logs
1820
if: always()
1921
uses: actions/upload-artifact@v2

.plzconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ ImportPath = github.com/please-build/python-rules
1414
gotool = //third_party/go:toolchain|go
1515

1616

17+
[Plugin "python"]
18+
DisableVendorFlags = true
19+
1720
[PluginDefinition]
1821
name = python
1922

build_defs/python.build_defs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ def pip_library(name:str, version:str, labels:list=[], hashes:list=None, package
477477
def python_wheel(name:str, version:str, labels:list=[], hashes:list=None, package_name:str=None,
478478
outs:list=None, post_install_commands:list=None, patch:str|list=None, licences:list=None,
479479
test_only:bool&testonly=False, repo:str=None, zip_safe:bool=True, visibility:list=None,
480-
deps:list=[], name_scheme:str=None, strip:list=['*.pyc', 'tests']):
480+
deps:list=[], name_scheme:str=None, strip:list=['*.pyc', 'tests'], binary = False, entry_points={}):
481481
"""Downloads a Python wheel and extracts it.
482482

483483
This is a lightweight pip-free alternative to pip_library which supports cross-compiling.
@@ -509,7 +509,15 @@ def python_wheel(name:str, version:str, labels:list=[], hashes:list=None, packag
509509
name_scheme (str): The templatized wheel naming scheme (available template variables
510510
are `url_base`, `package_name`, `initial`, and `version`).
511511
strip (list): Files to strip after install. Note that these are done at any level.
512+
binary (bool): Whether this wheel should be executable. This assumes that the wheel will contain a __main__ module
513+
with a main() function. If this is not the case, then entry_points should be used.
514+
entry_points (dict|str): Any entry points into this wheel. These relate to the entrypoints.txt in the dist-info of
515+
the wheel, which define a module, and function in the format "module.path:function".
516+
This parameter can be a string, in which case the rule can be ran directly, or a
517+
dictionary, for example `{"protoc", "protoc.__main__:main"}. For the latter, each key can
518+
be ran using annotated labels, e.g. `plz run //third_party/python:protobuf|protoc`
512519
"""
520+
binary = binary or entry_points
513521
package_name = package_name or name.replace('-', '_')
514522
initial = package_name[0]
515523
url_base = repo or CONFIG.PYTHON.WHEEL_REPO
@@ -590,8 +598,10 @@ def python_wheel(name:str, version:str, labels:list=[], hashes:list=None, packag
590598
before, _, after = outs[0].partition('/')
591599
if after:
592600
cmd = f'rm -rf {before} && {cmd}'
593-
return build_rule(
601+
602+
lib_rule = build_rule(
594603
name = name,
604+
tag = "lib_rule" if binary else None,
595605
srcs = [wheel_rule],
596606
hashes = None if CONFIG.FF_PYTHON_WHEEL_HASHING else hashes,
597607
outs = outs or [name],
@@ -604,7 +614,52 @@ def python_wheel(name:str, version:str, labels:list=[], hashes:list=None, packag
604614
labels = labels + [label] + ["link:plz-out/python/venv"],
605615
provides = {'py': wheel_rule},
606616
)
607-
617+
if binary:
618+
entry_points = entry_points or f"{package_name}.__main__:main"
619+
if isinstance(entry_points, str):
620+
return _wheel_entrypoint_binary(
621+
name = name,
622+
entrypoint = entry_points,
623+
lib_rule = lib_rule,
624+
visibility = visibility,
625+
test_only = test_only,
626+
)
627+
628+
entry_point_binaries = [_wheel_entrypoint_binary(
629+
name = tag(name, f"{alias}_bin"),
630+
entrypoint = ep,
631+
lib_rule = lib_rule,
632+
visibility = visibility,
633+
test_only = test_only,
634+
out = f"{alias}.pex",
635+
) for alias, ep in entry_points.items()]
636+
637+
return filegroup(
638+
name = name,
639+
srcs = entry_point_binaries,
640+
entry_points = {k: f"{k}.pex" for k in entry_points.keys()},
641+
provides = {'py': wheel_rule}, # So things can still depend on this as a library
642+
binary=True,
643+
test_only=test_only,
644+
)
645+
return lib_rule
646+
647+
def _wheel_entrypoint_binary(name:str, entrypoint:str, lib_rule, visibility, test_only, out=None):
648+
module, _, func = entrypoint.rpartition(":")
649+
main = text_file(
650+
name = tag(name, "main"),
651+
out = f"__{name}_main__.py",
652+
content = f"import {module} as m\nm.{func}()",
653+
test_only = test_only,
654+
)
655+
return python_binary(
656+
name = name,
657+
main = main,
658+
out = out,
659+
deps = [lib_rule],
660+
test_only = test_only,
661+
visibility = visibility,
662+
)
608663

609664
def _interpreter_cmd(interpreter:str):
610665
return f'$(out {interpreter})' if interpreter.startswith('//') or interpreter.startswith(':') else interpreter

test/expected_labels_on_grpcio.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
py
2-
pip:grpcio==1.32.0
2+
pip:grpcio==1.49.1

test/expected_labels_on_numpy.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
py
2-
pip:numpy==1.18.4
2+
pip:numpy==1.23.4
33
py:zip-unsafe

third_party/python/BUILD

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ python_wheel(
8989
python_wheel(
9090
name = "dateutil",
9191
package_name = "python_dateutil",
92-
hashes = ["5179fabb692e3ec5a6e994eb9a72a6f4498f19106774672fd7e664a7aa9f49c3"],
92+
hashes = ["961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"],
9393
test_only = True, # Not used by plz itself.
94-
version = "2.4.0",
94+
version = "2.8.2",
9595
deps = [":six"],
9696
)
9797

@@ -112,6 +112,7 @@ if is_platform(
112112
"https://files.pythonhosted.org/packages/16/e0/fc9f7bd9b84e6b41d0aad1a113e36714aac0c0a9b307aca5f9af443bc50f/coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl",
113113
"https://files.pythonhosted.org/packages/a4/3a/8f7b217265503eae2b0ea97e714e2709e1e84ee13cd3ca6abdff1e99e76c/coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl",
114114
"https://files.pythonhosted.org/packages/a4/79/625f1ed5da2a69f52fb44e0b7ca1b470437ff502348c716005a98a71cd49/coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl",
115+
"https://files.pythonhosted.org/packages/d4/3e/4f6451b8b09a1eb2d0e7f61a3d7019bd98d556fc5343378f76e8905b2789/coverage-5.5-cp310-cp310-manylinux1_x86_64.whl",
115116
]
116117
elif is_platform(
117118
arch = "amd64",
@@ -123,6 +124,7 @@ elif is_platform(
123124
"https://files.pythonhosted.org/packages/52/44/5df49f3b462a0f5818a2f6f206d6523ff21ff9b21c1eb2906f8a31aa321c/coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl",
124125
"https://files.pythonhosted.org/packages/b6/26/b53bf0fef1b4bce6f7d61fef10fbf924d943987d4c9e53c394ecebff3673/coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl",
125126
"https://files.pythonhosted.org/packages/0d/8a/3b13c4e1f241a7083a4ee9986b969f0238f41dcd7a8990c786bc3b4b5b19/coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl",
127+
"https://files.pythonhosted.org/packages/6b/a2/43dd30964103a7ff1fd03392a30a5b08105bc85d1bafbfc51023a1bb4fd3/coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl",
126128
]
127129
else:
128130
urls = [
@@ -210,8 +212,8 @@ python_wheel(
210212
"_pytest",
211213
"pytest",
212214
],
213-
hashes = ["5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"],
214-
version = "5.4.3",
215+
hashes = ["1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"],
216+
version = "7.1.3",
215217
deps = [
216218
":attrs",
217219
":funcsigs",
@@ -221,7 +223,20 @@ python_wheel(
221223
":pluggy",
222224
":py",
223225
":six",
226+
":wcwidth",
227+
":iniconfig",
224228
],
229+
entry_points="pytest:main",
230+
)
231+
232+
python_wheel(
233+
name = "iniconfig",
234+
version = "1.1.1",
235+
)
236+
237+
python_wheel(
238+
name = "wcwidth",
239+
version = "0.2.5",
225240
)
226241

227242
python_wheel(
@@ -240,6 +255,10 @@ python_wheel(
240255
":traceback2",
241256
":win_unicode_console",
242257
],
258+
entry_points = {
259+
"behave": "behave.__main__:main",
260+
"behave_test": "setuptools_behave:behave_test",
261+
}
243262
)
244263

245264
python_wheel(
@@ -300,7 +319,7 @@ python_wheel(
300319
pip_library(
301320
name = "numpy",
302321
test_only = True,
303-
version = "1.18.4",
322+
version = "1.23.4",
304323
zip_safe = False,
305324
)
306325

@@ -335,7 +354,7 @@ pip_library(
335354
pip_library(
336355
name = "grpcio",
337356
test_only = True,
338-
version = "1.32.0",
357+
version = "1.49.1",
339358
deps = [
340359
":six",
341360
],
@@ -377,7 +396,7 @@ pip_library(
377396
pip_library(
378397
name = "h5py",
379398
test_only = True,
380-
version = "2.10.0",
399+
version = "3.7.0",
381400
deps = [
382401
":numpy",
383402
":six",
@@ -393,7 +412,7 @@ pip_library(
393412
pip_library(
394413
name = "pandas",
395414
test_only = True,
396-
version = "1.0.3",
415+
version = "1.5.0",
397416
deps = [
398417
":dateutil",
399418
":numpy",
@@ -411,7 +430,7 @@ pip_library(
411430
pip_library(
412431
name = "scipy",
413432
test_only = True,
414-
version = "1.5.2",
433+
version = "1.9.2",
415434
zip_safe = False,
416435
deps = [
417436
":numpy",
@@ -468,6 +487,34 @@ python_wheel(
468487
version = "1.5.0",
469488
)
470489

490+
python_wheel(
491+
name = "typing_extensions",
492+
outs = ["typing_extensions.py"],
493+
version = "4.4.0",
494+
hashes=["sha256: 16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"],
495+
)
496+
497+
python_wheel(
498+
name = "mypy_extensions",
499+
outs = ["mypy_extensions.py"],
500+
version = "0.4.3",
501+
hashes=["sha256: 090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"],
502+
)
503+
504+
python_wheel(
505+
name = "tomli",
506+
version = "2.0.1",
507+
hashes=["sha256: 939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"],
508+
)
509+
510+
python_wheel(
511+
name = "mypy",
512+
version = "0.982",
513+
deps = [":typing_extensions", ":mypy_extensions", ":tomli"],
514+
binary=True,
515+
hashes=["sha256: 1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"],
516+
)
517+
471518
filegroup(
472519
name = "unittest_bootstrap",
473520
srcs = [

0 commit comments

Comments
 (0)