@@ -99,6 +99,21 @@ def poetry_project_target_previous_lock_latest():
9999 tempdir .cleanup ()
100100
101101
102+ @pytest .fixture
103+ def poetry_project_lock_latest ():
104+ """
105+ Initialize a Poetry project where the latest version of `TARGET` is an as-yet
106+ uninstalled dependency.
107+ """
108+ tempdir = TemporaryDirectory ()
109+ _init_poetry_project (tempdir .name , TEST_PROJECT_NAME )
110+ subprocess .run (["poetry" , "add" , "--lock" , f"{ TARGET } =={ TARGET_LATEST } " ], check = True , cwd = tempdir .name )
111+
112+ yield tempdir .name
113+
114+ tempdir .cleanup ()
115+
116+
102117def test_poetry_version_output ():
103118 """
104119 Test that `poetry --version` has the required format and parses correctly.
@@ -183,6 +198,29 @@ def test_poetry_sync_no_change(new_poetry_project):
183198 assert all (_test_poetry_no_change (new_poetry_project , init_state , command ) for command in test_cases )
184199
185200
201+ def test_poetry_update_no_change (new_poetry_project ):
202+ """
203+ Test that certain `poetry update` commands relied on by Supply-Chain Firewall
204+ not to error or modify the local installation state indeed have these properties.
205+ """
206+ test_cases = [
207+ ["poetry" , "-V" , "update" ],
208+ ["poetry" , "update" , "-V" ],
209+ ["poetry" , "--version" , "update" ],
210+ ["poetry" , "update" , "--version" ],
211+ ["poetry" , "-h" , "update" ],
212+ ["poetry" , "update" , "-h" ],
213+ ["poetry" , "--help" , "update" ],
214+ ["poetry" , "update" , "--help" ],
215+ ["poetry" , "--dry-run" , "update" ],
216+ ["poetry" , "update" , "--dry-run" ],
217+ ]
218+
219+ init_state = poetry_show (new_poetry_project )
220+
221+ assert all (_test_poetry_no_change (new_poetry_project , init_state , command ) for command in test_cases )
222+
223+
186224def _test_poetry_no_change (project , init_state , command ) -> bool :
187225 """
188226 Tests that a given Poetry command does not encounter any errors and does not
@@ -273,6 +311,35 @@ def test_poetry_sync_error_no_change(new_poetry_project):
273311 assert all (_test_poetry_error_no_change (new_poetry_project , init_state , command ) for command in test_cases )
274312
275313
314+ def test_poetry_update_error_no_change (new_poetry_project ):
315+ """
316+ Tests that certain `poetry update` commands encounter an error and do not
317+ modify the local installation state when run in the context of a given project.
318+ """
319+ test_cases = [
320+ ["poetry" , "update" , "--nonexistent-option" ],
321+ ["poetry" , "update" , "--nonexistent-option" , TARGET ],
322+ ["poetry" , "update" , "--without" ],
323+ ["poetry" , "update" , TARGET , "--without" ],
324+ ["poetry" , "update" , "--with" ],
325+ ["poetry" , "update" , TARGET , "--with" ],
326+ ["poetry" , "update" , "--only" ],
327+ ["poetry" , "update" , TARGET , "--only" ],
328+ ["poetry" , "update" , "-P" ],
329+ ["poetry" , "update" , TARGET , "-P" ],
330+ ["poetry" , "update" , "--project" ],
331+ ["poetry" , "update" , TARGET , "--project" ],
332+ ["poetry" , "update" , "-C" ],
333+ ["poetry" , "update" , TARGET , "-C" ],
334+ ["poetry" , "update" , "--directory" ],
335+ ["poetry" , "update" , TARGET , "--directory" ],
336+ ]
337+
338+ init_state = poetry_show (new_poetry_project )
339+
340+ assert all (_test_poetry_error_no_change (new_poetry_project , init_state , command ) for command in test_cases )
341+
342+
276343def _test_poetry_error_no_change (project , init_state , command ) -> bool :
277344 """
278345 Tests that a given Poetry command does encounter an error and does not modify
@@ -283,7 +350,7 @@ def _test_poetry_error_no_change(project, init_state, command) -> bool:
283350 return poetry_show (project ) == init_state
284351
285352
286- def test_poetry_dry_run_output_install (new_poetry_project ):
353+ def test_poetry_dry_run_output_install (new_poetry_project , poetry_project_lock_latest ):
287354 """
288355 Tests that a dry-run of an installish Poetry command that results in a
289356 dependency installation has the expected format.
@@ -293,16 +360,17 @@ def is_install_line(target: str, version: str, line: str) -> bool:
293360 return match is not None and match .group (1 ) == target and match .group (2 ) == version and "Skipped" not in line
294361
295362 test_cases = [
296- (["poetry" , "add" , "--dry-run" , TARGET ], TARGET , TARGET_LATEST , None ),
297- (["poetry" , "install" , "--dry-run" ], TEST_PROJECT_NAME , "0.1.0" , None ),
298- (["poetry" , "sync" , "--dry-run" ], TEST_PROJECT_NAME , "0.1.0" , POETRY_V2 ),
363+ (new_poetry_project , ["poetry" , "add" , "--dry-run" , TARGET ], TARGET , TARGET_LATEST , None ),
364+ (new_poetry_project , ["poetry" , "install" , "--dry-run" ], TEST_PROJECT_NAME , "0.1.0" , None ),
365+ (new_poetry_project , ["poetry" , "sync" , "--dry-run" ], TEST_PROJECT_NAME , "0.1.0" , POETRY_V2 ),
366+ (poetry_project_lock_latest , ["poetry" , "update" , "--dry-run" ], TARGET , TARGET_LATEST , None )
299367 ]
300368
301- for command , target , version , min_poetry_version in test_cases :
369+ for poetry_project , command , target , version , min_poetry_version in test_cases :
302370 if min_poetry_version and poetry_version () < min_poetry_version :
303371 continue
304372
305- dry_run = subprocess .run (command , check = True , cwd = new_poetry_project , text = True , capture_output = True )
373+ dry_run = subprocess .run (command , check = True , cwd = poetry_project , text = True , capture_output = True )
306374 assert any (is_install_line (target , version , line ) for line in dry_run .stdout .split ('\n ' ))
307375
308376
@@ -322,6 +390,7 @@ def is_update_line(target: str, line: str) -> bool:
322390 (poetry_project_target_previous , ["poetry" , "add" , "--dry-run" , f"{ TARGET } =={ TARGET_LATEST } " ], None ),
323391 (poetry_project_target_previous_lock_latest , ["poetry" , "install" , "--dry-run" ], None ),
324392 (poetry_project_target_previous_lock_latest , ["poetry" , "sync" , "--dry-run" ], POETRY_V2 ),
393+ (poetry_project_target_previous_lock_latest , ["poetry" , "update" , "--dry-run" ], None ),
325394 ]
326395
327396 for poetry_project , command , min_poetry_version in test_cases :
@@ -348,6 +417,7 @@ def is_downgrade_line(target: str, line: str) -> bool:
348417 (poetry_project_target_latest , ["poetry" , "add" , "--dry-run" , f"{ TARGET } =={ TARGET_PREVIOUS } " ], None ),
349418 (poetry_project_target_latest_lock_previous , ["poetry" , "install" , "--dry-run" ], None ),
350419 (poetry_project_target_latest_lock_previous , ["poetry" , "sync" , "--dry-run" ], POETRY_V2 ),
420+ (poetry_project_target_latest_lock_previous , ["poetry" , "update" , "--dry-run" ], None ),
351421 ]
352422
353423 for poetry_project , command , min_poetry_version in test_cases :
0 commit comments