Skip to content
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

feat: expose 'pip_utils.normalize_name' function #1542

Merged
merged 7 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ Breaking changes:
* (pip) Support for using [PEP621](https://peps.python.org/pep-0621/) compliant
`pyproject.toml` for creating a resolved `requirements.txt` file.

* (utils) Added a `pip_utils` struct with a `normalize_name` function to allow users
to find out how `rules_python` would normalize a PyPI distribution name.

## [0.26.0] - 2023-10-06

### Changed
Expand Down
2 changes: 1 addition & 1 deletion examples/pip_parse_vendored/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ genrule(
cmd = " | ".join([
"cat $<",
# Insert our load statement after the existing one so we don't produce a file with buildifier warnings
"""sed -e '/^load.*.whl_library/i\\'$$'\\n''load("@python39//:defs.bzl", "interpreter")'""",
"""sed -e '/^load.*.pip.bzl/i\\'$$'\\n''load("@python39//:defs.bzl", "interpreter")'""",
# Replace the bazel 6.0.0 specific comment with something that bazel 5.4.0 would produce.
# This enables this example to be run as a test under bazel 5.4.0.
"""sed -e 's#@//#//#'""",
Expand Down
14 changes: 6 additions & 8 deletions examples/pip_parse_vendored/requirements.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ from //:requirements.txt
"""

load("@python39//:defs.bzl", "interpreter")
load("@rules_python//python:pip.bzl", "pip_utils")
load("@rules_python//python/pip_install:pip_repository.bzl", "whl_library")

all_requirements = ["@pip//certifi:pkg", "@pip//charset_normalizer:pkg", "@pip//idna:pkg", "@pip//requests:pkg", "@pip//urllib3:pkg"]
Expand All @@ -19,25 +20,22 @@ _packages = [("pip_certifi", "certifi==2023.7.22 --hash=sha256:539cc1d13202e
_config = {"download_only": False, "enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600}
_annotations = {}

def _clean_name(name):
return name.replace("-", "_").replace(".", "_").lower()

def requirement(name):
return "@pip//{}:{}".format(_clean_name(name), "pkg")
return "@pip//{}:{}".format(pip_utils.normalize_name(name), "pkg")

def whl_requirement(name):
return "@pip//{}:{}".format(_clean_name(name), "whl")
return "@pip//{}:{}".format(pip_utils.normalize_name(name), "whl")

def data_requirement(name):
return "@pip//{}:{}".format(_clean_name(name), "data")
return "@pip//{}:{}".format(pip_utils.normalize_name(name), "data")

def dist_info_requirement(name):
return "@pip//{}:{}".format(_clean_name(name), "dist_info")
return "@pip//{}:{}".format(pip_utils.normalize_name(name), "dist_info")

def entry_point(pkg, script = None):
if not script:
script = pkg
return "@pip_" + _clean_name(pkg) + "//:rules_python_wheel_entry_point_" + script
return "@pip_" + pip_utils.normalize_name(pkg) + "//:rules_python_wheel_entry_point_" + script

def _get_annotation(requirement):
# This expects to parse `setuptools==58.2.0 --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11`
Expand Down
19 changes: 11 additions & 8 deletions python/pip.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ load("//python/pip_install:pip_repository.bzl", "pip_repository", _package_annot
load("//python/pip_install:requirements.bzl", _compile_pip_requirements = "compile_pip_requirements")
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED")
load("//python/private:full_version.bzl", "full_version")
load("//python/private:normalize_name.bzl", "normalize_name")
load("//python/private:render_pkg_aliases.bzl", "NO_MATCH_ERROR_MESSAGE_TEMPLATE")

compile_pip_requirements = _compile_pip_requirements
Expand Down Expand Up @@ -86,7 +87,7 @@ _process_requirements(
requirements_bzl = """\
# Generated by python/pip.bzl

load("@{rules_python}//python:pip.bzl", "whl_library_alias")
load("@{rules_python}//python:pip.bzl", "whl_library_alias", "pip_utils")
{load_statements}

_wheel_names = []
Expand All @@ -106,20 +107,17 @@ def _process_requirements(pkg_labels, python_version, repo_prefix):

{process_requirements_calls}

def _clean_name(name):
return name.replace("-", "_").replace(".", "_").lower()

def requirement(name):
return "{macro_tmpl}".format(_clean_name(name), "pkg")
return "{macro_tmpl}".format(pip_utils.normalize_name(name), "pkg")

def whl_requirement(name):
return "{macro_tmpl}".format(_clean_name(name), "whl")
return "{macro_tmpl}".format(pip_utils.normalize_name(name), "whl")

def data_requirement(name):
return "{macro_tmpl}".format(_clean_name(name), "data")
return "{macro_tmpl}".format(pip_utils.normalize_name(name), "data")

def dist_info_requirement(name):
return "{macro_tmpl}".format(_clean_name(name), "dist_info")
return "{macro_tmpl}".format(pip_utils.normalize_name(name), "dist_info")

def entry_point(pkg, script = None):
fail("Not implemented yet")
Expand Down Expand Up @@ -278,3 +276,8 @@ def multi_pip_parse(name, default_version, python_versions, python_interpreter_t
default_version = default_version,
pip_parses = pip_parses,
)

# Extra utilities visible to rules_python users.
pip_utils = struct(
normalize_name = normalize_name,
)
4 changes: 3 additions & 1 deletion python/pip_install/pip_repository.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ def _pip_repository_impl(rctx):
bzl_packages = dict(sorted([[name, normalize_name(name)] for name, _ in parsed_requirements_txt.requirements]))

imports = [
# NOTE: Maintain the order consistent with `buildifier`
'load("@rules_python//python:pip.bzl", "pip_utils")',
'load("@rules_python//python/pip_install:pip_repository.bzl", "whl_library")',
]

Expand Down Expand Up @@ -337,7 +339,7 @@ def _pip_repository_impl(rctx):
"%%ANNOTATIONS%%": _format_dict(_repr_dict(annotations)),
"%%CONFIG%%": _format_dict(_repr_dict(config)),
"%%EXTRA_PIP_ARGS%%": json.encode(options),
"%%IMPORTS%%": "\n".join(sorted(imports)),
"%%IMPORTS%%": "\n".join(imports),
"%%MACRO_TMPL%%": macro_tmpl,
"%%NAME%%": rctx.attr.name,
"%%PACKAGES%%": _format_repr_list(
Expand Down
13 changes: 5 additions & 8 deletions python/pip_install/pip_repository_requirements.bzl.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,22 @@ _packages = %%PACKAGES%%
_config = %%CONFIG%%
_annotations = %%ANNOTATIONS%%

def _clean_name(name):
return name.replace("-", "_").replace(".", "_").lower()

def requirement(name):
return "%%MACRO_TMPL%%".format(_clean_name(name), "pkg")
return "%%MACRO_TMPL%%".format(pip_utils.normalize_name(name), "pkg")

def whl_requirement(name):
return "%%MACRO_TMPL%%".format(_clean_name(name), "whl")
return "%%MACRO_TMPL%%".format(pip_utils.normalize_name(name), "whl")

def data_requirement(name):
return "%%MACRO_TMPL%%".format(_clean_name(name), "data")
return "%%MACRO_TMPL%%".format(pip_utils.normalize_name(name), "data")

def dist_info_requirement(name):
return "%%MACRO_TMPL%%".format(_clean_name(name), "dist_info")
return "%%MACRO_TMPL%%".format(pip_utils.normalize_name(name), "dist_info")

def entry_point(pkg, script = None):
if not script:
script = pkg
return "@%%NAME%%_" + _clean_name(pkg) + "//:rules_python_wheel_entry_point_" + script
return "@%%NAME%%_" + pip_utils.normalize_name(pkg) + "//:rules_python_wheel_entry_point_" + script

def _get_annotation(requirement):
# This expects to parse `setuptools==58.2.0 --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11`
Expand Down
17 changes: 8 additions & 9 deletions python/private/bzlmod/requirements.bzl.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
@generated by rules_python pip.parse bzlmod extension.
"""

load("@rules_python//python:pip.bzl", "pip_utils")

all_requirements = %%ALL_REQUIREMENTS%%

all_whl_requirements_by_package = %%ALL_WHL_REQUIREMENTS_BY_PACKAGE%%
Expand All @@ -11,20 +13,17 @@ all_whl_requirements = all_whl_requirements_by_package.values()

all_data_requirements = %%ALL_DATA_REQUIREMENTS%%

def _clean_name(name):
return name.replace("-", "_").replace(".", "_").lower()

def requirement(name):
return "%%MACRO_TMPL%%".format(_clean_name(name), "pkg")
return "%%MACRO_TMPL%%".format(pip_utils.normalize_name(name), "pkg")

def whl_requirement(name):
return "%%MACRO_TMPL%%".format(_clean_name(name), "whl")
return "%%MACRO_TMPL%%".format(pip_utils.normalize_name(name), "whl")

def data_requirement(name):
return "%%MACRO_TMPL%%".format(_clean_name(name), "data")
return "%%MACRO_TMPL%%".format(pip_utils.normalize_name(name), "data")

def dist_info_requirement(name):
return "%%MACRO_TMPL%%".format(_clean_name(name), "dist_info")
return "%%MACRO_TMPL%%".format(pip_utils.normalize_name(name), "dist_info")

def entry_point(pkg, script = None):
"""entry_point returns the target of the canonical label of the package entrypoints.
Expand All @@ -43,7 +42,7 @@ py_console_script_binary(
)
```
""".format(
pkg = _clean_name(pkg),
pkg_label = "%%MACRO_TMPL%%".format(_clean_name(pkg), "pkg"),
pkg = pip_utils.normalize_name(pkg),
pkg_label = "%%MACRO_TMPL%%".format(pip_utils.normalize_name(pkg), "pkg"),
aignas marked this conversation as resolved.
Show resolved Hide resolved
script = script,
))