-
-
Notifications
You must be signed in to change notification settings - Fork 51
feat(pip): Add a clean-sheet pip implementation #650
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 16 commits
8ecc4f7
869c736
33f5861
f1677e3
be8e869
50fe90b
b33ffb6
c12d501
ae54cb6
cb05389
f18274f
39f8053
cde1870
0ce4ea9
5fc76f1
7119541
ea3d238
23f28bc
87fb65b
65f64b0
ef98024
6b24ccd
63854cb
f2edc08
35f7e53
e714a39
2e46a34
f175cf7
1ce369d
db91365
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template") | ||
load("//py/unstable:defs.bzl", "py_venv", "py_venv_binary") | ||
|
||
expand_template( | ||
name = "stamped", | ||
stamp_substitutions = { | ||
"<BUILD_TIMESTAMP>": "{{BUILD_TIMESTAMP}}", | ||
}, | ||
template = "say.py", | ||
) | ||
|
||
py_venv_binary( | ||
name = "say", | ||
srcs = [ | ||
":stamped", | ||
], | ||
imports = [ | ||
".", | ||
], | ||
main = ":stamped", | ||
deps = [ | ||
"@pip2//package:cowsay", | ||
"@pip2//package:click", | ||
], | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#!/usr/bin/env python3 | ||
import sys | ||
|
||
print("---") | ||
import _virtualenv | ||
|
||
output_base = _virtualenv.__file__.split("/execroot/")[0] | ||
execroot = f"{output_base}/execroot" | ||
external = f"{output_base}/external" | ||
runfiles = _virtualenv.__file__.split(".runfiles/")[0] + ".runfiles" | ||
|
||
def _simplify(s): | ||
if isinstance(s, str): | ||
return s \ | ||
.replace(sys.prefix, "${PYTHONHOME}") \ | ||
.replace(runfiles, "${RUNFILES}") \ | ||
.replace(execroot, "${BAZEL_EXECROOT}") \ | ||
.replace(external, "${BAZEL_EXTERNAL}") \ | ||
.replace(output_base, "${BAZEL_BASE}") | ||
|
||
elif isinstance(s, list): | ||
return [_simplify(it) for it in s] | ||
|
||
print("virtualenv:", _simplify(_virtualenv.__file__)) | ||
import sys | ||
print("sys.prefix:", _simplify(sys.prefix)) | ||
print("sys.path:") | ||
for it in _simplify(sys.path): | ||
print(" -", it) | ||
import site | ||
print("site.PREFIXES:") | ||
for it in _simplify(site.PREFIXES): | ||
print(" -", it) | ||
|
||
import cowsay | ||
import click | ||
|
||
@click.command() | ||
@click.argument("who", envvar="USER") | ||
def main(who): | ||
cowsay.cow(f'hello {who}! (built at <BUILD_TIMESTAMP>)') | ||
|
||
main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
load("//pip/private:extension.bzl", _pip = "pip") | ||
|
||
pip = _pip |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
load(":macros.bzl", "generate") | ||
|
||
generate() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
load(":macro.bzl", "generate") | ||
|
||
package(default_visibility = ["//visibility:public"]) | ||
|
||
generate() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
load("@bazel_skylib//lib:selects.bzl", "selects") | ||
load("//pip/private/constraints:defs.bzl", "MAJORS", "MINORS", "INTERPRETERS", "FLAGS") | ||
|
||
# FIXME: Where does abi 2/3/4 fit in here? | ||
# FIXME: Where do ABI feature flags fit in here? | ||
def generate(): | ||
""" | ||
Lay down `py3`, `py312`, `cp3`, `cp312` etc and critically `any`. | ||
|
||
The interpretation is a bit tricky because `cp` | ||
""" | ||
|
||
# FIXME: Is there a better/worse way to do this? | ||
selects.config_setting_group( | ||
name = "none", | ||
match_all = [ | ||
"//conditions:default", | ||
] | ||
) | ||
|
||
native.constraint_setting( | ||
name = "feature_pydebug", | ||
default_constraint_value = ":pydebug_disabled", | ||
) | ||
native.constraint_value( | ||
name = "pydebug_enabled", | ||
constraint_setting = ":feature_pydebug", | ||
) | ||
native.constraint_value( | ||
name = "pydebug_disabled", | ||
constraint_setting = ":feature_pydebug", | ||
) | ||
|
||
native.constraint_setting( | ||
name = "feature_pymalloc", | ||
default_constraint_value = ":pymalloc_disabled", | ||
) | ||
native.constraint_value( | ||
name = "pymalloc_enabled", | ||
constraint_setting = ":feature_pymalloc", | ||
) | ||
native.constraint_value( | ||
name = "pymalloc_disabled", | ||
constraint_setting = ":feature_pymalloc", | ||
) | ||
|
||
native.constraint_setting( | ||
name = "feature_freethreading", | ||
default_constraint_value = ":freethreading_disabled", | ||
) | ||
native.constraint_value( | ||
name = "freethreading_enabled", | ||
constraint_setting = ":feature_freethreading", | ||
) | ||
native.constraint_value( | ||
name = "freethreading_disabled", | ||
constraint_setting = ":feature_freethreading", | ||
) | ||
|
||
native.constraint_setting( | ||
name = "feature_wide_unicode", | ||
default_constraint_value = ":wide_unicode_disabled", | ||
) | ||
native.constraint_value( | ||
name = "wide_unicode_enabled", | ||
constraint_setting = ":feature_wide_unicode", | ||
) | ||
native.constraint_value( | ||
name = "wide_unicode_disabled", | ||
constraint_setting = ":feature_wide_unicode", | ||
) | ||
|
||
native.alias( | ||
name = "abi3", | ||
actual = "is_py33" | ||
) | ||
|
||
for interpreter in INTERPRETERS: | ||
for major in MAJORS: | ||
# selects.config_setting_group( | ||
# name = "{}{}".format(interpreter, major), | ||
# match_all = [ | ||
# "//pip/private/constraints/python/interpreter:{}".format(interpreter), | ||
# "//pip/private/constraints/python/major:{}".format(major), | ||
# ] | ||
# ) | ||
|
||
for minor in MINORS: | ||
selects.config_setting_group( | ||
name = "is_{}{}{}".format(interpreter, major, minor), | ||
match_all = [ | ||
# "//pip/private/constraints/python/interpreter:{}".format(interpreter), | ||
"//pip/private/constraints/python/major:{}".format(major), | ||
"//pip/private/constraints/python/minor:{}".format(minor), | ||
] | ||
) | ||
|
||
for d in [False, True]: | ||
for m in [False, True]: | ||
for t in [False, True]: | ||
for u in [False, True]: | ||
selects.config_setting_group( | ||
# This is a bit out of hand I admit | ||
name = "{0}{1}{2}{3}{4}{5}{6}".format( | ||
interpreter, | ||
major, | ||
minor, | ||
"d" if d else "", | ||
"m" if m else "", | ||
"t" if t else "", | ||
"u" if u else "", | ||
), | ||
match_all = ( | ||
[ | ||
":is_{}{}{}".format(interpreter, major, minor), | ||
] | ||
+ ([":pydebug_enabled"] if d else []) | ||
+ ([":pymalloc_enabled"] if m else []) | ||
+ ([":freethreading_enabled"] if t else []) | ||
+ ([":wide_unicode_enabled"] if u else []) | ||
), | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
load("@bazel_skylib//lib:selects.bzl", "selects") | ||
|
||
MAJORS = [2, 3] # There is no 4 | ||
MINORS = range(0, 21) | ||
PATCHES = range(0, 31) | ||
INTERPRETERS = [ | ||
"py", # Generic | ||
"cp", # CPython | ||
# "jy", # Jython | ||
# "ip", # IronPython | ||
# "pp", # PyPy, has its own ABI scheme :| | ||
] | ||
# FIXME: We're ignoring these for now which isn't ideal | ||
FLAGS = { | ||
"d": "pydebug", | ||
"m": "pymalloc", | ||
"t": "freethreading", | ||
"u": "wide-unicode", # Deprecated in 3.13 | ||
} | ||
|
||
def generate_gte_ladder(stages): | ||
""" | ||
Accept a list of names of individual conditions representing specific versions. | ||
These names happen to be in ascending order and are generated by some other codepath. | ||
|
||
Given these conditon lable names generate a sequence ("ladder") of equality | ||
comparison operations + or with the "greater" comparison. | ||
|
||
So for [macos_10_0, macos_10_1, macos_11_0, macos_11_1, ...] | ||
We want to get | ||
|
||
selects.config_setting_group( | ||
name = "gte_macos_11_0", | ||
match_any = [ | ||
":macos_11_0", | ||
":gte_macos_10_1", | ||
], | ||
) | ||
selects.config_setting_group( | ||
name = "gte_macos_10_1", | ||
match_any = [ | ||
":macos_10_1", | ||
":gte_macos_10_0", | ||
], | ||
) | ||
|
||
As an added refinement the stages are a struct | ||
|
||
struct( | ||
name = <name of the ladder step>, | ||
condition = <condition for this ladder step>, | ||
) | ||
|
||
""" | ||
|
||
# We loop up to the second-to-last item to ensure we always have a 'next' stage. | ||
for i, current_stage in enumerate(stages): | ||
selects.config_setting_group( | ||
name = "{}".format(current_stage.name), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
match_any = [ | ||
":{}".format(current_stage.condition), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
] + ([":{}".format(stages[i+1].name)] if i+1 < len(stages) else []), | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
load(":macro.bzl", "generate") | ||
|
||
package(default_visibility = ["//visibility:public"]) | ||
|
||
generate() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally
%s
is faster than.format
because it avoids a function call and has simpler (faster) arg conversion. Also if you have only a single substitution it helps even more because you don't even need to construct a tuple. Up to you where to use it, but at least for the functions in the extension that are called repeatedly I would strongly consider it. (Honestly I pretty much always use it unless I have a complex/multiline template with 4+ args and/or using an arg multiple times)