-
-
Notifications
You must be signed in to change notification settings - Fork 372
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
Override requirements (at a given level) from a requirements file. #1209
base: main
Are you sure you want to change the base?
Changes from all commits
9a6e968
d8b0c09
96c6018
68bcfe6
23f201d
72c48f8
7f578ad
3f42195
6e31779
eb6c7b9
7f921bb
e6664c8
9cc1f65
1c9555b
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 |
---|---|---|
@@ -0,0 +1 @@ | ||
Support for pinned requirements files has been added |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -673,6 +673,12 @@ def _add_update_options( | |
help=f"Update requirements for the app{context_label}", | ||
) | ||
|
||
parser.add_argument( | ||
"--relock", | ||
action="store_true", | ||
help=f"Recalculate locked requirements for the app{context_label}", | ||
) | ||
Comment on lines
+676
to
+680
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. Why "relock" rather than simply "lock"? "Relock" implies that it was locked before, which isn't necessarily the case. 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. In the way it's defined in the PR at present, it is a relock, because the initial create call always passes If the setting is also exposed to the |
||
|
||
parser.add_argument( | ||
"--update-resources", | ||
action="store_true", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
import shutil | ||
import subprocess | ||
import sys | ||
import tempfile | ||
from datetime import date | ||
from pathlib import Path | ||
from typing import List, Optional | ||
|
@@ -487,7 +488,48 @@ def _install_app_requirements( | |
else: | ||
self.logger.info("No application requirements.") | ||
|
||
def install_app_requirements(self, app: BaseConfig, test_mode: bool): | ||
def _calc_app_requirements(self, app: BaseConfig, test_mode: bool, relock: bool): | ||
requires = app.requires.copy() if app.requires else [] | ||
if test_mode and app.test_requires: | ||
requires.extend(app.test_requires) | ||
|
||
lock_attr = "requires_lock" if not test_mode else "test_requires_lock" | ||
try: | ||
lock_value = getattr(app, lock_attr) | ||
except AttributeError: | ||
return requires | ||
else: | ||
lock_file = self.base_path / lock_value | ||
|
||
if relock: | ||
with tempfile.NamedTemporaryFile(mode="w+") as fpout: | ||
fpout.writelines(line + "\n" for line in requires) | ||
fpout.flush() | ||
res = self.tools[app].app_context.run( | ||
[ | ||
sys.executable, | ||
"-u", | ||
"-m", | ||
"piptools", | ||
"compile", | ||
fpout.name, | ||
"--output-file=-", | ||
], | ||
text=True, | ||
capture_output=True, | ||
check=True, | ||
) | ||
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. So... did you run this? Briefcase's If all we're looking to do is capture all of the output, |
||
lock_file.write_text(res.stdout) | ||
|
||
requires = [ | ||
line.split("#", 1)[0].strip() for line in lock_file.read_text().splitlines() | ||
] | ||
requires = [potential for potential in requires if potential != ""] | ||
return requires | ||
|
||
def install_app_requirements( | ||
self, app: BaseConfig, test_mode: bool, relock: bool = False | ||
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.
|
||
): | ||
"""Handle requirements for the app. | ||
|
||
This will result in either (in preferential order): | ||
|
@@ -504,9 +546,7 @@ def install_app_requirements(self, app: BaseConfig, test_mode: bool): | |
:param app: The config object for the app | ||
:param test_mode: Should the test requirements be installed? | ||
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. There's a missing docstring here. |
||
""" | ||
requires = app.requires.copy() if app.requires else [] | ||
if test_mode and app.test_requires: | ||
requires.extend(app.test_requires) | ||
requires = self._calc_app_requirements(app, test_mode, relock) | ||
|
||
try: | ||
requirements_path = self.app_requirements_path(app) | ||
|
@@ -766,7 +806,7 @@ def create_app(self, app: BaseConfig, test_mode: bool = False, **options): | |
self.install_app_code(app=app, test_mode=test_mode) | ||
|
||
self.logger.info("Installing requirements...", prefix=app.app_name) | ||
self.install_app_requirements(app=app, test_mode=test_mode) | ||
self.install_app_requirements(app=app, test_mode=test_mode, relock=True) | ||
|
||
self.logger.info("Installing application resources...", prefix=app.app_name) | ||
self.install_app_resources(app=app) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,14 @@ | |
from briefcase.exceptions import BriefcaseCommandError | ||
|
||
|
||
def _clean_relock(actions): | ||
for cmd, *rest in actions: | ||
if cmd not in {"run", "build", "create", "update"}: | ||
continue | ||
rest[-1].pop("relock", None) | ||
return actions | ||
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. I'm not sure what this is in aid of... the point of these tests is to confirm that the right arguments are being passed in to each stage. Post-processing the results to remove one of the arguments... doesn't make any sense to me. |
||
|
||
|
||
def test_specific_app(build_command, first_app, second_app): | ||
"""If a specific app is requested, build it.""" | ||
# Add two apps | ||
|
@@ -18,7 +26,7 @@ def test_specific_app(build_command, first_app, second_app): | |
build_command(first_app, **options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -47,7 +55,7 @@ def test_multiple_apps(build_command, first_app, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -81,7 +89,7 @@ def test_non_existent(build_command, first_app_config, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -121,7 +129,7 @@ def test_unbuilt(build_command, first_app_unbuilt, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -155,7 +163,7 @@ def test_update_app(build_command, first_app, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -213,7 +221,7 @@ def test_update_app_requirements(build_command, first_app, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -271,7 +279,7 @@ def test_update_app_resources(build_command, first_app, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -329,7 +337,7 @@ def test_update_non_existent(build_command, first_app_config, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -384,7 +392,7 @@ def test_update_unbuilt(build_command, first_app_unbuilt, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -442,7 +450,7 @@ def test_build_test(build_command, first_app, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -501,7 +509,7 @@ def test_build_test_no_update(build_command, first_app, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -540,7 +548,7 @@ def test_build_test_update_dependencies(build_command, first_app, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -599,7 +607,7 @@ def test_build_test_update_resources(build_command, first_app, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -716,7 +724,7 @@ def test_test_app_non_existent(build_command, first_app_config, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
@@ -772,7 +780,7 @@ def test_test_app_unbuilt(build_command, first_app_unbuilt, second_app): | |
build_command(**options) | ||
|
||
# The right sequence of things will be done | ||
assert build_command.actions == [ | ||
assert _clean_relock(build_command.actions) == [ | ||
# Host OS is verified | ||
("verify-host",), | ||
# Tools are verified | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -118,7 +118,7 @@ def generate_app_template(self, app): | |
def install_app_support_package(self, app): | ||
self.actions.append(("support", app.app_name)) | ||
|
||
def install_app_requirements(self, app, test_mode): | ||
def install_app_requirements(self, app, test_mode, relock=False): | ||
self.actions.append(("requirements", app.app_name, test_mode)) | ||
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 should also be tracking the provided argument in the list of actions. |
||
|
||
def install_app_code(self, app, test_mode): | ||
|
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.
This is... certainly a formatting choice. Is there a reason for the free verse style here? :-)
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.
[Conversation about general requirements file support moved to #1275]