Beispiel #1
0
def test_publish_can_publish_to_given_repository(
    fixture_dir, mocker, config, fixture_name
):
    uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
    uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")

    config.merge(
        {
            "repositories": {"foo": {"url": "http://foo.bar"}},
            "http-basic": {"foo": {"username": "******", "password": "******"}},
        }
    )

    mocker.patch("poetry.factory.Factory.create_config", return_value=config)
    poetry = Factory().create_poetry(fixture_dir(fixture_name))

    io = BufferedIO()
    publisher = Publisher(poetry, io)

    publisher.publish("foo", None, None)

    assert [("foo", "bar")] == uploader_auth.call_args
    assert [
        ("http://foo.bar",),
        {"cert": None, "client_cert": None, "dry_run": False},
    ] == uploader_upload.call_args
    assert "Publishing my-package (1.2.3) to foo" in io.fetch_output()
def test_render_better_error_message():
    io = BufferedIO()

    try:
        raise Exception("Failed")
    except Exception as e:
        trace = ExceptionTrace(e)

    trace.render(io)

    expected = """\

  Exception

  Failed

  at {}:19 in test_render_better_error_message
       15│ def test_render_better_error_message():
       16│     io = BufferedIO()
       17│ 
       18│     try:
    →  19│         raise Exception("Failed")
       20│     except Exception as e:
       21│         trace = ExceptionTrace(e)
       22│ 
       23│     trace.render(io)
""".format(trace._get_relative_file_path(__file__))
    assert expected == io.fetch_output()
Beispiel #3
0
class ApplicationTester(object):
    """
    Eases the testing of console applications.
    """
    def __init__(self, application: Application) -> None:
        self._application = application
        self._application.auto_exits(False)
        self._io = BufferedIO()
        self._status_code = 0

    @property
    def application(self) -> Application:
        return self._application

    @property
    def io(self):  # type: () -> BufferedIO
        return self._io

    @property
    def status_code(self):  # type: () -> int
        return self._status_code

    def execute(
        self,
        args: Optional[str] = "",
        inputs: Optional[str] = None,
        interactive: Optional[bool] = None,
        verbosity: Optional[Verbosity] = None,
        decorated: bool = False,
        supports_utf8: bool = True,
    ) -> int:
        """
        Executes the command
        """
        self._io.clear()

        input = StringInput(args)
        self._io.set_input(input)
        self._io.decorated(decorated)
        self._io.output.set_supports_utf8(supports_utf8)
        self._io.error_output.set_supports_utf8(supports_utf8)

        if inputs is not None:
            self._io.input.set_stream(StringIO(inputs))

        if interactive is not None:
            self._io.interactive(interactive)

        if verbosity is not None:
            self._io.set_verbosity(verbosity)

        self._status_code = self._application.run(
            self._io.input,
            self._io.output,
            self._io.error_output,
        )

        return self._status_code
def test_render_debug_better_error_message_recursion_error():
    io = BufferedIO()
    io.set_verbosity(Verbosity.DEBUG)

    try:
        recursion_error()
    except RecursionError as e:
        trace = ExceptionTrace(e)

    trace.render(io)

    expected = r"""^
  Stack trace:

  \d+  {}:99 in test_render_debug_better_error_message_recursion_error
         97\│ 
         98\│     try:
      →  99\│         recursion_error\(\)
        100\│     except RecursionError as e:
        101\│         trace = ExceptionTrace\(e\)

  ...  Previous frame repeated \d+ times

  \s*\d+  {}:91 in recursion_error
         89\│ 
         90\│ def recursion_error\(\):
      →  91\│     recursion_error\(\)
         92\│ 
         93\│ 

  RecursionError

  maximum recursion depth exceeded

  at {}:91 in recursion_error
       87\│     assert re.match\(expected, io.fetch_output\(\)\) is not None
       88\│ 
       89\│ 
       90\│ def recursion_error\(\):
    →  91\│     recursion_error\(\)
       92\│ 
       93\│ 
       94\│ def test_render_debug_better_error_message_recursion_error\(\):
       95\│     io = BufferedIO\(\)
""".format(
        re.escape(trace._get_relative_file_path(__file__)),
        re.escape(trace._get_relative_file_path(__file__)),
        re.escape(trace._get_relative_file_path(__file__)),
    )

    assert re.match(expected, io.fetch_output()) is not None
def test_render_falls_back_on_ascii_symbols():
    from crashtest.contracts.base_solution import BaseSolution
    from crashtest.contracts.provides_solution import ProvidesSolution
    from crashtest.solution_providers.solution_provider_repository import (
        SolutionProviderRepository, )

    class CustomError(ProvidesSolution, Exception):
        @property
        def solution(self):
            solution = BaseSolution("Solution Title.", "Solution Description")
            solution.documentation_links.append("https://example.com")
            solution.documentation_links.append("https://example2.com")

            return solution

    io = BufferedIO(supports_utf8=False)

    def call():
        raise CustomError("Error with solution")

    with pytest.raises(CustomError) as e:
        call()

    trace = ExceptionTrace(
        e.value, solution_provider_repository=SolutionProviderRepository())

    trace.render(io)

    expected = """
  CustomError

  Error with solution

  at {}:411 in call
      407| 
      408|     io = BufferedIO(supports_utf8=False)
      409| 
      410|     def call():
    > 411|         raise CustomError("Error with solution")
      412| 
      413|     with pytest.raises(CustomError) as e:
      414|         call()
      415| 

  * Solution Title: Solution Description
    https://example.com,
    https://example2.com
""".format(trace._get_relative_file_path(__file__), )

    assert expected == io.fetch_output()
def test_render_supports_solutions():
    from crashtest.contracts.base_solution import BaseSolution
    from crashtest.contracts.provides_solution import ProvidesSolution
    from crashtest.solution_providers.solution_provider_repository import (
        SolutionProviderRepository, )

    class CustomError(ProvidesSolution, Exception):
        @property
        def solution(self):
            solution = BaseSolution("Solution Title.", "Solution Description")
            solution.documentation_links.append("https://example.com")
            solution.documentation_links.append("https://example2.com")

            return solution

    io = BufferedIO()

    def call():
        raise CustomError("Error with solution")

    with pytest.raises(CustomError) as e:
        call()

    trace = ExceptionTrace(
        e.value, solution_provider_repository=SolutionProviderRepository())

    trace.render(io)

    expected = """
  CustomError

  Error with solution

  at {}:355 in call
      351│ 
      352│     io = BufferedIO()
      353│ 
      354│     def call():
    → 355│         raise CustomError("Error with solution")
      356│ 
      357│     with pytest.raises(CustomError) as e:
      358│         call()
      359│ 

  • Solution Title: Solution Description
    https://example.com,
    https://example2.com
""".format(trace._get_relative_file_path(__file__), )

    assert expected == io.fetch_output()
def test_render_can_ignore_given_files():
    import os

    from .helpers import outer

    io = BufferedIO()
    io.set_verbosity(Verbosity.VERBOSE)

    def call():
        def run():
            outer()

        run()

    with pytest.raises(Exception) as e:
        call()

    trace = ExceptionTrace(e.value)
    helpers_file = os.path.join(os.path.dirname(__file__), "helpers.py")
    trace.ignore_files_in("^{}$".format(re.escape(helpers_file)))

    trace.render(io)

    expected = """
  Stack trace:

  2  {}:224 in test_render_can_ignore_given_files
       call()

  1  {}:221 in call
       run()

  Exception

  Foo

  at {}:3 in inner
        1│ def outer():
        2│     def inner():
    →   3│         raise Exception("Foo")
        4│ 
        5│     inner()
        6│ 
""".format(
        trace._get_relative_file_path(__file__),
        trace._get_relative_file_path(__file__),
        trace._get_relative_file_path(helpers_file),
    )

    assert expected == io.fetch_output()
def test_render_debug_better_error_message_recursion_error_with_multiple_duplicated_frames(
):
    io = BufferedIO()
    io.set_verbosity(Verbosity.VERBOSE)

    with pytest.raises(RecursionError) as e:
        first()

    trace = ExceptionTrace(e.value)

    trace.render(io)

    expected = r"...  Previous 2 frames repeated \d+ times"

    assert re.search(expected, io.fetch_output()) is not None
Beispiel #9
0
def test_execute_works_with_no_ansi_output(
    mocker: MockerFixture,
    config: Config,
    pool: Pool,
    io_not_decorated: BufferedIO,
    tmp_dir: str,
    mock_file_downloads: None,
    env: MockEnv,
):
    config.merge({"cache-dir": tmp_dir})

    executor = Executor(env, pool, config, io_not_decorated)

    install_output = (
        "some string that does not contain a keyb0ard !nterrupt or cance11ed by u$er"
    )
    mocker.patch.object(env, "_run", return_value=install_output)
    return_code = executor.execute([
        Install(Package("pytest", "3.5.2")),
    ])
    env._run.assert_called_once()

    expected = """
Package operations: 1 install, 0 updates, 0 removals

  • Installing pytest (3.5.2)
"""
    expected = set(expected.splitlines())
    output = set(io_not_decorated.fetch_output().splitlines())
    assert output == expected
    assert return_code == 0
def test_it_provides_the_correct_solution():
    from poetry.mixology.solutions.solutions import PythonRequirementSolution

    incompatibility = Incompatibility(
        [Term(Dependency("foo", "^1.0"), True)], PythonCause("^3.5", ">=3.6")
    )
    exception = SolverProblemError(SolveFailure(incompatibility))
    solution = PythonRequirementSolution(exception)

    title = "Check your dependencies Python requirement."
    description = """\
The Python requirement can be specified via the `python` or `markers` properties

For foo, a possible solution would be to set the `python` property to ">=3.6,<4.0"\
"""
    links = [
        "https://python-poetry.org/docs/dependency-specification/#python-restricted-dependencies",
        "https://python-poetry.org/docs/dependency-specification/#using-environment-markers",
    ]

    assert title == solution.solution_title
    assert (
        description == BufferedIO().remove_format(solution.solution_description).strip()
    )
    assert links == solution.documentation_links
Beispiel #11
0
def test_execute_works_with_ansi_output(
    mocker: "MockerFixture",
    config: "Config",
    pool: Pool,
    io_decorated: BufferedIO,
    tmp_dir: str,
    mock_file_downloads: None,
    env: MockEnv,
):
    config.merge({"cache-dir": tmp_dir})

    executor = Executor(env, pool, config, io_decorated)

    install_output = (
        "some string that does not contain a keyb0ard !nterrupt or cance11ed by u$er"
    )
    mocker.patch.object(env, "_run", return_value=install_output)
    return_code = executor.execute([
        Install(Package("pytest", "3.5.2")),
    ])
    env._run.assert_called_once()

    expected = [
        "\x1b[39;1mPackage operations\x1b[39;22m: \x1b[34m1\x1b[39m install, \x1b[34m0\x1b[39m updates, \x1b[34m0\x1b[39m removals",
        "\x1b[34;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[39;1m3.5.2\x1b[39;22m\x1b[39m)\x1b[39m: \x1b[34mPending...\x1b[39m",
        "\x1b[34;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[39;1m3.5.2\x1b[39;22m\x1b[39m)\x1b[39m: \x1b[34mDownloading...\x1b[39m",
        "\x1b[34;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[39;1m3.5.2\x1b[39;22m\x1b[39m)\x1b[39m: \x1b[34mInstalling...\x1b[39m",
        "\x1b[32;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[32m3.5.2\x1b[39m\x1b[39m)\x1b[39m",  # finished
    ]
    output = io_decorated.fetch_output()
    # hint: use print(repr(output)) if you need to debug this

    for line in expected:
        assert line in output
    assert return_code == 0
Beispiel #12
0
def test_execute_should_gracefully_handle_io_error(config: Config, pool: Pool,
                                                   mocker: MockerFixture,
                                                   io: BufferedIO,
                                                   env: MockEnv):
    executor = Executor(env, pool, config, io)
    executor.verbose()

    original_write_line = executor._io.write_line

    def write_line(string: str, **kwargs: Any) -> None:
        # Simulate UnicodeEncodeError
        string.encode("ascii")
        original_write_line(string, **kwargs)

    mocker.patch.object(io, "write_line", side_effect=write_line)

    assert executor.execute([Install(Package("clikit", "0.2.3"))]) == 1

    expected = r"""
Package operations: 1 install, 0 updates, 0 removals


\s*Unicode\w+Error
"""

    assert re.match(expected, io.fetch_output())
Beispiel #13
0
def io():
    io = BufferedIO()
    io.output.formatter.set_style("c1_dark", Style("cyan", options=["dark"]))
    io.output.formatter.set_style("c2_dark", Style("default", options=["bold", "dark"]))
    io.output.formatter.set_style("success_dark", Style("green", options=["dark"]))
    io.output.formatter.set_style("warning", Style("yellow"))

    return io
def test_load_plugins_with_plugins_disabled(
    no_plugin_manager: PluginManager,
    poetry: Poetry,
    io: BufferedIO,
    with_my_plugin: None,
):
    no_plugin_manager.load_plugins()

    assert poetry.package.version.text == "1.2.3"
    assert io.fetch_output() == ""
def test_render_debug_better_error_message():
    io = BufferedIO()
    io.set_verbosity(Verbosity.DEBUG)

    try:
        fail()
    except Exception as e:  # Exception
        trace = ExceptionTrace(e)

    trace.render(io)

    expected = r"""^
  Stack trace:

  1  {}:52 in test_render_debug_better_error_message
       50\│ 
       51\│     try:
    →  52\│         fail\(\)
       53\│     except Exception as e:  # Exception
       54\│         trace = ExceptionTrace\(e\)

  Exception

  Failed

  at {}:12 in fail
        8\│ from cleo.ui.exception_trace import ExceptionTrace
        9\│ 
       10\│ 
       11\│ def fail\(\):
    →  12\│     raise Exception\("Failed"\)
       13\│ 
       14\│ 
       15\│ def test_render_better_error_message\(\):
       16\│     io = BufferedIO\(\)
""".format(
        re.escape(trace._get_relative_file_path(__file__)),
        re.escape(trace._get_relative_file_path(__file__)),
    )

    assert re.match(expected, io.fetch_output()) is not None
def test_load_plugins_and_activate(
    manager_factory: ManagerFactory,
    poetry: Poetry,
    io: BufferedIO,
    with_my_plugin: None,
):
    manager = manager_factory()
    manager.load_plugins()
    manager.activate(poetry, io)

    assert poetry.package.readmes == ("README.md",)
    assert io.fetch_output() == "Setting readmes\n"
def test_load_plugins_with_plugins_disabled(
    no_plugin_manager: PluginManager,
    poetry: Poetry,
    io: BufferedIO,
    mocker: MockerFixture,
):
    mocker.patch(
        "entrypoints.get_group_all",
        return_value=[
            EntryPoint("my-plugin", "tests.plugins.test_plugin_manager", "MyPlugin")
        ],
    )

    no_plugin_manager.load_plugins()

    assert poetry.package.version.text == "1.2.3"
    assert io.fetch_output() == ""
Beispiel #18
0
def test_execute_should_show_operation_as_cancelled_on_subprocess_keyboard_interrupt(
        config: Config, pool: Pool, mocker: MockerFixture, io: BufferedIO,
        env: MockEnv):
    executor = Executor(env, pool, config, io)
    executor.verbose()

    # A return code of -2 means KeyboardInterrupt in the pip subprocess
    mocker.patch.object(executor, "_install", return_value=-2)

    assert executor.execute([Install(Package("clikit", "0.2.3"))]) == 1

    expected = """
Package operations: 1 install, 0 updates, 0 removals

  • Installing clikit (0.2.3)
  • Installing clikit (0.2.3): Cancelled
"""

    assert io.fetch_output() == expected
def test_load_plugins_and_activate(
    manager_factory: ManagerFactory,
    poetry: Poetry,
    io: BufferedIO,
    mocker: MockerFixture,
):
    manager = manager_factory()

    mocker.patch(
        "entrypoints.get_group_all",
        return_value=[
            EntryPoint("my-plugin", "tests.plugins.test_plugin_manager", "MyPlugin")
        ],
    )

    manager.load_plugins()
    manager.activate(poetry, io)

    assert poetry.package.readmes == ("README.md",)
    assert io.fetch_output() == "Setting readmes\n"
Beispiel #20
0
def test_execute_should_show_errors(
    config: "Config", pool: Pool, mocker: "MockerFixture", io: BufferedIO, env: MockEnv
):
    executor = Executor(env, pool, config, io)
    executor.verbose()

    mocker.patch.object(executor, "_install", side_effect=Exception("It failed!"))

    assert executor.execute([Install(Package("clikit", "0.2.3"))]) == 1

    expected = """
Package operations: 1 install, 0 updates, 0 removals

  • Installing clikit (0.2.3)

  Exception

  It failed!
"""

    assert expected in io.fetch_output()
Beispiel #21
0
def test_execute_shows_skipped_operations_if_verbose(config: Config,
                                                     pool: Pool,
                                                     io: BufferedIO,
                                                     config_cache_dir: Path,
                                                     env: MockEnv):
    config.merge({"cache-dir": config_cache_dir.as_posix()})

    executor = Executor(env, pool, config, io)
    executor.verbose()

    assert (executor.execute([
        Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed")
    ]) == 0)

    expected = """
Package operations: 0 installs, 0 updates, 0 removals, 1 skipped

  • Removing clikit (0.2.3): Skipped for the following reason: Not currently installed
"""
    assert io.fetch_output() == expected
    assert len(env.executed) == 0
Beispiel #22
0
def test_load_plugins_and_activate(
    manager_factory: ManagerFactory,
    poetry: Poetry,
    io: BufferedIO,
    mocker: "MockerFixture",
):
    manager = manager_factory()

    mocker.patch(
        "entrypoints.get_group_all",
        return_value=[
            EntryPoint("my-plugin", "tests.plugins.test_plugin_manager",
                       "MyPlugin")
        ],
    )

    manager.load_plugins()
    manager.activate(poetry, io)

    assert poetry.package.version.text == "9.9.9"
    assert io.fetch_output() == "Updating version\n"
Beispiel #23
0
def test_execute_executes_a_batch_of_operations(
    mocker: MockerFixture,
    config: Config,
    pool: Pool,
    io: BufferedIO,
    tmp_dir: str,
    mock_file_downloads: None,
    env: MockEnv,
):
    pip_install = mocker.patch("poetry.installation.executor.pip_install")

    config.merge({"cache-dir": tmp_dir})

    executor = Executor(env, pool, config, io)

    file_package = Package(
        "demo",
        "0.1.0",
        source_type="file",
        source_url=Path(__file__).parent.parent.joinpath(
            "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl").resolve(
            ).as_posix(),
    )

    directory_package = Package(
        "simple-project",
        "1.2.3",
        source_type="directory",
        source_url=Path(__file__).parent.parent.joinpath(
            "fixtures/simple_project").resolve().as_posix(),
    )

    git_package = Package(
        "demo",
        "0.1.0",
        source_type="git",
        source_reference="master",
        source_url="https://github.com/demo/demo.git",
        develop=True,
    )

    return_code = executor.execute([
        Install(Package("pytest", "3.5.2")),
        Uninstall(Package("attrs", "17.4.0")),
        Update(Package("requests", "2.18.3"), Package("requests", "2.18.4")),
        Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed"),
        Install(file_package),
        Install(directory_package),
        Install(git_package),
    ])

    expected = f"""
Package operations: 4 installs, 1 update, 1 removal

  • Installing pytest (3.5.2)
  • Removing attrs (17.4.0)
  • Updating requests (2.18.3 -> 2.18.4)
  • Installing demo (0.1.0 {file_package.source_url})
  • Installing simple-project (1.2.3 {directory_package.source_url})
  • Installing demo (0.1.0 master)
"""

    expected = set(expected.splitlines())
    output = set(io.fetch_output().splitlines())
    assert output == expected
    assert len(env.executed) == 1
    assert return_code == 0
    assert pip_install.call_count == 5
    assert pip_install.call_args.kwargs.get("upgrade", False)
    assert pip_install.call_args.kwargs.get("editable", False)
 def activate(self, poetry: Poetry, io: BufferedIO) -> None:
     io.write_line("Updating version")
     poetry.package.version = "9.9.9"
 def activate(self, poetry: Poetry, io: BufferedIO) -> None:
     io.write_line("Setting readmes")
     poetry.package.readmes = ("README.md",)
Beispiel #26
0
def ansi_io():
    input_ = StringInput("")
    input_.set_stream(StringIO())

    return BufferedIO(input_, decorated=True)
Beispiel #27
0
 def __init__(self, application: Application) -> None:
     self._application = application
     self._application.auto_exits(False)
     self._io = BufferedIO()
     self._status_code = 0
Beispiel #28
0
def io_decorated():
    io = BufferedIO(decorated=True)
    io.output.formatter.set_style("c1", Style("cyan"))
    io.output.formatter.set_style("success", Style("green"))

    return io
Beispiel #29
0
def io_not_decorated():
    io = BufferedIO(decorated=False)

    return io
def io() -> BufferedIO:
    return BufferedIO()