Ejemplo n.º 1
0
    def publish(self, repository_name, username, password):
        if repository_name:
            self._io.writeln(
                'Publishing <info>{}</info> (<comment>{}</comment>) '
                'to <fg=cyan>{}</>'.format(self._package.pretty_name,
                                           self._package.pretty_version,
                                           repository_name))
        else:
            self._io.writeln(
                'Publishing <info>{}</info> (<comment>{}</comment>) '
                'to <fg=cyan>PyPI</>'.format(self._package.pretty_name,
                                             self._package.pretty_version))

        if not repository_name:
            url = 'https://upload.pypi.org/legacy/'
            repository_name = 'pypi'
        else:
            # Retrieving config information
            config_file = Path(CONFIG_DIR) / 'config.toml'

            if not config_file.exists():
                raise RuntimeError('Config file does not exist. '
                                   'Unable to get repository information')

            with config_file.open() as f:
                config = toml.loads(f.read())

            if ('repositories' not in config
                    or repository_name not in config['repositories']):
                raise RuntimeError(
                    'Repository {} is not defined'.format(repository_name))

            url = config['repositories'][repository_name]['url']

        if not (username and password):
            auth_file = Path(CONFIG_DIR) / 'auth.toml'
            if auth_file.exists():
                with auth_file.open() as f:
                    auth_config = toml.loads(f.read())

                if 'http-basic' in auth_config and repository_name in auth_config[
                        'http-basic']:
                    config = auth_config['http-basic'][repository_name]

                    username = config.get('username')
                    password = config.get('password')

        # Requesting missing credentials
        if not username:
            username = self._io.ask('Username:'******'Password:')

        # TODO: handle certificates

        self._uploader.auth(username, password)

        return self._uploader.upload(url)
Ejemplo n.º 2
0
def test_executor_should_delete_incomplete_downloads(config, io, tmp_dir,
                                                     mocker, pool,
                                                     mock_file_downloads):
    fixture = Path(__file__).parent.parent.joinpath(
        "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl")
    destination_fixture = Path(tmp_dir) / "tomlkit-0.5.3-py2.py3-none-any.whl"
    shutil.copyfile(str(fixture), str(destination_fixture))
    mocker.patch(
        "poetry.installation.executor.Executor._download_archive",
        side_effect=Exception("Download error"),
    )
    mocker.patch(
        "poetry.installation.chef.Chef.get_cached_archive_for_link",
        side_effect=lambda link: link,
    )
    mocker.patch(
        "poetry.installation.chef.Chef.get_cache_directory_for_link",
        return_value=Path(tmp_dir),
    )

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

    env = MockEnv(path=Path(tmp_dir))
    executor = Executor(env, pool, config, io)

    with pytest.raises(Exception, match="Download error"):
        executor._download(Install(Package("tomlkit", "0.5.3")))

    assert not destination_fixture.exists()
Ejemplo n.º 3
0
def test_remove_keeps_dir_if_not_deleteable(tmp_dir, manager, poetry, config,
                                            mocker):
    # Ensure we empty rather than delete folder if its is an active mount point.
    # See https://github.com/python-poetry/poetry/pull/2064
    config.merge({"virtualenvs": {"path": str(tmp_dir)}})

    venv_name = manager.generate_env_name("simple-project",
                                          str(poetry.file.parent))
    venv_path = Path(tmp_dir) / "{}-py3.6".format(venv_name)
    venv_path.mkdir()

    folder1_path = venv_path / "folder1"
    folder1_path.mkdir()

    file1_path = folder1_path / "file1"
    file1_path.touch(exist_ok=False)

    file2_path = venv_path / "file2"
    file2_path.touch(exist_ok=False)

    mocker.patch(
        "poetry.utils._compat.subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.6")),
    )

    original_rmtree = shutil.rmtree

    def err_on_rm_venv_only(path, *args, **kwargs):
        print(path)
        if path == str(venv_path):
            raise OSError(16,
                          "Test error")  # ERRNO 16: Device or resource busy
        else:
            original_rmtree(path)

    m = mocker.patch("shutil.rmtree", side_effect=err_on_rm_venv_only)

    venv = manager.remove("{}-py3.6".format(venv_name))

    m.assert_any_call(str(venv_path))

    assert venv_path == venv.path
    assert venv_path.exists()

    assert not folder1_path.exists()
    assert not file1_path.exists()
    assert not file2_path.exists()

    m.side_effect = original_rmtree  # Avoid teardown using `err_on_rm_venv_only`
Ejemplo n.º 4
0
    def update(self, release):
        from poetry.utils._compat import Path
        from poetry.utils.helpers import temporary_directory

        version = release.version
        self.line('Updating to <info>{}</info>'.format(version))

        prefix = sys.prefix
        base_prefix = getattr(sys, 'base_prefix', None)
        real_prefix = getattr(sys, 'real_prefix', None)

        prefix_poetry = Path(prefix) / 'bin' / 'poetry'
        if prefix_poetry.exists():
            pip = (prefix_poetry.parent / 'pip').resolve()
        elif (base_prefix and base_prefix != prefix
              and (Path(base_prefix) / 'bin' / 'poetry').exists()):
            pip = Path(base_prefix) / 'bin' / 'pip'
        elif real_prefix:
            pip = Path(real_prefix) / 'bin' / 'pip'
        else:
            pip = Path(prefix) / 'bin' / 'pip'

            if not pip.exists():
                raise RuntimeError('Unable to determine poetry\'s path')

        with temporary_directory(prefix='poetry-update-') as temp_dir:
            temp_dir = Path(temp_dir)
            dist = temp_dir / 'dist'
            self.line('  - Getting dependencies')
            self.process(str(pip), 'install', '-U',
                         'poetry=={}'.format(release.version), '--target',
                         str(dist))

            self.line('  - Vendorizing dependencies')

            poetry_dir = dist / 'poetry'
            vendor_dir = poetry_dir / '_vendor'

            # Everything, except poetry itself, should
            # be put in the _vendor directory
            for file in dist.glob('*'):
                if file.name.startswith('poetry'):
                    continue

                dest = vendor_dir / file.name
                if file.is_dir():
                    shutil.copytree(str(file), str(dest))
                    shutil.rmtree(str(file))
                else:
                    shutil.copy(str(file), str(dest))
                    os.unlink(str(file))

            wheel_data = dist / 'poetry-{}.dist-info'.format(version) / 'WHEEL'
            with wheel_data.open() as f:
                wheel_data = Parser().parsestr(f.read())

            tag = wheel_data['Tag']

            # Repack everything and install
            self.line('  - Updating <info>poetry</info>')

            shutil.make_archive(str(temp_dir /
                                    'poetry-{}-{}'.format(version, tag)),
                                format='zip',
                                root_dir=str(dist))

            os.rename(
                str(temp_dir / 'poetry-{}-{}.zip'.format(version, tag)),
                str(temp_dir / 'poetry-{}-{}.whl'.format(version, tag)),
            )

            self.process(
                str(pip), 'install', '--upgrade', '--no-deps',
                str(temp_dir / 'poetry-{}-{}.whl'.format(version, tag)))

            self.line('')
            self.line('<info>poetry</> (<comment>{}</>) '
                      'successfully installed!'.format(version))
Ejemplo n.º 5
0
    def update(self, release):
        from poetry.utils._compat import Path
        from poetry.utils.helpers import temporary_directory

        version = release.version
        self.line("Updating to <info>{}</info>".format(version))

        prefix = sys.prefix
        base_prefix = getattr(sys, "base_prefix", None)
        real_prefix = getattr(sys, "real_prefix", None)

        prefix_poetry = Path(prefix) / "bin" / "poetry"
        if prefix_poetry.exists():
            pip = (prefix_poetry.parent / "pip").resolve()
        elif (base_prefix and base_prefix != prefix
              and (Path(base_prefix) / "bin" / "poetry").exists()):
            pip = Path(base_prefix) / "bin" / "pip"
        elif real_prefix:
            pip = Path(real_prefix) / "bin" / "pip"
        else:
            pip = Path(prefix) / "bin" / "pip"

            if not pip.exists():
                raise RuntimeError("Unable to determine poetry's path")

        with temporary_directory(prefix="poetry-update-") as temp_dir:
            temp_dir = Path(temp_dir)
            dist = temp_dir / "dist"
            self.line("  - Getting dependencies")
            self.process(
                str(pip),
                "install",
                "-U",
                "poetry=={}".format(release.version),
                "--target",
                str(dist),
            )

            self.line("  - Vendorizing dependencies")

            poetry_dir = dist / "poetry"
            vendor_dir = poetry_dir / "_vendor"

            # Everything, except poetry itself, should
            # be put in the _vendor directory
            for file in dist.glob("*"):
                if file.name.startswith("poetry"):
                    continue

                dest = vendor_dir / file.name
                if file.is_dir():
                    shutil.copytree(str(file), str(dest))
                    shutil.rmtree(str(file))
                else:
                    shutil.copy(str(file), str(dest))
                    os.unlink(str(file))

            wheel_data = dist / "poetry-{}.dist-info".format(version) / "WHEEL"
            with wheel_data.open() as f:
                wheel_data = Parser().parsestr(f.read())

            tag = wheel_data["Tag"]

            # Repack everything and install
            self.line("  - Updating <info>poetry</info>")

            shutil.make_archive(
                str(temp_dir / "poetry-{}-{}".format(version, tag)),
                format="zip",
                root_dir=str(dist),
            )

            os.rename(
                str(temp_dir / "poetry-{}-{}.zip".format(version, tag)),
                str(temp_dir / "poetry-{}-{}.whl".format(version, tag)),
            )

            self.process(
                str(pip),
                "install",
                "--upgrade",
                "--no-deps",
                str(temp_dir / "poetry-{}-{}.whl".format(version, tag)),
            )

            self.line("")
            self.line("<info>poetry</> (<comment>{}</>) "
                      "successfully installed!".format(version))
Ejemplo n.º 6
0
def test_self_update_should_install_all_necessary_elements(
    app, http, mocker, environ, tmp_dir
):
    os.environ["POETRY_HOME"] = tmp_dir

    command = app.find("self update")

    version = Version.parse(__version__).next_minor.text
    mocker.patch(
        "poetry.repositories.pypi_repository.PyPiRepository.find_packages",
        return_value=[Package("poetry", version)],
    )
    mocker.patch.object(command, "_check_recommended_installation", return_value=None)
    mocker.patch.object(
        command, "_get_release_name", return_value="poetry-{}-darwin".format(version)
    )
    mocker.patch("subprocess.check_output", return_value=b"Python 3.8.2")

    http.register_uri(
        "GET",
        command.BASE_URL + "/{}/poetry-{}-darwin.sha256sum".format(version, version),
        body=FIXTURES.joinpath("poetry-1.0.5-darwin.sha256sum").read_bytes(),
    )
    http.register_uri(
        "GET",
        command.BASE_URL + "/{}/poetry-{}-darwin.tar.gz".format(version, version),
        body=FIXTURES.joinpath("poetry-1.0.5-darwin.tar.gz").read_bytes(),
    )

    tester = CommandTester(command)
    tester.execute()

    bin_ = Path(tmp_dir).joinpath("bin")
    lib = Path(tmp_dir).joinpath("lib")
    assert bin_.exists()

    script = bin_.joinpath("poetry")
    assert script.exists()

    expected_script = """\
# -*- coding: utf-8 -*-
import glob
import sys
import os

lib = os.path.normpath(os.path.join(os.path.realpath(__file__), "../..", "lib"))
vendors = os.path.join(lib, "poetry", "_vendor")
current_vendors = os.path.join(
    vendors, "py{}".format(".".join(str(v) for v in sys.version_info[:2]))
)
sys.path.insert(0, lib)
sys.path.insert(0, current_vendors)

if __name__ == "__main__":
    from poetry.console import main
    main()
"""
    if not WINDOWS:
        expected_script = "#!/usr/bin/env python\n" + expected_script

    assert expected_script == script.read_text()

    if WINDOWS:
        bat = bin_.joinpath("poetry.bat")
        expected_bat = '@echo off\r\npython "{}" %*\r\n'.format(
            str(script).replace(os.environ.get("USERPROFILE", ""), "%USERPROFILE%")
        )
        assert bat.exists()
        with bat.open(newline="") as f:
            assert expected_bat == f.read()

    assert lib.exists()
    assert lib.joinpath("poetry").exists()
Ejemplo n.º 7
0
    def publish(self, repository_name, username, password):
        if repository_name:
            self._io.writeln(
                "Publishing <info>{}</info> (<comment>{}</comment>) "
                "to <fg=cyan>{}</>".format(
                    self._package.pretty_name,
                    self._package.pretty_version,
                    repository_name,
                ))
        else:
            self._io.writeln(
                "Publishing <info>{}</info> (<comment>{}</comment>) "
                "to <fg=cyan>PyPI</>".format(self._package.pretty_name,
                                             self._package.pretty_version))

        if not repository_name:
            url = "https://upload.pypi.org/legacy/"
            repository_name = "pypi"
        else:
            # Retrieving config information
            config_file = Path(CONFIG_DIR) / "config.toml"

            if not config_file.exists():
                raise RuntimeError("Config file does not exist. "
                                   "Unable to get repository information")

            with config_file.open() as f:
                config = toml.loads(f.read())

            if ("repositories" not in config
                    or repository_name not in config["repositories"]):
                raise RuntimeError(
                    "Repository {} is not defined".format(repository_name))

            url = config["repositories"][repository_name]["url"]

        if not (username and password):
            auth_file = Path(CONFIG_DIR) / "auth.toml"
            if auth_file.exists():
                with auth_file.open() as f:
                    auth_config = toml.loads(f.read())

                if ("http-basic" in auth_config
                        and repository_name in auth_config["http-basic"]):
                    config = auth_config["http-basic"][repository_name]

                    username = config.get("username")
                    password = config.get("password")

        # Requesting missing credentials
        if not username:
            username = self._io.ask("Username:"******"Password:")

        # TODO: handle certificates

        self._uploader.auth(username, password)

        return self._uploader.upload(url)
Ejemplo n.º 8
0
    def create(cls, path=None):
        path = path or os.getcwd()
        pyproject_file = Path(path)

        if pyproject_file.name != "pyproject.toml":
            pyproject_file = pyproject_file / "pyproject.toml"

        if not pyproject_file.exists():
            raise RuntimeError(
                "Jetty could not find a pyproject.toml file in {}".format(
                    path))

        local_config = TomlFile(pyproject_file.as_posix()).read()
        tool = local_config.setdefault('tool', {})

        if 'jetty' not in tool and 'poetry' not in tool:
            raise RuntimeError("[tool.jetty] section not found in {}".format(
                pyproject_file.name))

        local_config = merge(tool.get('jetty', {}), tool.get('poetry', {}))

        # Checking validity
        cls.check(local_config)

        # Load package
        name = local_config.get('name', pyproject_file.parent.name)
        version = local_config.get('version', '0')
        package = ProjectPackage(name, version, version)

        if 'dependencies' in local_config:
            for name, constraint in local_config['dependencies'].items():
                if name.lower() == 'python':
                    package.python_versions = constraint
                    continue

                if isinstance(constraint, list):
                    for _constraint in constraint:
                        package.add_dependency(name, _constraint)

                    continue

                package.add_dependency(name, constraint)

        if 'dev-dependencies' in local_config:
            for name, constraint in local_config['dev-dependencies'].items():
                if isinstance(constraint, list):
                    for _constraint in constraint:
                        package.add_dependency(name,
                                               _constraint,
                                               category='dev')

                    continue

                package.add_dependency(name, constraint, category='dev')

        extras = local_config.get("extras", {})
        for extra_name, requirements in extras.items():
            package.extras[extra_name] = []

            # Checking for dependency
            for req in requirements:
                req = Dependency(req, "*")

                for dep in package.requires:
                    if dep.name == req.name:
                        dep.in_extras.append(extra_name)
                        package.extras[extra_name].append(dep)

                        break

        lock = pyproject_file.parent / "poetry.lock"
        locker = Locker(lock, local_config)
        return cls(pyproject_file, local_config, package, locker)