-
-
Notifications
You must be signed in to change notification settings - Fork 646
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
Update the error/warning messages for stale/invalid lockfiles #12618
Changes from 8 commits
9a94ee9
d83c6e9
23aecb2
5147d25
c67f1cd
c8918ec
2c23bda
8b9ea01
db1e5d1
1356096
d2f4387
ac04497
f667881
6fcd36b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,10 @@ | |
import packaging.version | ||
from pkg_resources import Requirement | ||
|
||
from pants.backend.experimental.python.lockfile_metadata import LockfileMetadata | ||
from pants.backend.experimental.python.lockfile_metadata import ( | ||
InvalidLockfileReason, | ||
LockfileMetadata, | ||
) | ||
from pants.backend.python.target_types import MainSpecification | ||
from pants.backend.python.target_types import PexPlatformsField as PythonPlatformsField | ||
from pants.backend.python.target_types import PythonRequirementsField | ||
|
@@ -436,15 +439,7 @@ async def build_pex( | |
|
||
requirements_file_digest_contents = await Get(DigestContents, PathGlobs, globs) | ||
metadata = LockfileMetadata.from_lockfile(requirements_file_digest_contents[0].content) | ||
if not metadata.is_valid_for( | ||
request.requirements.lockfile_hex_digest, | ||
request.interpreter_constraints, | ||
python_setup.interpreter_universe, | ||
): | ||
if python_setup.invalid_lockfile_behavior == InvalidLockfileBehavior.error: | ||
raise ValueError("Invalid lockfile provided. [TODO(#12314): Improve message]") | ||
elif python_setup.invalid_lockfile_behavior == InvalidLockfileBehavior.warn: | ||
logger.warning("%s", "Invalid lockfile provided. [TODO(#12314): Improve message]") | ||
_validate_metadata(metadata, request, python_setup) | ||
|
||
requirements_file_digest = await Get(Digest, PathGlobs, globs) | ||
|
||
|
@@ -453,15 +448,7 @@ async def build_pex( | |
argv.extend(["--requirement", file_content.path]) | ||
|
||
metadata = LockfileMetadata.from_lockfile(file_content.content) | ||
if not metadata.is_valid_for( | ||
request.requirements.lockfile_hex_digest, | ||
request.interpreter_constraints, | ||
python_setup.interpreter_universe, | ||
): | ||
if python_setup.invalid_lockfile_behavior == InvalidLockfileBehavior.error: | ||
raise ValueError("Invalid lockfile provided. [TODO(#12314): Improve message]") | ||
elif python_setup.invalid_lockfile_behavior == InvalidLockfileBehavior.warn: | ||
logger.warning("%s", "Invalid lockfile provided. [TODO(#12314): Improve message]") | ||
_validate_metadata(metadata, request, python_setup) | ||
|
||
requirements_file_digest = await Get(Digest, CreateDigest([file_content])) | ||
else: | ||
|
@@ -515,6 +502,54 @@ async def build_pex( | |
) | ||
|
||
|
||
def _validate_metadata( | ||
metadata: LockfileMetadata, request: PexRequest, python_setup: PythonSetup | ||
) -> None: | ||
validation = metadata.is_valid_for( | ||
request.requirements.lockfile_hex_digest, | ||
request.interpreter_constraints, | ||
python_setup.interpreter_universe, | ||
) | ||
Eric-Arellano marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if validation: | ||
return | ||
|
||
message_parts = [ | ||
f"Invalid lockfile for PEX request `{request.output_filename}`.", | ||
"\n", | ||
] | ||
|
||
if InvalidLockfileReason.INVALIDATION_DIGEST_MISMATCH in validation.failure_reasons: | ||
message_parts.append( | ||
"The requirements set for this PEX request are different to the requirements set when " | ||
"the lockfile was generated. To fix this, you will need to regenerate the lockfile. " | ||
) | ||
message_parts.append( | ||
f"(Expected requirements digest: {request.requirements.lockfile_hex_digest}, " | ||
"actual: {metadata.requirements_invalidation_digest})" | ||
) | ||
message_parts.append("\n") | ||
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. This can use 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. Because the strings are bumping up agains the line length limit, using 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. Got it. FYI you could do this if you go with message_parts.extend([
(
"blah blah blah "
"blah blah"
),
(
"hola hola mundo "
"blah blah"
),
]) this is fine otherwise 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. Yeah, I know about |
||
|
||
if InvalidLockfileReason.INTERPRETER_CONSTRAINTS_MISMATCH in validation.failure_reasons: | ||
message_parts.append( | ||
"The lockfile was generated under different interpreter constraints to the constraints " | ||
"that are set. If you have overridden your project's interpreter constraints, you can " | ||
chrisjrn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"update them to specify a subset of the interpreters specified in the lockfile. If " | ||
"not, you will need to regenerate your lockfile. " | ||
) | ||
|
||
message_parts.append( | ||
"To regenerate the lockfile, follow the instructions in the header of the lockfile." | ||
) | ||
|
||
message = "\n".join(message_parts).strip() | ||
|
||
if python_setup.invalid_lockfile_behavior == InvalidLockfileBehavior.error: | ||
raise ValueError(message) | ||
elif python_setup.invalid_lockfile_behavior == InvalidLockfileBehavior.warn: | ||
logger.warning("%s", message) | ||
|
||
|
||
def _build_pex_description(request: PexRequest) -> str: | ||
if request.description: | ||
return request.description | ||
|
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.
No need for this because it's not a dataclass
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.
Declaring slots does make the class slightly more efficient under the hood, but I was mostly doing it for the benefit of type hinting. Is there a way to provide the type hints without declaring the slot?
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.
I don't think this results in actually using
__slots__
? Iiuc, you have to explicitly set__slots__
to get its benefit. Either way, we decided to not use__slots__
w/ Pants when I propsed it in #9469.Yeah, MyPy should already infer it thanks to your
__init__
.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.
bump - does this make sense?