from __future__ import absolute_import
from __future__ import unicode_literals
from typing import Dict
from typing import Optional
from clikit.api.io.io import IO
from poetry.core.factory import Factory as BaseFactory
from poetry.core.toml.file import TOMLFile
from .config.config import Config
from .config.file_config_source import FileConfigSource
from .io.null_io import NullIO
from .locations import CONFIG_DIR
from .packages.locker import Locker
from .poetry import Poetry
from .repositories.pypi_repository import PyPiRepository
from .utils._compat import Path
class Factory(BaseFactory):
"""
Factory class to create various elements needed by Poetry.
"""
def create_poetry(
self, cwd=None, io=None
): # type: (Optional[Path], Optional[IO]) -> Poetry
if io is None:
io = NullIO()
base_poetry = super(Factory, self).create_poetry(cwd)
locker = Locker(
base_poetry.file.parent / "poetry.lock", base_poetry.local_config
)
# Loading global configuration
config = self.create_config(io)
# Loading local configuration
local_config_file = TOMLFile(base_poetry.file.parent / "poetry.toml")
if local_config_file.exists():
if io.is_debug():
io.write_line(
"Loading configuration file {}".format(local_config_file.path)
)
config.merge(local_config_file.read())
# Load local sources
repositories = {}
existing_repositories = config.get("repositories", {})
for source in base_poetry.pyproject.poetry_config.get("source", []):
name = source.get("name")
url = source.get("url")
if name and url:
if name not in existing_repositories:
repositories[name] = {"url": url}
config.merge({"repositories": repositories})
poetry = Poetry(
base_poetry.file.path,
base_poetry.local_config,
base_poetry.package,
locker,
config,
)
# Configuring sources
sources = poetry.local_config.get("source", [])
for source in sources:
repository = self.create_legacy_repository(source, config)
is_default = source.get("default", False)
is_secondary = source.get("secondary", False)
if io.is_debug():
message = "Adding repository {} ({})".format(
repository.name, repository.url
)
if is_default:
message += " and setting it as the default one"
elif is_secondary:
message += " and setting it as secondary"
io.write_line(message)
poetry.pool.add_repository(repository, is_default, secondary=is_secondary)
# Put PyPI last to prefer private repositories
# unless we have no default source AND no primary sources
# (default = false, secondary = false)
if poetry.pool.has_default():
if io.is_debug():
io.write_line("Deactivating the PyPI repository")
else:
default = not poetry.pool.has_primary_repositories()
poetry.pool.add_repository(PyPiRepository(config=poetry.config), default, not default)
return poetry
@classmethod
def create_config(cls, io=None): # type: (Optional[IO]) -> Config
if io is None:
io = NullIO()
config = Config()
# Load global config
config_file = TOMLFile(Path(CONFIG_DIR) / "config.toml")
if config_file.exists():
if io.is_debug():
io.write_line(
"Loading configuration file {}".format(
config_file.path
)
)
config.merge(config_file.read())
config.set_config_source(FileConfigSource(config_file))
# Load global auth config
auth_config_file = TOMLFile(Path(CONFIG_DIR) / "auth.toml")
if auth_config_file.exists():
if io.is_debug():
io.write_line(
"Loading configuration file {}".format(
auth_config_file.path
)
)
config.merge(auth_config_file.read())
config.set_auth_config_source(FileConfigSource(auth_config_file))
return config
def create_legacy_repository(
self, source, auth_config
): # type: (Dict[str, str], Config) -> LegacyRepository
from .repositories.legacy_repository import LegacyRepository
from .utils.helpers import get_cert
from .utils.helpers import get_client_cert
if "url" in source:
# PyPI-like repository
if "name" not in source:
raise RuntimeError("Missing [name] in source.")
else:
raise RuntimeError("Unsupported source specified")
name = source["name"]
url = source["url"]
return LegacyRepository(
name,
url,
config=auth_config,
cert=get_cert(auth_config, name),
client_cert=get_client_cert(auth_config, name),
)