|
9 | 9 |
|
10 | 10 | import pytest
|
11 | 11 |
|
| 12 | +import pip._internal.exceptions |
12 | 13 | import pip._internal.req.req_file # this will be monkeypatched
|
13 | 14 | from pip._internal.exceptions import InstallationError, RequirementsFileParseError
|
14 | 15 | from pip._internal.index.package_finder import PackageFinder
|
@@ -358,21 +359,54 @@ def test_recursive_requirements_file(
|
358 | 359 | # When the passed requirements file recursively references itself
|
359 | 360 | with pytest.raises(
|
360 | 361 | RecursionError,
|
361 |
| - match=f"{req_files[0]} recursively references itself" |
362 |
| - f" in {req_files[req_file_count - 1]}", |
| 362 | + match=( |
| 363 | + f"{req_files[0]} recursively references itself" |
| 364 | + f" in {req_files[req_file_count - 1]}" |
| 365 | + ), |
363 | 366 | ):
|
364 | 367 | list(parse_requirements(filename=str(req_files[0]), session=session))
|
365 | 368 |
|
366 | 369 | # When one of other the requirements file recursively references itself
|
367 | 370 | req_files[req_file_count - 1].write_text(f"-r {req_files[req_file_count - 2]}")
|
368 | 371 | with pytest.raises(
|
369 | 372 | RecursionError,
|
370 |
| - match=f"{req_files[req_file_count - 2]} recursively references itself " |
371 |
| - f"in {req_files[req_file_count - 1]} and again in" |
372 |
| - f" {req_files[req_file_count - 3]}", |
| 373 | + match=( |
| 374 | + f"{req_files[req_file_count - 2]} recursively references itself " |
| 375 | + f"in {req_files[req_file_count - 1]} and again in" |
| 376 | + f" {req_files[req_file_count - 3]}" |
| 377 | + ), |
373 | 378 | ):
|
374 | 379 | list(parse_requirements(filename=str(req_files[0]), session=session))
|
375 | 380 |
|
| 381 | + def test_recursive_relative_requirements_file( |
| 382 | + self, monkeypatch: pytest.MonkeyPatch, tmpdir: Path, session: PipSession |
| 383 | + ) -> None: |
| 384 | + root_req_file = tmpdir / "root.txt" |
| 385 | + (tmpdir / "nest" / "nest").mkdir(parents=True) |
| 386 | + level_1_req_file = tmpdir / "nest" / "level_1.txt" |
| 387 | + level_2_req_file = tmpdir / "nest" / "nest" / "level_2.txt" |
| 388 | + |
| 389 | + root_req_file.write_text("-r nest/level_1.txt") |
| 390 | + level_1_req_file.write_text("-r nest/level_2.txt") |
| 391 | + level_2_req_file.write_text("-r ../../root.txt") |
| 392 | + |
| 393 | + with pytest.raises( |
| 394 | + RecursionError, |
| 395 | + match=( |
| 396 | + f"{root_req_file} recursively references itself in {level_2_req_file}" |
| 397 | + ), |
| 398 | + ): |
| 399 | + list(parse_requirements(filename=str(root_req_file), session=session)) |
| 400 | + |
| 401 | + # If we don't use absolute path, it keeps on chaining the filename resulting in |
| 402 | + # a huge filename, since a != a/b/c/../../ |
| 403 | + monkeypatch.setattr(os.path, "abspath", lambda x: x) |
| 404 | + with pytest.raises( |
| 405 | + pip._internal.exceptions.InstallationError, |
| 406 | + match=r"Could not open requirements file: \[Errno 36\] File name too long:", |
| 407 | + ): |
| 408 | + list(parse_requirements(filename=str(root_req_file), session=session)) |
| 409 | + |
376 | 410 | def test_options_on_a_requirement_line(self, line_processor: LineProcessor) -> None:
|
377 | 411 | line = (
|
378 | 412 | 'SomeProject --global-option="yo3" --global-option "yo4" '
|
|
0 commit comments