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

Allow overriding constraints with '-o' in constraints file. #11537

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions news/8076.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow overriding constraints with ``-o`` in constraints file.
6 changes: 6 additions & 0 deletions src/pip/_internal/req/constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ def install_req_from_editable(
user_supplied: bool = False,
permit_editable_wheels: bool = False,
config_settings: Optional[Dict[str, str]] = None,
is_override: Optional[bool] = False,
) -> InstallRequirement:

parts = parse_req_from_editable(editable_req)
Expand All @@ -227,6 +228,7 @@ def install_req_from_editable(
hash_options=options.get("hashes", {}) if options else {},
config_settings=config_settings,
extras=parts.extras,
is_override=is_override,
)


Expand Down Expand Up @@ -383,6 +385,7 @@ def install_req_from_line(
line_source: Optional[str] = None,
user_supplied: bool = False,
config_settings: Optional[Dict[str, str]] = None,
is_override: Optional[bool] = False,
) -> InstallRequirement:
"""Creates an InstallRequirement from a name, which might be a
requirement, directory containing 'setup.py', filename, or URL.
Expand All @@ -406,6 +409,7 @@ def install_req_from_line(
constraint=constraint,
extras=parts.extras,
user_supplied=user_supplied,
is_override=is_override,
)


Expand Down Expand Up @@ -465,6 +469,7 @@ def install_req_from_parsed_requirement(
isolated=isolated,
user_supplied=user_supplied,
config_settings=config_settings,
is_override=parsed_req.is_override,
)

else:
Expand All @@ -478,6 +483,7 @@ def install_req_from_parsed_requirement(
line_source=parsed_req.line_source,
user_supplied=user_supplied,
config_settings=config_settings,
is_override=parsed_req.is_override,
)
return req

Expand Down
12 changes: 12 additions & 0 deletions src/pip/_internal/req/req_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,15 @@ def __init__(
constraint: bool,
options: Optional[Dict[str, Any]] = None,
line_source: Optional[str] = None,
is_override: Optional[bool] = False,
) -> None:
self.requirement = requirement
self.is_editable = is_editable
self.comes_from = comes_from
self.options = options
self.constraint = constraint
self.line_source = line_source
self.is_override = is_override


class ParsedLine:
Expand All @@ -109,6 +111,7 @@ def __init__(
self.lineno = lineno
self.opts = opts
self.constraint = constraint
self.is_override = opts.is_override

if args:
self.is_requirement = True
Expand Down Expand Up @@ -200,6 +203,7 @@ def handle_requirement_line(
constraint=line.constraint,
options=req_options,
line_source=line_source,
is_override=line.is_override,
)


Expand Down Expand Up @@ -391,6 +395,13 @@ def parse_line(line: str) -> Tuple[str, Values]:
if finder:
defaults.format_control = finder.format_control

tokens = line.strip().split(" ")
if tokens[0] in ("-o", "--override"):
is_override = True
# Only consider the rest of the line
line = " ".join(tokens[1:])
else:
is_override = False
args_str, options_str = break_args_options(line)

try:
Expand All @@ -399,6 +410,7 @@ def parse_line(line: str) -> Tuple[str, Values]:
raise OptionParsingError(f"Could not split options: {options_str}") from e

opts, _ = parser.parse_args(options, defaults)
opts.is_override = is_override

return args_str, opts

Expand Down
2 changes: 2 additions & 0 deletions src/pip/_internal/req/req_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def __init__(
extras: Collection[str] = (),
user_supplied: bool = False,
permit_editable_wheels: bool = False,
is_override: Optional[bool] = False,
) -> None:
assert req is None or isinstance(req, Requirement), req
self.req = req
Expand All @@ -99,6 +100,7 @@ def __init__(
self.editable = editable
self.permit_editable_wheels = permit_editable_wheels
self.legacy_install_reason: Optional[LegacyInstallReason] = None
self.is_override = is_override

# source_dir is the local directory where the linked requirement is
# located, or unpacked. In case unpacking is needed, creating and
Expand Down
2 changes: 1 addition & 1 deletion src/pip/_internal/resolution/resolvelib/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ def collect_root_requirements(
continue
assert ireq.name, "Constraint must be named"
name = canonicalize_name(ireq.name)
if name in collected.constraints:
if name in collected.constraints and not ireq.is_override:
collected.constraints[name] &= ireq
else:
collected.constraints[name] = Constraint.from_ireq(ireq)
Expand Down