|
19 | 19 | from os import chdir, getcwd
|
20 | 20 | from os.path import abspath, dirname, join, sep
|
21 | 21 | from pathlib import Path
|
22 |
| -from shutil import rmtree |
| 22 | +from shutil import copytree, rmtree |
23 | 23 |
|
24 | 24 | import platformdirs
|
25 | 25 | import pytest
|
|
59 | 59 |
|
60 | 60 |
|
61 | 61 | @contextmanager
|
62 |
| -def fake_home() -> Iterator: |
| 62 | +def fake_home() -> Iterator[str]: |
63 | 63 | folder = tempfile.mkdtemp("fake-home")
|
64 | 64 | old_home = os.environ.get(HOME)
|
65 | 65 | try:
|
66 | 66 | os.environ[HOME] = folder
|
67 |
| - yield |
| 67 | + yield folder |
68 | 68 | finally:
|
69 | 69 | os.environ.pop("PYLINTRC", "")
|
70 | 70 | if old_home is None:
|
@@ -524,6 +524,188 @@ def test_load_plugin_command_line() -> None:
|
524 | 524 | sys.path.remove(dummy_plugin_path)
|
525 | 525 |
|
526 | 526 |
|
| 527 | +@pytest.mark.usefixtures("pop_pylintrc") |
| 528 | +def test_load_plugin_path_manipulation_case_6() -> None: |
| 529 | + """Case 6 refers to GitHub issue #7264. |
| 530 | +
|
| 531 | + This is where we supply a plugin we want to load on both the CLI and |
| 532 | + config file, but that plugin is only loadable after the ``init-hook`` in |
| 533 | + the config file has run. This is not supported, and was previously a silent |
| 534 | + failure. This test ensures a ``bad-plugin-value`` message is emitted. |
| 535 | + """ |
| 536 | + dummy_plugin_path = abspath(join(REGRTEST_DATA_DIR, "dummy_plugin")) |
| 537 | + with fake_home() as home_path: |
| 538 | + # construct a basic rc file that just modifies the path |
| 539 | + pylintrc_file = join(home_path, "pylintrc") |
| 540 | + with open(pylintrc_file, "w", encoding="utf8") as out: |
| 541 | + out.writelines( |
| 542 | + [ |
| 543 | + "[MASTER]\n", |
| 544 | + f"init-hook=\"import sys; sys.path.append(r'{home_path}')\"\n", |
| 545 | + "load-plugins=copy_dummy\n", |
| 546 | + ] |
| 547 | + ) |
| 548 | + |
| 549 | + copytree(dummy_plugin_path, join(home_path, "copy_dummy")) |
| 550 | + |
| 551 | + # To confirm we won't load this module _without_ the init hook running. |
| 552 | + assert home_path not in sys.path |
| 553 | + |
| 554 | + run = Run( |
| 555 | + [ |
| 556 | + "--rcfile", |
| 557 | + pylintrc_file, |
| 558 | + "--load-plugins", |
| 559 | + "copy_dummy", |
| 560 | + join(REGRTEST_DATA_DIR, "empty.py"), |
| 561 | + ], |
| 562 | + reporter=testutils.GenericTestReporter(), |
| 563 | + exit=False, |
| 564 | + ) |
| 565 | + assert run._rcfile == pylintrc_file |
| 566 | + assert home_path in sys.path |
| 567 | + # The module should not be loaded |
| 568 | + assert not any(ch.name == "copy_dummy" for ch in run.linter.get_checkers()) |
| 569 | + |
| 570 | + # There should be a bad-plugin-message for this module |
| 571 | + assert len(run.linter.reporter.messages) == 1 |
| 572 | + assert run.linter.reporter.messages[0] == Message( |
| 573 | + msg_id="E0013", |
| 574 | + symbol="bad-plugin-value", |
| 575 | + msg="Plugin 'copy_dummy' is impossible to load, is it installed ? ('No module named 'copy_dummy'')", |
| 576 | + confidence=interfaces.Confidence( |
| 577 | + name="UNDEFINED", |
| 578 | + description="Warning without any associated confidence level.", |
| 579 | + ), |
| 580 | + location=MessageLocationTuple( |
| 581 | + abspath="Command line or configuration file", |
| 582 | + path="Command line or configuration file", |
| 583 | + module="Command line or configuration file", |
| 584 | + obj="", |
| 585 | + line=1, |
| 586 | + column=0, |
| 587 | + end_line=None, |
| 588 | + end_column=None, |
| 589 | + ), |
| 590 | + ) |
| 591 | + |
| 592 | + # Necessary as the executed init-hook modifies sys.path |
| 593 | + sys.path.remove(home_path) |
| 594 | + |
| 595 | + |
| 596 | +@pytest.mark.usefixtures("pop_pylintrc") |
| 597 | +def test_load_plugin_path_manipulation_case_3() -> None: |
| 598 | + """Case 3 refers to GitHub issue #7264. |
| 599 | +
|
| 600 | + This is where we supply a plugin we want to load on the CLI only, |
| 601 | + but that plugin is only loadable after the ``init-hook`` in |
| 602 | + the config file has run. This is not supported, and was previously a silent |
| 603 | + failure. This test ensures a ``bad-plugin-value`` message is emitted. |
| 604 | + """ |
| 605 | + dummy_plugin_path = abspath(join(REGRTEST_DATA_DIR, "dummy_plugin")) |
| 606 | + with fake_home() as home_path: |
| 607 | + # construct a basic rc file that just modifies the path |
| 608 | + pylintrc_file = join(home_path, "pylintrc") |
| 609 | + with open(pylintrc_file, "w", encoding="utf8") as out: |
| 610 | + out.writelines( |
| 611 | + [ |
| 612 | + "[MASTER]\n", |
| 613 | + f"init-hook=\"import sys; sys.path.append(r'{home_path}')\"\n", |
| 614 | + ] |
| 615 | + ) |
| 616 | + |
| 617 | + copytree(dummy_plugin_path, join(home_path, "copy_dummy")) |
| 618 | + |
| 619 | + # To confirm we won't load this module _without_ the init hook running. |
| 620 | + assert home_path not in sys.path |
| 621 | + |
| 622 | + run = Run( |
| 623 | + [ |
| 624 | + "--rcfile", |
| 625 | + pylintrc_file, |
| 626 | + "--load-plugins", |
| 627 | + "copy_dummy", |
| 628 | + join(REGRTEST_DATA_DIR, "empty.py"), |
| 629 | + ], |
| 630 | + reporter=testutils.GenericTestReporter(), |
| 631 | + exit=False, |
| 632 | + ) |
| 633 | + assert run._rcfile == pylintrc_file |
| 634 | + assert home_path in sys.path |
| 635 | + # The module should not be loaded |
| 636 | + assert not any(ch.name == "copy_dummy" for ch in run.linter.get_checkers()) |
| 637 | + |
| 638 | + # There should be a bad-plugin-message for this module |
| 639 | + assert len(run.linter.reporter.messages) == 1 |
| 640 | + assert run.linter.reporter.messages[0] == Message( |
| 641 | + msg_id="E0013", |
| 642 | + symbol="bad-plugin-value", |
| 643 | + msg="Plugin 'copy_dummy' is impossible to load, is it installed ? ('No module named 'copy_dummy'')", |
| 644 | + confidence=interfaces.Confidence( |
| 645 | + name="UNDEFINED", |
| 646 | + description="Warning without any associated confidence level.", |
| 647 | + ), |
| 648 | + location=MessageLocationTuple( |
| 649 | + abspath="Command line or configuration file", |
| 650 | + path="Command line or configuration file", |
| 651 | + module="Command line or configuration file", |
| 652 | + obj="", |
| 653 | + line=1, |
| 654 | + column=0, |
| 655 | + end_line=None, |
| 656 | + end_column=None, |
| 657 | + ), |
| 658 | + ) |
| 659 | + |
| 660 | + # Necessary as the executed init-hook modifies sys.path |
| 661 | + sys.path.remove(home_path) |
| 662 | + |
| 663 | + |
| 664 | +def test_load_plugin_command_line_before_init_hook() -> None: |
| 665 | + """Check that the order of 'load-plugins' and 'init-hook' doesn't affect execution.""" |
| 666 | + regrtest_data_dir_abs = abspath(REGRTEST_DATA_DIR) |
| 667 | + |
| 668 | + run = Run( |
| 669 | + [ |
| 670 | + "--load-plugins", |
| 671 | + "dummy_plugin", |
| 672 | + "--init-hook", |
| 673 | + f'import sys; sys.path.append("{regrtest_data_dir_abs}")', |
| 674 | + join(REGRTEST_DATA_DIR, "empty.py"), |
| 675 | + ], |
| 676 | + exit=False, |
| 677 | + ) |
| 678 | + assert ( |
| 679 | + len([ch.name for ch in run.linter.get_checkers() if ch.name == "dummy_plugin"]) |
| 680 | + == 2 |
| 681 | + ) |
| 682 | + |
| 683 | + # Necessary as the executed init-hook modifies sys.path |
| 684 | + sys.path.remove(regrtest_data_dir_abs) |
| 685 | + |
| 686 | + |
| 687 | +def test_load_plugin_command_line_with_init_hook_command_line() -> None: |
| 688 | + regrtest_data_dir_abs = abspath(REGRTEST_DATA_DIR) |
| 689 | + |
| 690 | + run = Run( |
| 691 | + [ |
| 692 | + "--init-hook", |
| 693 | + f'import sys; sys.path.append("{regrtest_data_dir_abs}")', |
| 694 | + "--load-plugins", |
| 695 | + "dummy_plugin", |
| 696 | + join(REGRTEST_DATA_DIR, "empty.py"), |
| 697 | + ], |
| 698 | + exit=False, |
| 699 | + ) |
| 700 | + assert ( |
| 701 | + len([ch.name for ch in run.linter.get_checkers() if ch.name == "dummy_plugin"]) |
| 702 | + == 2 |
| 703 | + ) |
| 704 | + |
| 705 | + # Necessary as the executed init-hook modifies sys.path |
| 706 | + sys.path.remove(regrtest_data_dir_abs) |
| 707 | + |
| 708 | + |
527 | 709 | def test_load_plugin_config_file() -> None:
|
528 | 710 | dummy_plugin_path = join(REGRTEST_DATA_DIR, "dummy_plugin")
|
529 | 711 | sys.path.append(dummy_plugin_path)
|
|
0 commit comments