Commit 9b286303 by Sébastien Eustace Committed by GitHub

Add a Factory class to help create objects needed by Poetry (#1349)

parent 2e579c74
......@@ -11,13 +11,16 @@ from poetry.locations import CACHE_DIR
from poetry.utils._compat import Path
from poetry.utils._compat import basestring
from .config_source import ConfigSource
from .dict_config_source import DictConfigSource
_NOT_SET = object()
boolean_validator = lambda val: val in {"true", "false", "1", "0"}
boolean_normalizer = lambda val: val in ["true", "1"]
class Config:
class Config(object):
default_config = {
"cache-dir": str(CACHE_DIR),
......@@ -34,6 +37,8 @@ class Config:
self._config = deepcopy(self.default_config)
self._use_environment = use_environment
self._base_dir = base_dir
self._config_source = DictConfigSource()
self._auth_config_source = DictConfigSource()
@property
def name(self):
......@@ -43,6 +48,24 @@ class Config:
def config(self):
return self._config
@property
def config_source(self): # type: () -> ConfigSource
return self._config_source
@property
def auth_config_source(self): # type: () -> ConfigSource
return self._auth_config_source
def set_config_source(self, config_source): # type: (ConfigSource) -> Config
self._config_source = config_source
return self
def set_auth_config_source(self, config_source): # type: (ConfigSource) -> Config
self._auth_config_source = config_source
return self
def merge(self, config): # type: (Dict[str, Any]) -> None
from poetry.utils.helpers import merge_dicts
......
import io
import os
from contextlib import contextmanager
from typing import Any
from tomlkit import document
from tomlkit import table
from poetry.utils.toml_file import TomlFile
class ConfigSource:
def __init__(self, file, auth_config=False): # type: (TomlFile, bool) -> None
self._file = file
self._auth_config = auth_config
@property
def name(self): # type: () -> str
return str(self._file.path)
@property
def file(self): # type: () -> TomlFile
return self._file
class ConfigSource(object):
def add_property(self, key, value): # type: (str, Any) -> None
with self.secure() as config:
keys = key.split(".")
for i, key in enumerate(keys):
if key not in config and i < len(keys) - 1:
config[key] = table()
if i == len(keys) - 1:
config[key] = value
break
config = config[key]
raise NotImplementedError()
def remove_property(self, key): # type: (str) -> None
with self.secure() as config:
keys = key.split(".")
current_config = config
for i, key in enumerate(keys):
if key not in current_config:
return
if i == len(keys) - 1:
del current_config[key]
break
current_config = current_config[key]
@contextmanager
def secure(self):
if self.file.exists():
initial_config = self.file.read()
config = self.file.read()
else:
initial_config = document()
config = document()
new_file = not self.file.exists()
yield config
try:
# Ensuring the file is only readable and writable
# by the current user
mode = 0o600
if new_file:
self.file.touch(mode=mode)
self.file.write(config)
except Exception:
self.file.write(initial_config)
raise
raise NotImplementedError()
from typing import Any
from typing import Dict
from .config_source import ConfigSource
class DictConfigSource(ConfigSource):
def __init__(self): # type: () -> None
self._config = {}
@property
def config(self): # type: () -> Dict[str, Any]
return self._config
def add_property(self, key, value): # type: (str, Any) -> None
keys = key.split(".")
config = self._config
for i, key in enumerate(keys):
if key not in config and i < len(keys) - 1:
config[key] = {}
if i == len(keys) - 1:
config[key] = value
break
config = config[key]
def remove_property(self, key): # type: (str) -> None
keys = key.split(".")
config = self._config
for i, key in enumerate(keys):
if key not in config:
return
if i == len(keys) - 1:
del config[key]
break
config = config[key]
from contextlib import contextmanager
from typing import Any
from tomlkit import document
from tomlkit import table
from poetry.utils.toml_file import TomlFile
from .config_source import ConfigSource
class FileConfigSource(ConfigSource):
def __init__(self, file, auth_config=False): # type: (TomlFile, bool) -> None
self._file = file
self._auth_config = auth_config
@property
def name(self): # type: () -> str
return str(self._file.path)
@property
def file(self): # type: () -> TomlFile
return self._file
def add_property(self, key, value): # type: (str, Any) -> None
with self.secure() as config:
keys = key.split(".")
for i, key in enumerate(keys):
if key not in config and i < len(keys) - 1:
config[key] = table()
if i == len(keys) - 1:
config[key] = value
break
config = config[key]
def remove_property(self, key): # type: (str) -> None
with self.secure() as config:
keys = key.split(".")
current_config = config
for i, key in enumerate(keys):
if key not in current_config:
return
if i == len(keys) - 1:
del current_config[key]
break
current_config = current_config[key]
@contextmanager
def secure(self):
if self.file.exists():
initial_config = self.file.read()
config = self.file.read()
else:
initial_config = document()
config = document()
new_file = not self.file.exists()
yield config
try:
# Ensuring the file is only readable and writable
# by the current user
mode = 0o600
if new_file:
self.file.touch(mode=mode)
self.file.write(config)
except Exception:
self.file.write(initial_config)
raise
......@@ -47,12 +47,13 @@ class Application(BaseApplication):
@property
def poetry(self):
from poetry.poetry import Poetry
from poetry.factory import Factory
from poetry.utils._compat import Path
if self._poetry is not None:
return self._poetry
self._poetry = Poetry.create(os.getcwd())
self._poetry = Factory().create_poetry(Path.cwd())
return self._poetry
......
from poetry.poetry import Poetry
from poetry.factory import Factory
from poetry.utils._compat import Path
from poetry.utils.toml_file import TomlFile
......@@ -12,9 +12,9 @@ class CheckCommand(Command):
def handle(self):
# Load poetry config and display errors, if any
poetry_file = Poetry.locate(Path.cwd())
poetry_file = Factory.locate(Path.cwd())
config = TomlFile(str(poetry_file)).read()["tool"]["poetry"]
check_result = Poetry.check(config, strict=True)
check_result = Factory.validate(config, strict=True)
if not check_result["errors"] and not check_result["warnings"]:
self.info("All set!")
......
......@@ -4,6 +4,7 @@ import re
from cleo import argument
from cleo import option
from poetry.factory import Factory
from poetry.utils.helpers import (
keyring_repository_password_del,
keyring_repository_password_set,
......@@ -37,6 +38,8 @@ To remove a repository (repo is a short alias for repositories):
<comment>poetry config --unset repo.foo</comment>"""
LIST_PROHIBITED_SETTINGS = {"http-basic", "pypi-token"}
@property
def unique_config_values(self):
from poetry.locations import CACHE_DIR
......@@ -63,28 +66,24 @@ To remove a repository (repo is a short alias for repositories):
return unique_config_values
def handle(self):
from poetry.config.config import Config
from poetry.config.config_source import ConfigSource
from poetry.config.file_config_source import FileConfigSource
from poetry.locations import CONFIG_DIR
from poetry.utils._compat import Path
from poetry.utils._compat import basestring
from poetry.utils.toml_file import TomlFile
config = Config()
config = Factory.create_config(self.io)
config_file = TomlFile(Path(CONFIG_DIR) / "config.toml")
config_source = ConfigSource(config_file)
if config_source.file.exists():
config.merge(config_source.file.read())
auth_config_file = TomlFile(Path(CONFIG_DIR) / "auth.toml")
auth_config_source = ConfigSource(auth_config_file, auth_config=True)
local_config_file = TomlFile(self.poetry.file.parent / "poetry.toml")
if local_config_file.exists():
config.merge(local_config_file.read())
try:
local_config_file = TomlFile(self.poetry.file.parent / "poetry.toml")
if local_config_file.exists():
config.merge(local_config_file.read())
except RuntimeError:
local_config_file = TomlFile(Path.cwd() / "poetry.toml")
if self.option("local"):
config_source = ConfigSource(local_config_file)
config.set_config_source(FileConfigSource(local_config_file))
if not config_file.exists():
config_file.path.parent.mkdir(parents=True, exist_ok=True)
......@@ -139,10 +138,13 @@ To remove a repository (repo is a short alias for repositories):
unique_config_values = self.unique_config_values
if setting_key in unique_config_values:
if self.option("unset"):
return config_source.remove_property(setting_key)
return config.config_source.remove_property(setting_key)
return self._handle_single_value(
config_source, setting_key, unique_config_values[setting_key], values
config.config_source,
setting_key,
unique_config_values[setting_key],
values,
)
# handle repositories
......@@ -158,14 +160,16 @@ To remove a repository (repo is a short alias for repositories):
"There is no {} repository defined".format(m.group(1))
)
config_source.remove_property("repositories.{}".format(m.group(1)))
config.config_source.remove_property(
"repositories.{}".format(m.group(1))
)
return 0
if len(values) == 1:
url = values[0]
config_source.add_property(
config.config_source.add_property(
"repositories.{}.url".format(m.group(1)), url
)
......@@ -181,7 +185,7 @@ To remove a repository (repo is a short alias for repositories):
if m:
if self.option("unset"):
keyring_repository_password_del(config, m.group(2))
auth_config_source.remove_property(
config.auth_config_source.remove_property(
"{}.{}".format(m.group(1), m.group(2))
)
......@@ -207,7 +211,7 @@ To remove a repository (repo is a short alias for repositories):
except RuntimeError:
property_value.update(password=password)
auth_config_source.add_property(
config.auth_config_source.add_property(
"{}.{}".format(m.group(1), m.group(2)), property_value
)
elif m.group(1) == "pypi-token":
......@@ -218,7 +222,7 @@ To remove a repository (repo is a short alias for repositories):
token = values[0]
auth_config_source.add_property(
config.auth_config_source.add_property(
"{}.{}".format(m.group(1), m.group(2)), token
)
......@@ -245,6 +249,9 @@ To remove a repository (repo is a short alias for repositories):
orig_k = k
for key, value in sorted(config.items()):
if k + key in self.LIST_PROHIBITED_SETTINGS:
continue
raw_val = raw.get(key)
if isinstance(value, dict):
......
from __future__ import absolute_import
from __future__ import unicode_literals
import shutil
from typing import Dict
from typing import List
from typing import Optional
from clikit.api.io.io import IO
from .config.config import Config
from .config.file_config_source import FileConfigSource
from .io.null_io import NullIO
from .json import validate_object
from .locations import CONFIG_DIR
from .packages.dependency import Dependency
from .packages.locker import Locker
from .packages.project_package import ProjectPackage
from .poetry import Poetry
from .repositories.pypi_repository import PyPiRepository
from .spdx import license_by_id
from .utils._compat import Path
from .utils.toml_file import TomlFile
class Factory:
"""
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()
poetry_file = self.locate(cwd)
local_config = TomlFile(poetry_file.as_posix()).read()
if "tool" not in local_config or "poetry" not in local_config["tool"]:
raise RuntimeError(
"[tool.poetry] section not found in {}".format(poetry_file.name)
)
local_config = local_config["tool"]["poetry"]
# Checking validity
check_result = self.validate(local_config)
if check_result["errors"]:
message = ""
for error in check_result["errors"]:
message += " - {}\n".format(error)
raise RuntimeError("The Poetry configuration is invalid:\n" + message)
# Load package
name = local_config["name"]
version = local_config["version"]
package = ProjectPackage(name, version, version)
package.root_dir = poetry_file.parent
for author in local_config["authors"]:
package.authors.append(author)
for maintainer in local_config.get("maintainers", []):
package.maintainers.append(maintainer)
package.description = local_config.get("description", "")
package.homepage = local_config.get("homepage")
package.repository_url = local_config.get("repository")
package.documentation_url = local_config.get("documentation")
try:
license_ = license_by_id(local_config.get("license", ""))
except ValueError:
license_ = None
package.license = license_
package.keywords = local_config.get("keywords", [])
package.classifiers = local_config.get("classifiers", [])
if "readme" in local_config:
package.readme = Path(poetry_file.parent) / local_config["readme"]
if "platform" in local_config:
package.platform = local_config["platform"]
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
if "build" in local_config:
package.build = local_config["build"]
if "include" in local_config:
package.include = local_config["include"]
if "exclude" in local_config:
package.exclude = local_config["exclude"]
if "packages" in local_config:
package.packages = local_config["packages"]
# Custom urls
if "urls" in local_config:
package.custom_urls = local_config["urls"]
# Moving lock if necessary (pyproject.lock -> poetry.lock)
lock = poetry_file.parent / "poetry.lock"
if not lock.exists():
# Checking for pyproject.lock
old_lock = poetry_file.with_suffix(".lock")
if old_lock.exists():
shutil.move(str(old_lock), str(lock))
locker = Locker(poetry_file.parent / "poetry.lock", local_config)
# Loading global configuration
config = self.create_config(io)
# Loading local configuration
local_config_file = TomlFile(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())
poetry = Poetry(poetry_file, local_config, package, locker, config)
# Configuring sources
for source in local_config.get("source", []):
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)
# Always put PyPI last to prefer private repositories
# but only if we have no other default source
if not poetry.pool.has_default():
poetry.pool.add_repository(PyPiRepository(), True)
else:
if io.is_debug():
io.write_line("Deactivating the PyPI repository")
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(
"<debug>Loading configuration file {}</debug>".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(
"<debug>Loading configuration file {}</debug>".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.auth import Auth
from .repositories.legacy_repository import LegacyRepository
from .utils.helpers import get_http_basic_auth
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"]
credentials = get_http_basic_auth(auth_config, name)
if not credentials:
return LegacyRepository(name, url)
auth = Auth(url, credentials[0], credentials[1])
return LegacyRepository(name, url, auth=auth)
@classmethod
def validate(
cls, config, strict=False
): # type: (dict, bool) -> Dict[str, List[str]]
"""
Checks the validity of a configuration
"""
result = {"errors": [], "warnings": []}
# Schema validation errors
validation_errors = validate_object(config, "poetry-schema")
result["errors"] += validation_errors
if strict:
# If strict, check the file more thoroughly
# Checking license
license = config.get("license")
if license:
try:
license_by_id(license)
except ValueError:
result["errors"].append("{} is not a valid license".format(license))
if "dependencies" in config:
python_versions = config["dependencies"]["python"]
if python_versions == "*":
result["warnings"].append(
"A wildcard Python dependency is ambiguous. "
"Consider specifying a more explicit one."
)
# Checking for scripts with extras
if "scripts" in config:
scripts = config["scripts"]
for name, script in scripts.items():
if not isinstance(script, dict):
continue
extras = script["extras"]
for extra in extras:
if extra not in config["extras"]:
result["errors"].append(
'Script "{}" requires extra "{}" which is not defined.'.format(
name, extra
)
)
return result
@classmethod
def locate(cls, cwd): # type: (Path) -> Path
candidates = [Path(cwd)]
candidates.extend(Path(cwd).parents)
for path in candidates:
poetry_file = path / "pyproject.toml"
if poetry_file.exists():
return poetry_file
else:
raise RuntimeError(
"Poetry could not find a pyproject.toml file in {} or its parents".format(
cwd
)
)
......@@ -6,7 +6,7 @@ import sys
from clikit.io import NullIO
from poetry.poetry import Poetry
from poetry.factory import Factory
from poetry.utils._compat import Path
from poetry.utils._compat import unicode
from poetry.utils.env import SystemEnv
......@@ -21,7 +21,7 @@ def get_requires_for_build_wheel(config_settings=None):
"""
Returns a list of requirements for building, as strings
"""
poetry = Poetry.create(".")
poetry = Factory().create_poetry(Path("."))
main, _ = SdistBuilder.convert_dependencies(poetry.package, poetry.package.requires)
......@@ -33,7 +33,7 @@ get_requires_for_build_sdist = get_requires_for_build_wheel
def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
poetry = Poetry.create(".")
poetry = Factory().create_poetry(Path("."))
builder = WheelBuilder(poetry, SystemEnv(Path(sys.prefix)), NullIO())
dist_info = Path(metadata_directory, builder.dist_info)
......@@ -54,7 +54,7 @@ def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
"""Builds a wheel, places it in wheel_directory"""
poetry = Poetry.create(".")
poetry = Factory().create_poetry(Path("."))
return unicode(
WheelBuilder.make_in(
......@@ -65,7 +65,7 @@ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
def build_sdist(sdist_directory, config_settings=None):
"""Builds an sdist, places it in sdist_directory"""
poetry = Poetry.create(".")
poetry = Factory().create_poetry(Path("."))
path = SdistBuilder(poetry, SystemEnv(Path(sys.prefix)), NullIO()).build(
Path(sdist_directory)
......
import os
import tarfile
import poetry.poetry
from poetry.factory import Factory
from poetry.io.null_io import NullIO
from poetry.utils._compat import Path
from poetry.utils.helpers import temporary_directory
......@@ -43,7 +43,7 @@ class CompleteBuilder(Builder):
with self.unpacked_tarball(sdist_file) as tmpdir:
WheelBuilder.make_in(
poetry.poetry.Poetry.create(tmpdir),
Factory().create_poetry(tmpdir),
self._env,
self._io,
dist_dir,
......@@ -52,7 +52,7 @@ class CompleteBuilder(Builder):
else:
with self.unpacked_tarball(sdist_file) as tmpdir:
WheelBuilder.make_in(
poetry.poetry.Poetry.create(tmpdir),
Factory().create_poetry(tmpdir),
self._env,
self._io,
dist_dir,
......@@ -70,4 +70,4 @@ class CompleteBuilder(Builder):
assert len(files) == 1, files
yield os.path.join(tmpdir, files[0])
yield Path(tmpdir) / files[0]
from __future__ import absolute_import
from __future__ import unicode_literals
import shutil
from typing import Dict
from typing import List
from typing import Optional
from .__version__ import __version__
from .config.config import Config
from .json import validate_object
from .locations import CONFIG_DIR
from .packages import Dependency
from .packages import Locker
from .packages import Package
from .packages import ProjectPackage
from .repositories import Pool
from .repositories.auth import Auth
from .repositories.legacy_repository import LegacyRepository
from .repositories.pypi_repository import PyPiRepository
from .spdx import license_by_id
from .repositories.pool import Pool
from .utils._compat import Path
from .utils.helpers import get_http_basic_auth
from .utils.toml_file import TomlFile
......@@ -32,7 +20,7 @@ class Poetry:
self,
file, # type: Path
local_config, # type: dict
package, # type: Package
package, # type: ProjectPackage
locker, # type: Locker
config, # type: Config
):
......@@ -41,28 +29,14 @@ class Poetry:
self._local_config = local_config
self._locker = locker
self._config = config
# Configure sources
self._pool = Pool()
for source in self._local_config.get("source", []):
repository = self.create_legacy_repository(source)
self._pool.add_repository(
repository,
source.get("default", False),
secondary=source.get("secondary", False),
)
# Always put PyPI last to prefer private repositories
# but only if we have no other default source
if not self._pool.has_default():
self._pool.add_repository(PyPiRepository(), True)
@property
def file(self):
return self._file
@property
def package(self): # type: () -> Package
def package(self): # type: () -> ProjectPackage
return self._package
@property
......@@ -81,221 +55,17 @@ class Poetry:
def config(self): # type: () -> Config
return self._config
@classmethod
def create(cls, cwd): # type: (Path) -> Poetry
poetry_file = cls.locate(cwd)
local_config = TomlFile(poetry_file.as_posix()).read()
if "tool" not in local_config or "poetry" not in local_config["tool"]:
raise RuntimeError(
"[tool.poetry] section not found in {}".format(poetry_file.name)
)
local_config = local_config["tool"]["poetry"]
# Checking validity
check_result = cls.check(local_config)
if check_result["errors"]:
message = ""
for error in check_result["errors"]:
message += " - {}\n".format(error)
raise RuntimeError("The Poetry configuration is invalid:\n" + message)
# Load package
name = local_config["name"]
version = local_config["version"]
package = ProjectPackage(name, version, version)
package.root_dir = poetry_file.parent
for author in local_config["authors"]:
package.authors.append(author)
for maintainer in local_config.get("maintainers", []):
package.maintainers.append(maintainer)
package.description = local_config.get("description", "")
package.homepage = local_config.get("homepage")
package.repository_url = local_config.get("repository")
package.documentation_url = local_config.get("documentation")
try:
license_ = license_by_id(local_config.get("license", ""))
except ValueError:
license_ = None
package.license = license_
package.keywords = local_config.get("keywords", [])
package.classifiers = local_config.get("classifiers", [])
if "readme" in local_config:
package.readme = Path(poetry_file.parent) / local_config["readme"]
if "platform" in local_config:
package.platform = local_config["platform"]
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
if "build" in local_config:
package.build = local_config["build"]
if "include" in local_config:
package.include = local_config["include"]
if "exclude" in local_config:
package.exclude = local_config["exclude"]
if "packages" in local_config:
package.packages = local_config["packages"]
# Custom urls
if "urls" in local_config:
package.custom_urls = local_config["urls"]
# Moving lock if necessary (pyproject.lock -> poetry.lock)
lock = poetry_file.parent / "poetry.lock"
if not lock.exists():
# Checking for pyproject.lock
old_lock = poetry_file.with_suffix(".lock")
if old_lock.exists():
shutil.move(str(old_lock), str(lock))
locker = Locker(poetry_file.parent / "poetry.lock", local_config)
config = Config()
# Load global config
config_file = TomlFile(Path(CONFIG_DIR) / "config.toml")
if config_file.exists():
config.merge(config_file.read())
local_config_file = TomlFile(poetry_file.parent / "poetry.toml")
if local_config_file.exists():
config.merge(local_config_file.read())
# Load global auth config
auth_config_file = TomlFile(Path(CONFIG_DIR) / "auth.toml")
if auth_config_file.exists():
config.merge(auth_config_file.read())
return cls(poetry_file, local_config, package, locker, config)
def create_legacy_repository(
self, source
): # type: (Dict[str, str]) -> LegacyRepository
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"]
credentials = get_http_basic_auth(self._config, name)
if not credentials:
return LegacyRepository(name, url)
auth = Auth(url, credentials[0], credentials[1])
return LegacyRepository(name, url, auth=auth)
@classmethod
def locate(cls, cwd): # type: (Path) -> Poetry
candidates = [Path(cwd)]
candidates.extend(Path(cwd).parents)
for path in candidates:
poetry_file = path / "pyproject.toml"
if poetry_file.exists():
return poetry_file
else:
raise RuntimeError(
"Poetry could not find a pyproject.toml file in {} or its parents".format(
cwd
)
)
@classmethod
def check(cls, config, strict=False): # type: (dict, bool) -> Dict[str, List[str]]
"""
Checks the validity of a configuration
"""
result = {"errors": [], "warnings": []}
# Schema validation errors
validation_errors = validate_object(config, "poetry-schema")
result["errors"] += validation_errors
if strict:
# If strict, check the file more thoroughly
def set_locker(self, locker): # type: (Locker) -> Poetry
self._locker = locker
# Checking license
license = config.get("license")
if license:
try:
license_by_id(license)
except ValueError:
result["errors"].append("{} is not a valid license".format(license))
return self
if "dependencies" in config:
python_versions = config["dependencies"]["python"]
if python_versions == "*":
result["warnings"].append(
"A wildcard Python dependency is ambiguous. "
"Consider specifying a more explicit one."
)
def set_pool(self, pool): # type: (Pool) -> Poetry
self._pool = pool
# Checking for scripts with extras
if "scripts" in config:
scripts = config["scripts"]
for name, script in scripts.items():
if not isinstance(script, dict):
continue
return self
extras = script["extras"]
for extra in extras:
if extra not in config["extras"]:
result["errors"].append(
'Script "{}" requires extra "{}" which is not defined.'.format(
name, extra
)
)
def set_config(self, config): # type: (Config) -> Poetry
self._config = config
return result
return self
......@@ -11,6 +11,7 @@ from tempfile import mkdtemp
from typing import List
from typing import Optional
from poetry.factory import Factory
from poetry.packages import Dependency
from poetry.packages import DependencyPackage
from poetry.packages import DirectoryDependency
......@@ -300,9 +301,7 @@ class Provider:
)
if supports_poetry:
from poetry.poetry import Poetry
poetry = Poetry.create(directory)
poetry = Factory().create_poetry(directory)
pkg = poetry.package
package = Package(pkg.name, pkg.version)
......
......@@ -8,7 +8,7 @@ def test_config_get_default_value(config):
def test_config_get_processes_depended_on_values(config):
assert os.path.join(str(CACHE_DIR), "virtualenvs") == config.get("virtualenvs.path")
assert os.path.join("/foo", "virtualenvs") == config.get("virtualenvs.path")
def test_config_get_from_environment_variable(config, environ):
......
......@@ -10,43 +10,68 @@ try:
except ImportError:
import urlparse
from tomlkit import parse
from typing import Any
from typing import Dict
from poetry.config.config import Config
from poetry.config.config import Config as BaseConfig
from poetry.config.dict_config_source import DictConfigSource
from poetry.utils._compat import PY2
from poetry.utils._compat import WINDOWS
from poetry.utils._compat import Path
from poetry.utils.helpers import merge_dicts
from poetry.utils.toml_file import TomlFile
class Config(BaseConfig):
def get(self, setting_name, default=None): # type: (str, Any) -> Any
self.merge(self._config_source.config)
self.merge(self._auth_config_source.config)
return super(Config, self).get(setting_name, default=default)
def raw(self): # type: () -> Dict[str, Any]
self.merge(self._config_source.config)
self.merge(self._auth_config_source.config)
return super(Config, self).raw()
def all(self): # type: () -> Dict[str, Any]
self.merge(self._config_source.config)
self.merge(self._auth_config_source.config)
return super(Config, self).all()
def tmp_dir():
dir_ = tempfile.mkdtemp(prefix="poetry_")
yield dir_
shutil.rmtree(dir_)
@pytest.fixture
def config_document():
content = """cache-dir = "/foo"
"""
doc = parse(content)
def config_source():
source = DictConfigSource()
source.add_property("cache-dir", "/foo")
return doc
return source
@pytest.fixture
def config_source(config_document, mocker):
file = TomlFile(Path(tempfile.mktemp()))
mocker.patch.object(file, "exists", return_value=True)
mocker.patch.object(file, "read", return_value=config_document)
mocker.patch.object(
file, "write", return_value=lambda new: merge_dicts(config_document, new)
)
mocker.patch(
"poetry.config.config_source.ConfigSource.file",
new_callable=mocker.PropertyMock,
return_value=file,
)
def auth_config_source():
source = DictConfigSource()
return source
@pytest.fixture
def config(config_source):
def config(config_source, auth_config_source, mocker):
c = Config()
c.merge(config_source.config)
c.set_config_source(config_source)
c.set_auth_config_source(auth_config_source)
mocker.patch("poetry.factory.Factory.create_config", return_value=c)
mocker.patch("poetry.config.config.Config.set_config_source")
return c
......
......@@ -2,7 +2,6 @@ from cleo.testers import CommandTester
from poetry.utils._compat import PY2
from poetry.utils._compat import Path
from poetry.poetry import Poetry
def test_check_valid(app):
......@@ -20,7 +19,7 @@ All set!
def test_check_invalid(app, mocker):
mocker.patch(
"poetry.poetry.Poetry.locate",
"poetry.factory.Factory.locate",
return_value=Path(__file__).parent.parent.parent
/ "fixtures"
/ "invalid_pyproject"
......
......@@ -4,13 +4,12 @@ import os
from cleo.testers import CommandTester
from poetry.config.config_source import ConfigSource
from poetry.poetry import Poetry
from poetry.factory import Factory
def test_list_displays_default_value_if_not_set(app, config_source):
def test_list_displays_default_value_if_not_set(app, config):
command = app.find("config")
tester = CommandTester(command)
tester.execute("--list")
expected = """cache-dir = "/foo"
......@@ -24,7 +23,7 @@ virtualenvs.path = {path} # /foo{sep}virtualenvs
assert expected == tester.io.fetch_output()
def test_list_displays_set_get_setting(app, config_source, config_document):
def test_list_displays_set_get_setting(app, config):
command = app.find("config")
tester = CommandTester(command)
......@@ -40,10 +39,11 @@ virtualenvs.path = {path} # /foo{sep}virtualenvs
path=json.dumps(os.path.join("{cache-dir}", "virtualenvs")), sep=os.path.sep
)
assert 0 == config.set_config_source.call_count
assert expected == tester.io.fetch_output()
def test_display_single_setting(app, config_source):
def test_display_single_setting(app, config):
command = app.find("config")
tester = CommandTester(command)
......@@ -55,8 +55,8 @@ def test_display_single_setting(app, config_source):
assert expected == tester.io.fetch_output()
def test_display_single_local_setting(app, config_source, fixture_dir):
poetry = Poetry.create(fixture_dir("with_local_config"))
def test_display_single_local_setting(app, config, fixture_dir):
poetry = Factory().create_poetry(fixture_dir("with_local_config"))
app._poetry = poetry
command = app.find("config")
......@@ -70,10 +70,7 @@ def test_display_single_local_setting(app, config_source, fixture_dir):
assert expected == tester.io.fetch_output()
def test_list_displays_set_get_local_setting(
app, config_source, config_document, mocker
):
init = mocker.spy(ConfigSource, "__init__")
def test_list_displays_set_get_local_setting(app, config):
command = app.find("config")
tester = CommandTester(command)
......@@ -89,14 +86,11 @@ virtualenvs.path = {path} # /foo{sep}virtualenvs
path=json.dumps(os.path.join("{cache-dir}", "virtualenvs")), sep=os.path.sep
)
assert expected == tester.io.fetch_output()
assert "poetry.toml" == init.call_args_list[2][0][1].path.name
assert 1 == config.set_config_source.call_count
assert expected == tester.io.fetch_output()
def test_set_pypi_token(app, config_source, config_document, mocker):
init = mocker.spy(ConfigSource, "__init__")
def test_set_pypi_token(app, config, config_source, auth_config_source):
command = app.find("config")
tester = CommandTester(command)
......@@ -104,4 +98,4 @@ def test_set_pypi_token(app, config_source, config_document, mocker):
tester.execute("--list")
assert "mytoken" == config_document["pypi-token"]["pypi"]
assert "mytoken" == auth_config_source.config["pypi-token"]["pypi"]
......@@ -5,11 +5,13 @@ import pytest
from cleo.testers import CommandTester
from poetry.factory import Factory
from poetry.repositories.pool import Pool
from tests.helpers import get_package
from ..conftest import Application
from ..conftest import Locker
from ..conftest import Path
from ..conftest import Poetry
PYPROJECT_CONTENT = """\
......@@ -51,11 +53,15 @@ def poetry(repo, tmp_dir):
with (Path(tmp_dir) / "pyproject.toml").open("w", encoding="utf-8") as f:
f.write(PYPROJECT_CONTENT)
p = Poetry.create(Path(tmp_dir))
p = Factory().create_poetry(Path(tmp_dir))
p.pool.remove_repository("pypi")
p.pool.add_repository(repo)
p._locker.write()
locker = Locker(p.locker.lock.path, p.locker._local_config)
locker.write()
p.set_locker(locker)
pool = Pool()
pool.add_repository(repo)
p.set_pool(pool)
yield p
......
......@@ -10,6 +10,7 @@ except ImportError:
from cleo import ApplicationTester
from poetry.console import Application as BaseApplication
from poetry.factory import Factory
from poetry.installation.noop_installer import NoopInstaller
from poetry.poetry import Poetry as BasePoetry
from poetry.packages import Locker as BaseLocker
......@@ -112,8 +113,10 @@ class Application(BaseApplication):
def reset_poetry(self):
poetry = self._poetry
self._poetry = Poetry.create(self._poetry.file.path.parent)
self._poetry._pool = poetry.pool
self._poetry = Factory().create_poetry(self._poetry.file.path.parent)
self._poetry.set_pool(poetry.pool)
self._poetry.set_config(poetry.config)
self._poetry.set_locker(poetry.locker)
class Locker(BaseLocker):
......@@ -189,14 +192,20 @@ def project_directory():
@pytest.fixture
def poetry(repo, project_directory, config_source):
p = Poetry.create(Path(__file__).parent.parent / "fixtures" / project_directory)
def poetry(repo, project_directory, config):
p = Factory().create_poetry(
Path(__file__).parent.parent / "fixtures" / project_directory
)
p.set_locker(Locker(p.locker.lock.path, p.locker._local_config))
with p.file.path.open(encoding="utf-8") as f:
content = f.read()
p.pool.remove_repository("pypi")
p.pool.add_repository(repo)
p.set_config(config)
pool = Pool()
pool.add_repository(repo)
p.set_pool(pool)
yield p
......
......@@ -2,8 +2,8 @@
from clikit.io import NullIO
from email.parser import Parser
from poetry.factory import Factory
from poetry.masonry.builders.builder import Builder
from poetry.poetry import Poetry
from poetry.utils._compat import Path
from poetry.utils.env import NullEnv
......@@ -13,7 +13,7 @@ def test_builder_find_excluded_files(mocker):
p.return_value = []
builder = Builder(
Poetry.create(Path(__file__).parent / "fixtures" / "complete"),
Factory().create_poetry(Path(__file__).parent / "fixtures" / "complete"),
NullEnv(),
NullIO(),
)
......@@ -26,7 +26,9 @@ def test_builder_find_case_sensitive_excluded_files(mocker):
p.return_value = []
builder = Builder(
Poetry.create(Path(__file__).parent / "fixtures" / "case_sensitive_exclusions"),
Factory().create_poetry(
Path(__file__).parent / "fixtures" / "case_sensitive_exclusions"
),
NullEnv(),
NullIO(),
)
......@@ -47,7 +49,7 @@ def test_builder_find_invalid_case_sensitive_excluded_files(mocker):
p.return_value = []
builder = Builder(
Poetry.create(
Factory().create_poetry(
Path(__file__).parent / "fixtures" / "invalid_case_sensitive_exclusions"
),
NullEnv(),
......@@ -59,7 +61,7 @@ def test_builder_find_invalid_case_sensitive_excluded_files(mocker):
def test_get_metadata_content():
builder = Builder(
Poetry.create(Path(__file__).parent / "fixtures" / "complete"),
Factory().create_poetry(Path(__file__).parent / "fixtures" / "complete"),
NullEnv(),
NullIO(),
)
......@@ -110,7 +112,7 @@ def test_get_metadata_content():
def test_metadata_homepage_default():
builder = Builder(
Poetry.create(Path(__file__).parent / "fixtures" / "simple_version"),
Factory().create_poetry(Path(__file__).parent / "fixtures" / "simple_version"),
NullEnv(),
NullIO(),
)
......@@ -122,7 +124,9 @@ def test_metadata_homepage_default():
def test_metadata_with_vcs_dependencies():
builder = Builder(
Poetry.create(Path(__file__).parent / "fixtures" / "with_vcs_dependency"),
Factory().create_poetry(
Path(__file__).parent / "fixtures" / "with_vcs_dependency"
),
NullEnv(),
NullIO(),
)
......@@ -136,7 +140,9 @@ def test_metadata_with_vcs_dependencies():
def test_metadata_with_url_dependencies():
builder = Builder(
Poetry.create(Path(__file__).parent / "fixtures" / "with_url_dependency"),
Factory().create_poetry(
Path(__file__).parent / "fixtures" / "with_url_dependency"
),
NullEnv(),
NullIO(),
)
......
......@@ -14,8 +14,8 @@ import tempfile
from clikit.io import NullIO
from poetry import __version__
from poetry.factory import Factory
from poetry.masonry.builders import CompleteBuilder
from poetry.poetry import Poetry
from poetry.utils._compat import Path
from poetry.utils._compat import decode
from poetry.utils.env import NullEnv
......@@ -45,7 +45,7 @@ def clear_samples_dist():
def test_wheel_c_extension():
module_path = fixtures_dir / "extended"
builder = CompleteBuilder(
Poetry.create(module_path), NullEnv(execute=True), NullIO()
Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
)
builder.build()
......@@ -102,7 +102,7 @@ $""".format(
def test_wheel_c_extension_src_layout():
module_path = fixtures_dir / "src_extended"
builder = CompleteBuilder(
Poetry.create(module_path), NullEnv(execute=True), NullIO()
Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
)
builder.build()
......@@ -155,7 +155,7 @@ $""".format(
def test_complete():
module_path = fixtures_dir / "complete"
builder = CompleteBuilder(
Poetry.create(module_path), NullEnv(execute=True), NullIO()
Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
)
builder.build()
......@@ -244,7 +244,7 @@ def test_complete_no_vcs():
shutil.copytree(module_path.as_posix(), temporary_dir.as_posix())
builder = CompleteBuilder(
Poetry.create(temporary_dir), NullEnv(execute=True), NullIO()
Factory().create_poetry(temporary_dir), NullEnv(execute=True), NullIO()
)
builder.build()
......@@ -341,7 +341,7 @@ My Package
def test_module_src():
module_path = fixtures_dir / "source_file"
builder = CompleteBuilder(
Poetry.create(module_path), NullEnv(execute=True), NullIO()
Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
)
builder.build()
......@@ -367,7 +367,7 @@ def test_module_src():
def test_package_src():
module_path = fixtures_dir / "source_package"
builder = CompleteBuilder(
Poetry.create(module_path), NullEnv(execute=True), NullIO()
Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
)
builder.build()
......@@ -413,7 +413,7 @@ def test_package_with_include(mocker):
/ "vcs_excluded.txt"
),
]
builder = CompleteBuilder(Poetry.create(module_path), NullEnv(), NullIO())
builder = CompleteBuilder(Factory().create_poetry(module_path), NullEnv(), NullIO())
builder.build()
sdist = fixtures_dir / "with-include" / "dist" / "with-include-1.2.3.tar.gz"
......
......@@ -3,8 +3,8 @@ from __future__ import unicode_literals
from clikit.io import NullIO
from poetry.factory import Factory
from poetry.masonry.builders import EditableBuilder
from poetry.poetry import Poetry
from poetry.utils._compat import Path
from poetry.utils.env import MockEnv
......@@ -18,7 +18,7 @@ def test_build_should_delegate_to_pip_for_non_pure_python_packages(tmp_dir, mock
env.site_packages.mkdir(parents=True)
module_path = fixtures_dir / "extended"
builder = EditableBuilder(Poetry.create(module_path), env, NullIO())
builder = EditableBuilder(Factory().create_poetry(module_path), env, NullIO())
builder.build()
expected = [["python", "-m", "pip", "install", "-e", str(module_path)]]
......@@ -34,7 +34,7 @@ def test_build_should_temporarily_remove_the_pyproject_file(tmp_dir, mocker):
env.site_packages.mkdir(parents=True)
module_path = fixtures_dir / "extended"
builder = EditableBuilder(Poetry.create(module_path), env, NullIO())
builder = EditableBuilder(Factory().create_poetry(module_path), env, NullIO())
builder.build()
expected = [["python", "-m", "pip", "install", "-e", str(module_path)]]
......
......@@ -8,11 +8,11 @@ from email.parser import Parser
from clikit.io import NullIO
from poetry.factory import Factory
from poetry.masonry.builders.sdist import SdistBuilder
from poetry.masonry.utils.package_include import PackageInclude
from poetry.packages import Package
from poetry.packages.vcs_dependency import VCSDependency
from poetry.poetry import Poetry
from poetry.utils._compat import Path
from poetry.utils._compat import to_str
from poetry.utils.env import NullEnv
......@@ -111,7 +111,7 @@ def test_convert_dependencies():
def test_make_setup():
poetry = Poetry.create(project("complete"))
poetry = Factory().create_poetry(project("complete"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
setup = builder.build_setup()
......@@ -144,7 +144,7 @@ def test_make_pkg_info(mocker):
get_metadata_content = mocker.patch(
"poetry.masonry.builders.builder.Builder.get_metadata_content"
)
poetry = Poetry.create(project("complete"))
poetry = Factory().create_poetry(project("complete"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
builder.build_pkg_info()
......@@ -153,7 +153,7 @@ def test_make_pkg_info(mocker):
def test_make_pkg_info_any_python():
poetry = Poetry.create(project("module1"))
poetry = Factory().create_poetry(project("module1"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
pkg_info = builder.build_pkg_info()
......@@ -164,7 +164,7 @@ def test_make_pkg_info_any_python():
def test_find_files_to_add():
poetry = Poetry.create(project("complete"))
poetry = Factory().create_poetry(project("complete"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
result = builder.find_files_to_add()
......@@ -184,7 +184,7 @@ def test_find_files_to_add():
def test_make_pkg_info_multi_constraints_dependency():
poetry = Poetry.create(
poetry = Factory().create_poetry(
Path(__file__).parent.parent.parent
/ "fixtures"
/ "project_with_multi_constraints_dependency"
......@@ -203,7 +203,7 @@ def test_make_pkg_info_multi_constraints_dependency():
def test_find_packages():
poetry = Poetry.create(project("complete"))
poetry = Factory().create_poetry(project("complete"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
......@@ -220,7 +220,7 @@ def test_find_packages():
"my_package.sub_pkg2": ["data2/*"],
}
poetry = Poetry.create(project("source_package"))
poetry = Factory().create_poetry(project("source_package"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
......@@ -235,7 +235,7 @@ def test_find_packages():
def test_package():
poetry = Poetry.create(project("complete"))
poetry = Factory().create_poetry(project("complete"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
builder.build()
......@@ -249,7 +249,7 @@ def test_package():
def test_module():
poetry = Poetry.create(project("module1"))
poetry = Factory().create_poetry(project("module1"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
builder.build()
......@@ -263,7 +263,7 @@ def test_module():
def test_prelease():
poetry = Poetry.create(project("prerelease"))
poetry = Factory().create_poetry(project("prerelease"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
builder.build()
......@@ -274,7 +274,7 @@ def test_prelease():
def test_with_c_extensions():
poetry = Poetry.create(project("extended"))
poetry = Factory().create_poetry(project("extended"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
builder.build()
......@@ -289,7 +289,7 @@ def test_with_c_extensions():
def test_with_c_extensions_src_layout():
poetry = Poetry.create(project("src_extended"))
poetry = Factory().create_poetry(project("src_extended"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
builder.build()
......@@ -304,7 +304,7 @@ def test_with_c_extensions_src_layout():
def test_with_src_module_file():
poetry = Poetry.create(project("source_file"))
poetry = Factory().create_poetry(project("source_file"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
......@@ -329,7 +329,7 @@ def test_with_src_module_file():
def test_with_src_module_dir():
poetry = Poetry.create(project("source_package"))
poetry = Factory().create_poetry(project("source_package"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
......@@ -372,7 +372,7 @@ def test_default_with_excluded_data(mocker):
.as_posix()
)
]
poetry = Poetry.create(project("default_with_excluded_data"))
poetry = Factory().create_poetry(project("default_with_excluded_data"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
......@@ -411,7 +411,7 @@ def test_default_with_excluded_data(mocker):
def test_proper_python_requires_if_two_digits_precision_version_specified():
poetry = Poetry.create(project("simple_version"))
poetry = Factory().create_poetry(project("simple_version"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
pkg_info = builder.build_pkg_info()
......@@ -422,7 +422,7 @@ def test_proper_python_requires_if_two_digits_precision_version_specified():
def test_proper_python_requires_if_three_digits_precision_version_specified():
poetry = Poetry.create(project("single_python"))
poetry = Factory().create_poetry(project("single_python"))
builder = SdistBuilder(poetry, NullEnv(), NullIO())
pkg_info = builder.build_pkg_info()
......
......@@ -5,8 +5,8 @@ import zipfile
from clikit.io import NullIO
from poetry.factory import Factory
from poetry.masonry.builders import WheelBuilder
from poetry.poetry import Poetry
from poetry.utils._compat import Path
from poetry.utils.env import NullEnv
......@@ -31,7 +31,7 @@ def clear_samples_dist():
def test_wheel_module():
module_path = fixtures_dir / "module1"
WheelBuilder.make(Poetry.create(str(module_path)), NullEnv(), NullIO())
WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
whl = module_path / "dist" / "module1-0.1-py2.py3-none-any.whl"
......@@ -43,7 +43,7 @@ def test_wheel_module():
def test_wheel_package():
module_path = fixtures_dir / "complete"
WheelBuilder.make(Poetry.create(str(module_path)), NullEnv(), NullIO())
WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl"
......@@ -55,7 +55,7 @@ def test_wheel_package():
def test_wheel_prerelease():
module_path = fixtures_dir / "prerelease"
WheelBuilder.make(Poetry.create(str(module_path)), NullEnv(), NullIO())
WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
whl = module_path / "dist" / "prerelease-0.1b1-py2.py3-none-any.whl"
......@@ -64,7 +64,7 @@ def test_wheel_prerelease():
def test_wheel_localversionlabel():
module_path = fixtures_dir / "localversionlabel"
WheelBuilder.make(Poetry.create(str(module_path)), NullEnv(), NullIO())
WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
local_version_string = "localversionlabel-0.1b1+gitbranch.buildno.1"
whl = module_path / "dist" / (local_version_string + "-py2.py3-none-any.whl")
......@@ -76,7 +76,7 @@ def test_wheel_localversionlabel():
def test_wheel_package_src():
module_path = fixtures_dir / "source_package"
WheelBuilder.make(Poetry.create(str(module_path)), NullEnv(), NullIO())
WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
whl = module_path / "dist" / "package_src-0.1-py2.py3-none-any.whl"
......@@ -89,7 +89,7 @@ def test_wheel_package_src():
def test_wheel_module_src():
module_path = fixtures_dir / "source_file"
WheelBuilder.make(Poetry.create(str(module_path)), NullEnv(), NullIO())
WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
whl = module_path / "dist" / "module_src-0.1-py2.py3-none-any.whl"
......@@ -101,7 +101,7 @@ def test_wheel_module_src():
def test_dist_info_file_permissions():
module_path = fixtures_dir / "complete"
WheelBuilder.make(Poetry.create(str(module_path)), NullEnv(), NullIO())
WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl"
......
import pytest
from poetry.factory import Factory
from poetry.io.null_io import NullIO
from poetry.masonry.publishing.publisher import Publisher
from poetry.poetry import Poetry
def test_publish_publishes_to_pypi_by_default(fixture_dir, mocker, config):
uploader_auth = mocker.patch("poetry.masonry.publishing.uploader.Uploader.auth")
uploader_upload = mocker.patch("poetry.masonry.publishing.uploader.Uploader.upload")
poetry = Poetry.create(fixture_dir("sample_project"))
poetry = Factory().create_poetry(fixture_dir("sample_project"))
poetry._config = config
poetry.config.merge(
{"http-basic": {"pypi": {"username": "foo", "password": "bar"}}}
......@@ -24,7 +24,7 @@ def test_publish_publishes_to_pypi_by_default(fixture_dir, mocker, config):
def test_publish_can_publish_to_given_repository(fixture_dir, mocker, config):
uploader_auth = mocker.patch("poetry.masonry.publishing.uploader.Uploader.auth")
uploader_upload = mocker.patch("poetry.masonry.publishing.uploader.Uploader.upload")
poetry = Poetry.create(fixture_dir("sample_project"))
poetry = Factory().create_poetry(fixture_dir("sample_project"))
poetry._config = config
poetry.config.merge(
{
......@@ -41,7 +41,7 @@ def test_publish_can_publish_to_given_repository(fixture_dir, mocker, config):
def test_publish_raises_error_for_undefined_repository(fixture_dir, mocker, config):
poetry = Poetry.create(fixture_dir("sample_project"))
poetry = Factory().create_poetry(fixture_dir("sample_project"))
poetry._config = config
poetry.config.merge(
{"http-basic": {"my-repo": {"username": "foo", "password": "bar"}}}
......@@ -55,7 +55,7 @@ def test_publish_raises_error_for_undefined_repository(fixture_dir, mocker, conf
def test_publish_uses_token_if_it_exists(fixture_dir, mocker, config):
uploader_auth = mocker.patch("poetry.masonry.publishing.uploader.Uploader.auth")
uploader_upload = mocker.patch("poetry.masonry.publishing.uploader.Uploader.upload")
poetry = Poetry.create(fixture_dir("sample_project"))
poetry = Factory().create_poetry(fixture_dir("sample_project"))
poetry._config = config
poetry.config.merge({"pypi-token": {"pypi": "my-token"}})
publisher = Publisher(poetry, NullIO())
......
import pytest
from poetry.factory import Factory
from poetry.io.null_io import NullIO
from poetry.masonry.publishing.uploader import UploadError
from poetry.masonry.publishing.uploader import Uploader
from poetry.poetry import Poetry
from poetry.utils._compat import Path
......@@ -16,7 +16,7 @@ def project(name):
def test_uploader_properly_handles_400_errors(http):
http.register_uri(http.POST, "https://foo.com", status=400, body="Bad request")
uploader = Uploader(Poetry.create(project("simple_project")), NullIO())
uploader = Uploader(Factory().create_poetry(project("simple_project")), NullIO())
with pytest.raises(UploadError) as e:
uploader.upload("https://foo.com")
......@@ -26,7 +26,7 @@ def test_uploader_properly_handles_400_errors(http):
def test_uploader_properly_handles_403_errors(http):
http.register_uri(http.POST, "https://foo.com", status=403, body="Unauthorized")
uploader = Uploader(Poetry.create(project("simple_project")), NullIO())
uploader = Uploader(Factory().create_poetry(project("simple_project")), NullIO())
with pytest.raises(UploadError) as e:
uploader.upload("https://foo.com")
......@@ -39,7 +39,7 @@ def test_uploader_registers_for_appropriate_400_errors(mocker, http):
http.register_uri(
http.POST, "https://foo.com", status=400, body="No package was ever registered"
)
uploader = Uploader(Poetry.create(project("simple_project")), NullIO())
uploader = Uploader(Factory().create_poetry(project("simple_project")), NullIO())
with pytest.raises(UploadError):
uploader.upload("https://foo.com")
......
......@@ -4,7 +4,8 @@ from __future__ import unicode_literals
import pytest
from poetry.poetry import Poetry
from poetry.io.null_io import NullIO
from poetry.factory import Factory
from poetry.utils._compat import PY2
from poetry.utils._compat import Path
from poetry.utils.toml_file import TomlFile
......@@ -13,8 +14,8 @@ from poetry.utils.toml_file import TomlFile
fixtures_dir = Path(__file__).parent / "fixtures"
def test_poetry():
poetry = Poetry.create(str(fixtures_dir / "sample_project"))
def test_create_poetry():
poetry = Factory().create_poetry(fixtures_dir / "sample_project")
package = poetry.package
......@@ -111,9 +112,9 @@ def test_poetry():
]
def test_poetry_with_packages_and_includes():
poetry = Poetry.create(
str(fixtures_dir.parent / "masonry" / "builders" / "fixtures" / "with-include")
def test_create_poetry_with_packages_and_includes():
poetry = Factory().create_poetry(
fixtures_dir.parent / "masonry" / "builders" / "fixtures" / "with-include"
)
package = poetry.package
......@@ -131,9 +132,9 @@ def test_poetry_with_packages_and_includes():
assert package.include == ["extra_dir/vcs_excluded.txt", "notes.txt"]
def test_poetry_with_multi_constraints_dependency():
poetry = Poetry.create(
str(fixtures_dir / "project_with_multi_constraints_dependency")
def test_create_poetry_with_multi_constraints_dependency():
poetry = Factory().create_poetry(
fixtures_dir / "project_with_multi_constraints_dependency"
)
package = poetry.package
......@@ -142,26 +143,26 @@ def test_poetry_with_multi_constraints_dependency():
def test_poetry_with_default_source():
poetry = Poetry.create(fixtures_dir / "with_default_source")
poetry = Factory().create_poetry(fixtures_dir / "with_default_source")
assert 1 == len(poetry.pool.repositories)
def test_poetry_with_two_default_sources():
with pytest.raises(ValueError) as e:
Poetry.create(fixtures_dir / "with_two_default_sources")
Factory().create_poetry(fixtures_dir / "with_two_default_sources")
assert "Only one repository can be the default" == str(e.value)
def test_check():
def test_validate():
complete = TomlFile(fixtures_dir / "complete.toml")
content = complete.read()["tool"]["poetry"]
assert Poetry.check(content) == {"errors": [], "warnings": []}
assert Factory.validate(content) == {"errors": [], "warnings": []}
def test_check_fails():
def test_validate_fails():
complete = TomlFile(fixtures_dir / "complete.toml")
content = complete.read()["tool"]["poetry"]
content["this key is not in the schema"] = ""
......@@ -177,12 +178,12 @@ def test_check_fails():
"('this key is not in the schema' was unexpected)"
)
assert Poetry.check(content) == {"errors": [expected], "warnings": []}
assert Factory.validate(content) == {"errors": [expected], "warnings": []}
def test_create_fails_on_invalid_configuration():
def test_create_poetry_fails_on_invalid_configuration():
with pytest.raises(RuntimeError) as e:
Poetry.create(
Factory().create_poetry(
Path(__file__).parent / "fixtures" / "invalid_pyproject" / "pyproject.toml"
)
......@@ -199,8 +200,8 @@ The Poetry configuration is invalid:
assert expected == str(e.value)
def test_poetry_with_local_config(fixture_dir):
poetry = Poetry.create(fixture_dir("with_local_config"))
def test_create_poetry_with_local_config(fixture_dir):
poetry = Factory().create_poetry(fixture_dir("with_local_config"))
assert not poetry.config.get("virtualenvs.in-project")
assert not poetry.config.get("virtualenvs.create")
......@@ -2,8 +2,8 @@ import sys
import pytest
from poetry.factory import Factory
from poetry.packages import Locker as BaseLocker
from poetry.poetry import Poetry
from poetry.repositories.auth import Auth
from poetry.repositories.legacy_repository import LegacyRepository
from poetry.utils._compat import Path
......@@ -40,7 +40,7 @@ def locker():
@pytest.fixture
def poetry(fixture_dir, locker):
p = Poetry.create(fixture_dir("sample_project"))
p = Factory().create_poetry(fixture_dir("sample_project"))
p._locker = locker
return p
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment