def test_list_displays_set_get_setting(tester: CommandTester, config: Config, config_cache_dir: Path): tester.execute("virtualenvs.create false") tester.execute("--list") cache_dir = json.dumps(str(config_cache_dir)) venv_path = json.dumps(os.path.join("{cache-dir}", "virtualenvs")) expected = f"""cache-dir = {cache_dir} experimental.new-installer = true experimental.system-git-client = false installer.max-workers = null installer.no-binary = null installer.parallel = true virtualenvs.create = false virtualenvs.in-project = null virtualenvs.options.always-copy = false virtualenvs.options.no-pip = false virtualenvs.options.no-setuptools = false virtualenvs.options.system-site-packages = false virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'} virtualenvs.prefer-active-python = false """ assert config.set_config_source.call_count == 0 assert tester.io.fetch_output() == expected
def test_display_single_setting(tester: CommandTester, config: Config): tester.execute("virtualenvs.create") expected = """true """ assert tester.io.fetch_output() == expected
def test_remove_installed_package(app: PoetryTestApplication, tester: CommandTester, env: MockEnv): tester.execute("poetry-plugin") expected = """\ Updating dependencies Resolving dependencies... Writing lock file Package operations: 0 installs, 0 updates, 1 removal • Removing poetry-plugin (1.2.3) """ assert tester.io.fetch_output() == expected remove_command: RemoveCommand = app.find("remove") assert remove_command.poetry.file.parent == env.path assert remove_command.poetry.locker.lock.parent == env.path assert remove_command.poetry.locker.lock.exists() assert not remove_command.installer.executor._dry_run content = remove_command.poetry.file.read()["tool"]["poetry"] assert "poetry-plugin" not in content["dependencies"]
def test_source_add_error_default_and_secondary(tester: CommandTester): tester.execute("--default --secondary error https://error.com") assert ( tester.io.fetch_error().strip() == "Cannot configure a source as both default and secondary." ) assert tester.status_code == 1
def test_group_options_are_passed_to_the_installer( options: str, groups: set[str], with_root: bool, tester: CommandTester, mocker: MockerFixture, ): """ Group options are passed properly to the installer. """ mocker.patch.object(tester.command.installer, "run", return_value=0) editable_builder_mock = mocker.patch( "poetry.masonry.builders.editable.EditableBuilder", side_effect=ModuleOrPackageNotFound(), ) if not with_root: options = f"--no-root {options}" tester.execute(options) package_groups = set(tester.command.poetry.package._dependency_groups.keys()) installer_groups = set(tester.command.installer._groups) assert installer_groups <= package_groups assert set(installer_groups) == groups if with_root: assert editable_builder_mock.call_count == 1 assert editable_builder_mock.call_args_list[0][0][0] == tester.command.poetry else: assert editable_builder_mock.call_count == 0
def test_self_update_does_not_update_non_recommended_installation( tester: CommandTester, http: type[httpretty.httpretty], mocker: MockerFixture, environ: None, tmp_venv: VirtualEnv, ): mocker.patch.object(EnvManager, "get_system_env", return_value=tmp_venv) command = tester.command new_version = Version.parse(__version__).next_minor().text old_poetry = Package("poetry", __version__) old_poetry.add_dependency(Factory.create_dependency("cleo", "^0.8.2")) new_poetry = Package("poetry", new_version) new_poetry.add_dependency(Factory.create_dependency("cleo", "^1.0.0")) installed_repository = Repository() installed_repository.add_package(old_poetry) installed_repository.add_package(Package("cleo", "0.8.2")) repository = Repository() repository.add_package(new_poetry) repository.add_package(Package("cleo", "1.0.0")) pool = Pool() pool.add_repository(repository) command._pool = pool with pytest.raises(PoetrySimpleConsoleException): tester.execute()
def test_export_includes_extras_by_flag(tester: CommandTester, do_lock: None): tester.execute("--format requirements.txt --extras feature_bar") expected = """\ bar==1.1.0 foo==1.0.0 """ assert tester.io.fetch_output() == expected
def test_add_with_git_constraint_with_extras( tester: CommandTester, repo: TestRepository, ): repo.add_package(Package("pendulum", "2.0.5")) repo.add_package(Package("tomlkit", "0.7.0")) tester.execute("git+https://github.com/demo/poetry-plugin.git[foo]") expected = """ Updating dependencies Resolving dependencies... Writing lock file Package operations: 3 installs, 0 updates, 0 removals • Installing pendulum (2.0.5) • Installing tomlkit (0.7.0) • Installing poetry-plugin (0.1.2 9cf87a2) """ assert_plugin_add_result( tester, expected, { "git": "https://github.com/demo/poetry-plugin.git", "extras": ["foo"], }, )
def test_python_option(tester: CommandTester): inputs = [ "my-package", # Package name "1.2.3", # Version "This is a description", # Description "n", # Author "MIT", # License "n", # Interactive packages "n", # Interactive dev packages "\n", # Generate ] tester.execute("--python '~2.7 || ^3.6'", inputs="\n".join(inputs)) expected = """\ [tool.poetry] name = "my-package" version = "1.2.3" description = "This is a description" authors = ["Your Name <*****@*****.**>"] license = "MIT" readme = "README.md" packages = [{include = "my_package"}] [tool.poetry.dependencies] python = "~2.7 || ^3.6" """ assert expected in tester.io.fetch_output()
def test_predefined_dependency(tester: CommandTester, repo: "TestRepository"): repo.add_package(get_package("pendulum", "2.0.0")) inputs = [ "my-package", # Package name "1.2.3", # Version "This is a description", # Description "n", # Author "MIT", # License "~2.7 || ^3.6", # Python "n", # Interactive packages "n", # Interactive dev packages "\n", # Generate ] tester.execute("--dependency pendulum", inputs="\n".join(inputs)) expected = """\ [tool.poetry] name = "my-package" version = "1.2.3" description = "This is a description" authors = ["Your Name <*****@*****.**>"] license = "MIT" readme = "README.md" packages = [{include = "my_package"}] [tool.poetry.dependencies] python = "~2.7 || ^3.6" pendulum = "^2.0.0" """ assert expected in tester.io.fetch_output()
def test_get_prefers_explicitly_activated_non_existing_virtualenvs_over_env_var( mocker: MockerFixture, tester: CommandTester, current_python: tuple[int, int, int], venv_cache: Path, venv_name: str, venvs_in_cache_config: None, ): os.environ["VIRTUAL_ENV"] = "/environment/prefix" python_minor = ".".join(str(v) for v in current_python[:2]) venv_dir = venv_cache / f"{venv_name}-py{python_minor}" mocker.patch( "poetry.utils.env.EnvManager._env", new_callable=mocker.PropertyMock, return_value=MockEnv( path=Path("/environment/prefix"), base=Path("/base/prefix"), version_info=current_python, is_venv=True, ), ) mocker.patch("poetry.utils.env.EnvManager.build_venv", side_effect=build_venv) tester.execute(python_minor) expected = f"""\ Creating virtualenv {venv_dir.name} in {venv_dir.parent} Using virtualenv: {venv_dir} """ assert tester.io.fetch_output() == expected
def test_empty_license(tester: CommandTester): inputs = [ "my-package", # Package name "1.2.3", # Version "", # Description "n", # Author "", # License "", # Python "n", # Interactive packages "n", # Interactive dev packages "\n", # Generate ] tester.execute(inputs="\n".join(inputs)) python = ".".join(str(c) for c in sys.version_info[:2]) expected = f"""\ [tool.poetry] name = "my-package" version = "1.2.3" description = "" authors = ["Your Name <*****@*****.**>"] readme = "README.md" packages = [{{include = "my_package"}}] [tool.poetry.dependencies] python = "^{python}" """ assert expected in tester.io.fetch_output()
def test_get_prefers_explicitly_activated_virtualenvs_over_env_var( tester: CommandTester, current_python: tuple[int, int, int], venv_cache: Path, venv_name: str, venvs_in_cache_config: None, ): os.environ["VIRTUAL_ENV"] = "/environment/prefix" python_minor = ".".join(str(v) for v in current_python[:2]) python_patch = ".".join(str(v) for v in current_python[:3]) venv_dir = venv_cache / f"{venv_name}-py{python_minor}" venv_dir.mkdir(parents=True, exist_ok=True) envs_file = TOMLFile(venv_cache / "envs.toml") doc = tomlkit.document() doc[venv_name] = {"minor": python_minor, "patch": python_patch} envs_file.write(doc) tester.execute(python_minor) expected = f"""\ Using virtualenv: {venv_dir} """ assert tester.io.fetch_output() == expected
def test_explicit_multiple_argument(): command = MySecondCommand() tester = CommandTester(command) tester.execute("1 2 3") assert "1,2,3\n" == tester.io.fetch_output()
def test_dry_run(tester: CommandTester): old_pyproject = tester.command.poetry.file.path.read_text() tester.execute("--dry-run major") new_pyproject = tester.command.poetry.file.path.read_text() assert tester.io.fetch_output() == "Bumping version from 1.2.3 to 2.0.0\n" assert old_pyproject == new_pyproject
def test_export_prints_to_stdout_by_default(tester: CommandTester, do_lock: None): tester.execute("--format requirements.txt") expected = """\ foo==1.0.0 """ assert tester.io.fetch_output() == expected
def test_export_uses_requirements_txt_format_by_default( tester: CommandTester, do_lock: None): tester.execute() expected = """\ foo==1.0.0 """ assert tester.io.fetch_output() == expected
def test_deprecation_warning(tester: CommandTester, repo: TestRepository) -> None: plugin = Package("poetry-plugin", "1.2.3") repo.add_package(Package("poetry", __version__)) repo.add_package(plugin) package = ProjectPackage("poetry-instance", __version__) package.add_dependency( Dependency(plugin.name, "^1.2.3", groups=[SelfCommand.ADDITIONAL_PACKAGE_GROUP])) content = Factory.create_pyproject_from_package(package) system_pyproject_file = SelfCommand.get_default_system_pyproject_file() system_pyproject_file.write_text(content.as_string(), encoding="utf-8") dependencies = get_self_command_dependencies(locked=False) assert "poetry-plugin" in dependencies tester.execute("poetry-plugin") assert (tester.io.fetch_error() == "This command is deprecated. Use self remove command instead.\n") dependencies = get_self_command_dependencies() assert "poetry-plugin" not in dependencies assert not dependencies
def test_deprecation_warning(tester: CommandTester, repo: TestRepository) -> None: repo.add_package(Package("poetry", __version__)) repo.add_package(Package("poetry-plugin", "1.0")) tester.execute("poetry-plugin") assert (tester.io.fetch_error() == "This command is deprecated. Use self add command instead.\n")
def test_add_with_git_constraint( app: PoetryTestApplication, repo: TestRepository, tester: CommandTester, env: MockEnv, installed: Repository, ): repo.add_package(Package("pendulum", "2.0.5")) tester.execute("git+https://github.com/demo/poetry-plugin.git") expected = """\ Updating dependencies Resolving dependencies... Writing lock file Package operations: 2 installs, 0 updates, 0 removals • Installing pendulum (2.0.5) • Installing poetry-plugin (0.1.2 9cf87a2) """ assert_plugin_add_result( tester, app, env, expected, {"git": "https://github.com/demo/poetry-plugin.git"})
def test_noninteractive( app: PoetryTestApplication, mocker: "MockerFixture", poetry: "Poetry", repo: "TestRepository", tmp_path: Path, ): command = app.find("init") command._pool = poetry.pool repo.add_package(get_package("pytest", "3.6.0")) p = mocker.patch("pathlib.Path.cwd") p.return_value = tmp_path tester = CommandTester(command) args = "--name my-package --dependency pytest" tester.execute(args=args, interactive=False) expected = "Using version ^3.6.0 for pytest\n" assert tester.io.fetch_output() == expected assert tester.io.fetch_error() == "" toml_content = (tmp_path / "pyproject.toml").read_text() assert 'name = "my-package"' in toml_content assert 'pytest = "^3.6.0"' in toml_content
def test_cache_list_empty(tester: CommandTester, repository_cache_dir: Path): tester.execute() expected = """\ No caches found """ assert tester.io.fetch_error() == expected
def test_execute_namespace_command(): app = Application() app.add(FooBarCommand()) tester = CommandTester(app.find("foo bar")) assert 0 == tester.execute() assert 0 == tester.status_code assert "foo bar called\n" == tester.io.fetch_output()
def test_overwrite(): command = MyCommand() tester = CommandTester(command) tester.execute("overwrite", decorated=True) expected = "Processing...\x1b[1G\x1b[2KDone!" assert expected == tester.io.fetch_output()
def test_check_valid(tester: CommandTester): tester.execute() expected = """\ All set! """ assert tester.io.fetch_output() == expected
def test_source_add_error_pypi(tester: CommandTester): tester.execute("pypi https://test.pypi.org/simple/") assert ( tester.io.fetch_error().strip() == "Failed to validate addition of pypi: The name [pypi] is reserved for" " repositories" ) assert tester.status_code == 1
def test_source_add_secondary( tester: CommandTester, source_existing: Source, source_secondary: Source, poetry_with_source: Poetry, ): tester.execute(f"--secondary {source_secondary.name} {source_secondary.url}") assert_source_added(tester, poetry_with_source, source_existing, source_secondary)
def test_source_add_default( tester: CommandTester, source_existing: Source, source_default: Source, poetry_with_source: Poetry, ): tester.execute(f"--default {source_default.name} {source_default.url}") assert_source_added(tester, poetry_with_source, source_existing, source_default)
def test_source_add_simple( tester: CommandTester, source_existing: Source, source_one: Source, poetry_with_source: Poetry, ): tester.execute(f"{source_one.name} {source_one.url}") assert_source_added(tester, poetry_with_source, source_existing, source_one)
class TestCommandTester(TestCase): def setUp(self): self.command = Command('foo') self.command.add_argument('command') self.command.add_argument('foo') self.command.set_code(lambda input_, output_: output_.writeln('foo')) self.tester = CommandTester(self.command) self.tester.execute( [('foo', 'bar')], { 'interactive': False, 'decorated': False, 'verbosity': Output.VERBOSITY_VERBOSE }) def tearDown(self): self.command = None self.tester = None def test_execute(self): """ CommandTester.execute() behaves properly """ self.assertFalse(self.tester.get_input().is_interactive(), msg='.execute() takes an interactive option.') self.assertFalse(self.tester.get_output().is_decorated(), msg='.execute() takes a decorated option.') self.assertEqual(Output.VERBOSITY_VERBOSE, self.tester.get_output().get_verbosity(), msg='.execute() takes an interactive option.') def test_get_input(self): """ CommandTester.get_input() behaves properly """ self.assertEqual( 'bar', self.tester.get_input().get_argument('foo'), msg='.get_input() returns the current input instance.') def test_get_output(self): """ CommandTester.get_output() behaves properly """ self.tester.get_output().get_stream().seek(0) self.assertEqual( 'foo\n', self.tester.get_output().get_stream().read().decode(), msg='.get_output() returns the current output instance.') def test_get_display(self): """ CommandTester.get_display() behaves properly """ self.assertEqual( 'foo\n', self.tester.get_display(), msg='.get_display() returns the display of the last execution.')
class TestCommandTester(TestCase): def setUp(self): self.command = Command('foo') self.command.add_argument('command') self.command.add_argument('foo') self.command.set_code(lambda input_, output_: output_.writeln('foo')) self.tester = CommandTester(self.command) self.tester.execute([('foo', 'bar')], {'interactive': False, 'decorated': False, 'verbosity': Output.VERBOSITY_VERBOSE}) def tearDown(self): self.command = None self.tester = None def test_execute(self): """ CommandTester.execute() behaves properly """ self.assertFalse(self.tester.get_input().is_interactive(), msg='.execute() takes an interactive option.') self.assertFalse(self.tester.get_output().is_decorated(), msg='.execute() takes a decorated option.') self.assertEqual(Output.VERBOSITY_VERBOSE, self.tester.get_output().get_verbosity(), msg='.execute() takes an interactive option.') def test_get_input(self): """ CommandTester.get_input() behaves properly """ self.assertEqual('bar', self.tester.get_input().get_argument('foo'), msg='.get_input() returns the current input instance.') def test_get_output(self): """ CommandTester.get_output() behaves properly """ self.tester.get_output().get_stream().seek(0) self.assertEqual('foo\n', self.tester.get_output().get_stream().read().decode(), msg='.get_output() returns the current output instance.') def test_get_display(self): """ CommandTester.get_display() behaves properly """ self.assertEqual('foo\n', self.tester.get_display(), msg='.get_display() returns the display of the last execution.')
def setUp(self): self.command = Command('foo') self.command.add_argument('command') self.command.add_argument('foo') self.command.set_code(lambda input_, output_: output_.writeln('foo')) self.tester = CommandTester(self.command) self.tester.execute([('foo', 'bar')], {'interactive': False, 'decorated': False, 'verbosity': Output.VERBOSITY_VERBOSE})
def test_execute(self): """ ListCommand.execute() behaves properly """ application = Application() command = application.get('list') command_tester = CommandTester(command) command_tester.execute([('command', command.get_name())], {'decorated': False}) self.assertTrue(re.match('(?s).*help Displays help for a command.*', command_tester.get_display()) is not None, msg='.execute() returns a list of available commands') command_tester.execute([('command', command.get_name()), ('--raw', True)]) output = """help Displays help for a command list Lists commands""" self.assertEqual(output, command_tester.get_display())