Commit e49f0934 by Arun Babu Neelicattu Committed by GitHub

Unify toml and pyproject file handling (#2982)

This change unifies TOML and pyproject.toml file handling to core
classes to ensure consistent handling of TOML files.

Reference: python-poetry/poetry-core#70
Reference: python-poetry/poetry-core#74
parent b1422f1f
from contextlib import contextmanager from contextlib import contextmanager
from typing import TYPE_CHECKING
from typing import Any from typing import Any
from tomlkit import document from tomlkit import document
from tomlkit import table from tomlkit import table
from poetry.utils.toml_file import TomlFile
from .config_source import ConfigSource from .config_source import ConfigSource
if TYPE_CHECKING:
from poetry.core.toml.file import TOMLFile # noqa
class FileConfigSource(ConfigSource): class FileConfigSource(ConfigSource):
def __init__(self, file, auth_config=False): # type: (TomlFile, bool) -> None def __init__(self, file, auth_config=False): # type: ("TOMLFile", bool) -> None
self._file = file self._file = file
self._auth_config = auth_config self._auth_config = auth_config
...@@ -19,7 +22,7 @@ class FileConfigSource(ConfigSource): ...@@ -19,7 +22,7 @@ class FileConfigSource(ConfigSource):
return str(self._file.path) return str(self._file.path)
@property @property
def file(self): # type: () -> TomlFile def file(self): # type: () -> "TOMLFile"
return self._file return self._file
def add_property(self, key, value): # type: (str, Any) -> None def add_property(self, key, value): # type: (str, Any) -> None
......
from poetry.core.pyproject.toml import PyProjectTOML
from poetry.factory import Factory from poetry.factory import Factory
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.toml_file import TomlFile
from .command import Command from .command import Command
...@@ -13,7 +13,7 @@ class CheckCommand(Command): ...@@ -13,7 +13,7 @@ class CheckCommand(Command):
def handle(self): def handle(self):
# Load poetry config and display errors, if any # Load poetry config and display errors, if any
poetry_file = Factory.locate(Path.cwd()) poetry_file = Factory.locate(Path.cwd())
config = TomlFile(str(poetry_file)).read()["tool"]["poetry"] config = PyProjectTOML(poetry_file).poetry_config
check_result = Factory.validate(config, strict=True) check_result = Factory.validate(config, strict=True)
if not check_result["errors"] and not check_result["warnings"]: if not check_result["errors"] and not check_result["warnings"]:
self.info("All set!") self.info("All set!")
......
...@@ -4,6 +4,7 @@ import re ...@@ -4,6 +4,7 @@ import re
from cleo import argument from cleo import argument
from cleo import option from cleo import option
from poetry.core.toml.file import TOMLFile
from poetry.factory import Factory from poetry.factory import Factory
from .command import Command from .command import Command
...@@ -71,17 +72,16 @@ To remove a repository (repo is a short alias for repositories): ...@@ -71,17 +72,16 @@ To remove a repository (repo is a short alias for repositories):
from poetry.locations import CONFIG_DIR from poetry.locations import CONFIG_DIR
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils._compat import basestring from poetry.utils._compat import basestring
from poetry.utils.toml_file import TomlFile
config = Factory.create_config(self.io) config = Factory.create_config(self.io)
config_file = TomlFile(Path(CONFIG_DIR) / "config.toml") config_file = TOMLFile(Path(CONFIG_DIR) / "config.toml")
try: try:
local_config_file = TomlFile(self.poetry.file.parent / "poetry.toml") local_config_file = TOMLFile(self.poetry.file.parent / "poetry.toml")
if local_config_file.exists(): if local_config_file.exists():
config.merge(local_config_file.read()) config.merge(local_config_file.read())
except RuntimeError: except RuntimeError:
local_config_file = TomlFile(Path.cwd() / "poetry.toml") local_config_file = TOMLFile(Path.cwd() / "poetry.toml")
if self.option("local"): if self.option("local"):
config.set_config_source(FileConfigSource(local_config_file)) config.set_config_source(FileConfigSource(local_config_file))
......
...@@ -7,7 +7,7 @@ from typing import Optional ...@@ -7,7 +7,7 @@ from typing import Optional
from clikit.api.io.io import IO from clikit.api.io.io import IO
from poetry.core.factory import Factory as BaseFactory from poetry.core.factory import Factory as BaseFactory
from poetry.core.utils.toml_file import TomlFile from poetry.core.toml.file import TOMLFile
from .config.config import Config from .config.config import Config
from .config.file_config_source import FileConfigSource from .config.file_config_source import FileConfigSource
...@@ -40,7 +40,7 @@ class Factory(BaseFactory): ...@@ -40,7 +40,7 @@ class Factory(BaseFactory):
config = self.create_config(io) config = self.create_config(io)
# Loading local configuration # Loading local configuration
local_config_file = TomlFile(base_poetry.file.parent / "poetry.toml") local_config_file = TOMLFile(base_poetry.file.parent / "poetry.toml")
if local_config_file.exists(): if local_config_file.exists():
if io.is_debug(): if io.is_debug():
io.write_line( io.write_line(
...@@ -102,7 +102,7 @@ class Factory(BaseFactory): ...@@ -102,7 +102,7 @@ class Factory(BaseFactory):
config = Config() config = Config()
# Load global config # Load global config
config_file = TomlFile(Path(CONFIG_DIR) / "config.toml") config_file = TOMLFile(Path(CONFIG_DIR) / "config.toml")
if config_file.exists(): if config_file.exists():
if io.is_debug(): if io.is_debug():
io.write_line( io.write_line(
...@@ -116,7 +116,7 @@ class Factory(BaseFactory): ...@@ -116,7 +116,7 @@ class Factory(BaseFactory):
config.set_config_source(FileConfigSource(config_file)) config.set_config_source(FileConfigSource(config_file))
# Load global auth config # Load global auth config
auth_config_file = TomlFile(Path(CONFIG_DIR) / "auth.toml") auth_config_file = TOMLFile(Path(CONFIG_DIR) / "auth.toml")
if auth_config_file.exists(): if auth_config_file.exists():
if io.is_debug(): if io.is_debug():
io.write_line( io.write_line(
......
...@@ -16,6 +16,7 @@ from poetry.core.factory import Factory ...@@ -16,6 +16,7 @@ from poetry.core.factory import Factory
from poetry.core.packages import Package from poetry.core.packages import Package
from poetry.core.packages import ProjectPackage from poetry.core.packages import ProjectPackage
from poetry.core.packages import dependency_from_pep_508 from poetry.core.packages import dependency_from_pep_508
from poetry.core.pyproject.toml import PyProjectTOML
from poetry.core.utils._compat import PY35 from poetry.core.utils._compat import PY35
from poetry.core.utils._compat import Path from poetry.core.utils._compat import Path
from poetry.core.utils.helpers import parse_requires from poetry.core.utils.helpers import parse_requires
...@@ -25,7 +26,6 @@ from poetry.utils.env import EnvCommandError ...@@ -25,7 +26,6 @@ from poetry.utils.env import EnvCommandError
from poetry.utils.env import EnvManager from poetry.utils.env import EnvManager
from poetry.utils.env import VirtualEnv from poetry.utils.env import VirtualEnv
from poetry.utils.setup_reader import SetupReader from poetry.utils.setup_reader import SetupReader
from poetry.utils.toml_file import TomlFile
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -410,21 +410,10 @@ class PackageInfo: ...@@ -410,21 +410,10 @@ class PackageInfo:
@staticmethod @staticmethod
def _get_poetry_package(path): # type: (Path) -> Optional[ProjectPackage] def _get_poetry_package(path): # type: (Path) -> Optional[ProjectPackage]
pyproject = path.joinpath("pyproject.toml")
try:
# Note: we ignore any setup.py file at this step # Note: we ignore any setup.py file at this step
if pyproject.exists():
# TODO: add support for handling non-poetry PEP-517 builds # TODO: add support for handling non-poetry PEP-517 builds
pyproject = TomlFile(pyproject) if PyProjectTOML(path.joinpath("pyproject.toml")).is_poetry_project():
pyproject_content = pyproject.read()
supports_poetry = (
"tool" in pyproject_content
and "poetry" in pyproject_content["tool"]
)
if supports_poetry:
return Factory().create_poetry(path).package return Factory().create_poetry(path).package
except RuntimeError:
pass
@classmethod @classmethod
def _pep517_metadata(cls, path): # type (Path) -> PackageInfo def _pep517_metadata(cls, path): # type (Path) -> PackageInfo
......
...@@ -11,6 +11,7 @@ from subprocess import CalledProcessError ...@@ -11,6 +11,7 @@ from subprocess import CalledProcessError
from poetry.core.packages.file_dependency import FileDependency from poetry.core.packages.file_dependency import FileDependency
from poetry.core.packages.utils.link import Link from poetry.core.packages.utils.link import Link
from poetry.core.pyproject.toml import PyProjectTOML
from poetry.io.null_io import NullIO from poetry.io.null_io import NullIO
from poetry.utils._compat import PY2 from poetry.utils._compat import PY2
from poetry.utils._compat import WINDOWS from poetry.utils._compat import WINDOWS
...@@ -463,7 +464,6 @@ class Executor(object): ...@@ -463,7 +464,6 @@ class Executor(object):
def _install_directory(self, operation): def _install_directory(self, operation):
from poetry.factory import Factory from poetry.factory import Factory
from poetry.utils.toml_file import TomlFile
package = operation.package package = operation.package
operation_message = self.get_operation_message(operation) operation_message = self.get_operation_message(operation)
...@@ -480,28 +480,18 @@ class Executor(object): ...@@ -480,28 +480,18 @@ class Executor(object):
args = ["install", "--no-deps", "-U"] args = ["install", "--no-deps", "-U"]
pyproject = TomlFile(os.path.join(req, "pyproject.toml")) pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml"))
has_poetry = False if pyproject.is_poetry_project():
has_build_system = False
if pyproject.exists():
pyproject_content = pyproject.read()
has_poetry = (
"tool" in pyproject_content and "poetry" in pyproject_content["tool"]
)
# Even if there is a build system specified # Even if there is a build system specified
# some versions of pip (< 19.0.0) don't understand it # some versions of pip (< 19.0.0) don't understand it
# so we need to check the version of pip to know # so we need to check the version of pip to know
# if we can rely on the build system # if we can rely on the build system
pip_version = self._env.pip_version legacy_pip = self._env.pip_version < self._env.pip_version.__class__(
pip_version_with_build_system_support = pip_version.__class__(19, 0, 0) 19, 0, 0
has_build_system = (
"build-system" in pyproject_content
and pip_version >= pip_version_with_build_system_support
) )
package_poetry = Factory().create_poetry(pyproject.file.path.parent)
if has_poetry:
package_poetry = Factory().create_poetry(pyproject.parent)
if package.develop and not package_poetry.package.build_script: if package.develop and not package_poetry.package.build_script:
from poetry.masonry.builders.editable import EditableBuilder from poetry.masonry.builders.editable import EditableBuilder
...@@ -512,7 +502,7 @@ class Executor(object): ...@@ -512,7 +502,7 @@ class Executor(object):
builder.build() builder.build()
return 0 return 0
elif not has_build_system or package_poetry.package.build_script: elif legacy_pip or package_poetry.package.build_script:
from poetry.core.masonry.builders.sdist import SdistBuilder from poetry.core.masonry.builders.sdist import SdistBuilder
# We need to rely on creating a temporary setup.py # We need to rely on creating a temporary setup.py
......
...@@ -5,6 +5,7 @@ from subprocess import CalledProcessError ...@@ -5,6 +5,7 @@ from subprocess import CalledProcessError
from clikit.api.io import IO from clikit.api.io import IO
from poetry.core.pyproject.toml import PyProjectTOML
from poetry.repositories.pool import Pool from poetry.repositories.pool import Pool
from poetry.utils._compat import encode from poetry.utils._compat import encode
from poetry.utils.env import Env from poetry.utils.env import Env
...@@ -181,8 +182,6 @@ class PipInstaller(BaseInstaller): ...@@ -181,8 +182,6 @@ class PipInstaller(BaseInstaller):
def install_directory(self, package): def install_directory(self, package):
from poetry.factory import Factory from poetry.factory import Factory
from poetry.io.null_io import NullIO from poetry.io.null_io import NullIO
from poetry.masonry.builders.editable import EditableBuilder
from poetry.utils.toml_file import TomlFile
if package.root_dir: if package.root_dir:
req = (package.root_dir / package.source_url).as_posix() req = (package.root_dir / package.source_url).as_posix()
...@@ -191,37 +190,29 @@ class PipInstaller(BaseInstaller): ...@@ -191,37 +190,29 @@ class PipInstaller(BaseInstaller):
args = ["install", "--no-deps", "-U"] args = ["install", "--no-deps", "-U"]
pyproject = TomlFile(os.path.join(req, "pyproject.toml")) pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml"))
has_poetry = False if pyproject.is_poetry_project():
has_build_system = False
if pyproject.exists():
pyproject_content = pyproject.read()
has_poetry = (
"tool" in pyproject_content and "poetry" in pyproject_content["tool"]
)
# Even if there is a build system specified # Even if there is a build system specified
# some versions of pip (< 19.0.0) don't understand it # some versions of pip (< 19.0.0) don't understand it
# so we need to check the version of pip to know # so we need to check the version of pip to know
# if we can rely on the build system # if we can rely on the build system
pip_version = self._env.pip_version legacy_pip = self._env.pip_version < self._env.pip_version.__class__(
pip_version_with_build_system_support = pip_version.__class__(19, 0, 0) 19, 0, 0
has_build_system = (
"build-system" in pyproject_content
and pip_version >= pip_version_with_build_system_support
) )
package_poetry = Factory().create_poetry(pyproject.file.path.parent)
if has_poetry:
package_poetry = Factory().create_poetry(pyproject.parent)
if package.develop and not package_poetry.package.build_script: if package.develop and not package_poetry.package.build_script:
from poetry.masonry.builders.editable import EditableBuilder
# This is a Poetry package in editable mode # This is a Poetry package in editable mode
# we can use the EditableBuilder without going through pip # we can use the EditableBuilder without going through pip
# to install it, unless it has a build script. # to install it, unless it has a build script.
builder = EditableBuilder(package_poetry, self._env, NullIO()) builder = EditableBuilder(package_poetry, self._env, NullIO())
builder.build() builder.build()
return return 0
elif not has_build_system or package_poetry.package.build_script: elif legacy_pip or package_poetry.package.build_script:
from poetry.core.masonry.builders.sdist import SdistBuilder from poetry.core.masonry.builders.sdist import SdistBuilder
# We need to rely on creating a temporary setup.py # We need to rely on creating a temporary setup.py
...@@ -236,7 +227,7 @@ class PipInstaller(BaseInstaller): ...@@ -236,7 +227,7 @@ class PipInstaller(BaseInstaller):
args.append(req) args.append(req)
return self.run(*args) return self.run_pip(*args)
if package.develop: if package.develop:
args.append("-e") args.append("-e")
......
...@@ -19,10 +19,10 @@ from poetry.core.packages.package import Dependency ...@@ -19,10 +19,10 @@ from poetry.core.packages.package import Dependency
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
from poetry.core.semver import parse_constraint from poetry.core.semver import parse_constraint
from poetry.core.semver.version import Version from poetry.core.semver.version import Version
from poetry.core.toml.file import TOMLFile
from poetry.core.version.markers import parse_marker from poetry.core.version.markers import parse_marker
from poetry.utils._compat import OrderedDict from poetry.utils._compat import OrderedDict
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.toml_file import TomlFile
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -35,13 +35,13 @@ class Locker(object): ...@@ -35,13 +35,13 @@ class Locker(object):
_relevant_keys = ["dependencies", "dev-dependencies", "source", "extras"] _relevant_keys = ["dependencies", "dev-dependencies", "source", "extras"]
def __init__(self, lock, local_config): # type: (Path, dict) -> None def __init__(self, lock, local_config): # type: (Path, dict) -> None
self._lock = TomlFile(lock) self._lock = TOMLFile(lock)
self._local_config = local_config self._local_config = local_config
self._lock_data = None self._lock_data = None
self._content_hash = self._get_content_hash() self._content_hash = self._get_content_hash()
@property @property
def lock(self): # type: () -> TomlFile def lock(self): # type: () -> TOMLFile
return self._lock return self._lock
@property @property
......
...@@ -29,6 +29,7 @@ from packaging.tags import sys_tags ...@@ -29,6 +29,7 @@ from packaging.tags import sys_tags
from poetry.core.semver import parse_constraint from poetry.core.semver import parse_constraint
from poetry.core.semver.version import Version from poetry.core.semver.version import Version
from poetry.core.toml.file import TOMLFile
from poetry.core.version.markers import BaseMarker from poetry.core.version.markers import BaseMarker
from poetry.locations import CACHE_DIR from poetry.locations import CACHE_DIR
from poetry.poetry import Poetry from poetry.poetry import Poetry
...@@ -38,7 +39,6 @@ from poetry.utils._compat import decode ...@@ -38,7 +39,6 @@ from poetry.utils._compat import decode
from poetry.utils._compat import encode from poetry.utils._compat import encode
from poetry.utils._compat import list_to_shell_command from poetry.utils._compat import list_to_shell_command
from poetry.utils._compat import subprocess from poetry.utils._compat import subprocess
from poetry.utils.toml_file import TomlFile
GET_ENVIRONMENT_INFO = """\ GET_ENVIRONMENT_INFO = """\
...@@ -201,7 +201,7 @@ class EnvManager(object): ...@@ -201,7 +201,7 @@ class EnvManager(object):
cwd = self._poetry.file.parent cwd = self._poetry.file.parent
envs_file = TomlFile(venv_path / self.ENVS_FILE) envs_file = TOMLFile(venv_path / self.ENVS_FILE)
try: try:
python_version = Version.parse(python) python_version = Version.parse(python)
...@@ -299,7 +299,7 @@ class EnvManager(object): ...@@ -299,7 +299,7 @@ class EnvManager(object):
name = self._poetry.package.name name = self._poetry.package.name
name = self.generate_env_name(name, str(self._poetry.file.parent)) name = self.generate_env_name(name, str(self._poetry.file.parent))
envs_file = TomlFile(venv_path / self.ENVS_FILE) envs_file = TOMLFile(venv_path / self.ENVS_FILE)
if envs_file.exists(): if envs_file.exists():
envs = envs_file.read() envs = envs_file.read()
env = envs.get(name) env = envs.get(name)
...@@ -326,7 +326,7 @@ class EnvManager(object): ...@@ -326,7 +326,7 @@ class EnvManager(object):
venv_path = Path(venv_path) venv_path = Path(venv_path)
cwd = self._poetry.file.parent cwd = self._poetry.file.parent
envs_file = TomlFile(venv_path / self.ENVS_FILE) envs_file = TOMLFile(venv_path / self.ENVS_FILE)
env = None env = None
base_env_name = self.generate_env_name(self._poetry.package.name, str(cwd)) base_env_name = self.generate_env_name(self._poetry.package.name, str(cwd))
if envs_file.exists(): if envs_file.exists():
...@@ -415,7 +415,7 @@ class EnvManager(object): ...@@ -415,7 +415,7 @@ class EnvManager(object):
venv_path = Path(venv_path) venv_path = Path(venv_path)
cwd = self._poetry.file.parent cwd = self._poetry.file.parent
envs_file = TomlFile(venv_path / self.ENVS_FILE) envs_file = TOMLFile(venv_path / self.ENVS_FILE)
base_env_name = self.generate_env_name(self._poetry.package.name, str(cwd)) base_env_name = self.generate_env_name(self._poetry.package.name, str(cwd))
if python.startswith(base_env_name): if python.startswith(base_env_name):
......
# -*- coding: utf-8 -*-
from typing import Union
from tomlkit.toml_file import TOMLFile as BaseTOMLFile
from ._compat import Path
class TomlFile(BaseTOMLFile):
def __init__(self, path): # type: (Union[str, Path]) -> None
super(TomlFile, self).__init__(str(path))
self._path_ = Path(path)
@property
def path(self): # type: () -> Path
return self._path_
def exists(self): # type: () -> bool
return self._path_.exists()
def __getattr__(self, item):
return getattr(self._path_, item)
def __str__(self):
return str(self._path)
import pytest import pytest
import tomlkit import tomlkit
from poetry.utils.toml_file import TomlFile from poetry.core.toml.file import TOMLFile
@pytest.fixture @pytest.fixture
def venv_activate_37(venv_cache, venv_name): def venv_activate_37(venv_cache, venv_name):
envs_file = TomlFile(venv_cache / "envs.toml") envs_file = TOMLFile(venv_cache / "envs.toml")
doc = tomlkit.document() doc = tomlkit.document()
doc[venv_name] = {"minor": "3.7", "patch": "3.7.0"} doc[venv_name] = {"minor": "3.7", "patch": "3.7.0"}
envs_file.write(doc) envs_file.write(doc)
......
...@@ -4,9 +4,9 @@ import pytest ...@@ -4,9 +4,9 @@ import pytest
import tomlkit import tomlkit
from poetry.core.semver import Version from poetry.core.semver import Version
from poetry.core.toml.file import TOMLFile
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.env import MockEnv from poetry.utils.env import MockEnv
from poetry.utils.toml_file import TomlFile
from tests.console.commands.env.helpers import build_venv from tests.console.commands.env.helpers import build_venv
from tests.console.commands.env.helpers import check_output_wrapper from tests.console.commands.env.helpers import check_output_wrapper
...@@ -52,7 +52,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( ...@@ -52,7 +52,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file(
venv_py37 = venv_cache / "{}-py3.7".format(venv_name) venv_py37 = venv_cache / "{}-py3.7".format(venv_name)
mock_build_env.assert_called_with(venv_py37, executable="python3.7") mock_build_env.assert_called_with(venv_py37, executable="python3.7")
envs_file = TomlFile(venv_cache / "envs.toml") envs_file = TOMLFile(venv_cache / "envs.toml")
assert envs_file.exists() assert envs_file.exists()
envs = envs_file.read() envs = envs_file.read()
assert envs[venv_name]["minor"] == "3.7" assert envs[venv_name]["minor"] == "3.7"
...@@ -78,7 +78,7 @@ def test_get_prefers_explicitly_activated_virtualenvs_over_env_var( ...@@ -78,7 +78,7 @@ def test_get_prefers_explicitly_activated_virtualenvs_over_env_var(
venv_dir = venv_cache / "{}-py{}".format(venv_name, python_minor) venv_dir = venv_cache / "{}-py{}".format(venv_name, python_minor)
venv_dir.mkdir(parents=True, exist_ok=True) venv_dir.mkdir(parents=True, exist_ok=True)
envs_file = TomlFile(venv_cache / "envs.toml") envs_file = TOMLFile(venv_cache / "envs.toml")
doc = tomlkit.document() doc = tomlkit.document()
doc[venv_name] = {"minor": python_minor, "patch": python_patch} doc[venv_name] = {"minor": python_minor, "patch": python_patch}
envs_file.write(doc) envs_file.write(doc)
......
...@@ -7,6 +7,7 @@ from poetry.core.masonry.utils.helpers import escape_version ...@@ -7,6 +7,7 @@ from poetry.core.masonry.utils.helpers import escape_version
from poetry.core.packages import Dependency from poetry.core.packages import Dependency
from poetry.core.packages import Link from poetry.core.packages import Link
from poetry.core.packages import Package from poetry.core.packages import Package
from poetry.core.toml.file import TOMLFile
from poetry.core.vcs.git import ParsedUrl from poetry.core.vcs.git import ParsedUrl
from poetry.factory import Factory from poetry.factory import Factory
from poetry.installation.executor import Executor from poetry.installation.executor import Executor
...@@ -17,7 +18,6 @@ from poetry.utils._compat import PY2 ...@@ -17,7 +18,6 @@ from poetry.utils._compat import PY2
from poetry.utils._compat import WINDOWS from poetry.utils._compat import WINDOWS
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils._compat import urlparse from poetry.utils._compat import urlparse
from poetry.utils.toml_file import TomlFile
FIXTURE_PATH = Path(__file__).parent / "fixtures" FIXTURE_PATH = Path(__file__).parent / "fixtures"
...@@ -153,7 +153,7 @@ class TestApplication(Application): ...@@ -153,7 +153,7 @@ class TestApplication(Application):
class TestLocker(Locker): class TestLocker(Locker):
def __init__(self, lock, local_config): # noqa def __init__(self, lock, local_config): # noqa
self._lock = TomlFile(lock) self._lock = TOMLFile(lock)
self._local_config = local_config self._local_config = local_config
self._lock_data = None self._lock_data = None
self._content_hash = self._get_content_hash() self._content_hash = self._get_content_hash()
......
...@@ -8,6 +8,7 @@ import pytest ...@@ -8,6 +8,7 @@ import pytest
from clikit.io import NullIO from clikit.io import NullIO
from poetry.core.packages import ProjectPackage from poetry.core.packages import ProjectPackage
from poetry.core.toml.file import TOMLFile
from poetry.factory import Factory from poetry.factory import Factory
from poetry.installation import Installer as BaseInstaller from poetry.installation import Installer as BaseInstaller
from poetry.installation.executor import Executor as BaseExecutor from poetry.installation.executor import Executor as BaseExecutor
...@@ -20,7 +21,6 @@ from poetry.utils._compat import PY2 ...@@ -20,7 +21,6 @@ from poetry.utils._compat import PY2
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.env import MockEnv from poetry.utils.env import MockEnv
from poetry.utils.env import NullEnv from poetry.utils.env import NullEnv
from poetry.utils.toml_file import TomlFile
from tests.helpers import get_dependency from tests.helpers import get_dependency
from tests.helpers import get_package from tests.helpers import get_package
from tests.repositories.test_legacy_repository import ( from tests.repositories.test_legacy_repository import (
...@@ -81,7 +81,7 @@ class CustomInstalledRepository(InstalledRepository): ...@@ -81,7 +81,7 @@ class CustomInstalledRepository(InstalledRepository):
class Locker(BaseLocker): class Locker(BaseLocker):
def __init__(self): def __init__(self):
self._lock = TomlFile(Path.cwd().joinpath("poetry.lock")) self._lock = TOMLFile(Path.cwd().joinpath("poetry.lock"))
self._written_data = None self._written_data = None
self._locked = False self._locked = False
self._content_hash = self._get_content_hash() self._content_hash = self._get_content_hash()
...@@ -91,7 +91,7 @@ class Locker(BaseLocker): ...@@ -91,7 +91,7 @@ class Locker(BaseLocker):
return self._written_data return self._written_data
def set_lock_path(self, lock): def set_lock_path(self, lock):
self._lock = TomlFile(Path(lock).joinpath("poetry.lock")) self._lock = TOMLFile(Path(lock).joinpath("poetry.lock"))
return self return self
...@@ -184,7 +184,7 @@ def installer(package, pool, locker, env, installed, config): ...@@ -184,7 +184,7 @@ def installer(package, pool, locker, env, installed, config):
def fixture(name): def fixture(name):
file = TomlFile(Path(__file__).parent / "fixtures" / "{}.test".format(name)) file = TOMLFile(Path(__file__).parent / "fixtures" / "{}.test".format(name))
return json.loads(json.dumps(file.read())) return json.loads(json.dumps(file.read()))
......
...@@ -7,6 +7,7 @@ import pytest ...@@ -7,6 +7,7 @@ import pytest
from clikit.io import NullIO from clikit.io import NullIO
from poetry.core.packages import ProjectPackage from poetry.core.packages import ProjectPackage
from poetry.core.toml.file import TOMLFile
from poetry.factory import Factory from poetry.factory import Factory
from poetry.installation import Installer as BaseInstaller from poetry.installation import Installer as BaseInstaller
from poetry.installation.noop_installer import NoopInstaller from poetry.installation.noop_installer import NoopInstaller
...@@ -18,7 +19,6 @@ from poetry.utils._compat import PY2 ...@@ -18,7 +19,6 @@ from poetry.utils._compat import PY2
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.env import MockEnv from poetry.utils.env import MockEnv
from poetry.utils.env import NullEnv from poetry.utils.env import NullEnv
from poetry.utils.toml_file import TomlFile
from tests.helpers import get_dependency from tests.helpers import get_dependency
from tests.helpers import get_package from tests.helpers import get_package
from tests.repositories.test_legacy_repository import ( from tests.repositories.test_legacy_repository import (
...@@ -43,7 +43,7 @@ class CustomInstalledRepository(InstalledRepository): ...@@ -43,7 +43,7 @@ class CustomInstalledRepository(InstalledRepository):
class Locker(BaseLocker): class Locker(BaseLocker):
def __init__(self): def __init__(self):
self._lock = TomlFile(Path.cwd().joinpath("poetry.lock")) self._lock = TOMLFile(Path.cwd().joinpath("poetry.lock"))
self._written_data = None self._written_data = None
self._locked = False self._locked = False
self._content_hash = self._get_content_hash() self._content_hash = self._get_content_hash()
...@@ -53,7 +53,7 @@ class Locker(BaseLocker): ...@@ -53,7 +53,7 @@ class Locker(BaseLocker):
return self._written_data return self._written_data
def set_lock_path(self, lock): def set_lock_path(self, lock):
self._lock = TomlFile(Path(lock).joinpath("poetry.lock")) self._lock = TOMLFile(Path(lock).joinpath("poetry.lock"))
return self return self
...@@ -134,7 +134,7 @@ def installer(package, pool, locker, env, installed, config): ...@@ -134,7 +134,7 @@ def installer(package, pool, locker, env, installed, config):
def fixture(name): def fixture(name):
file = TomlFile(Path(__file__).parent / "fixtures" / "{}.test".format(name)) file = TOMLFile(Path(__file__).parent / "fixtures" / "{}.test".format(name))
return file.read() return file.read()
......
...@@ -4,10 +4,10 @@ from __future__ import unicode_literals ...@@ -4,10 +4,10 @@ from __future__ import unicode_literals
import pytest import pytest
from poetry.core.toml.file import TOMLFile
from poetry.factory import Factory from poetry.factory import Factory
from poetry.utils._compat import PY2 from poetry.utils._compat import PY2
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.toml_file import TomlFile
fixtures_dir = Path(__file__).parent / "fixtures" fixtures_dir = Path(__file__).parent / "fixtures"
...@@ -158,14 +158,14 @@ def test_poetry_with_two_default_sources(): ...@@ -158,14 +158,14 @@ def test_poetry_with_two_default_sources():
def test_validate(): def test_validate():
complete = TomlFile(fixtures_dir / "complete.toml") complete = TOMLFile(fixtures_dir / "complete.toml")
content = complete.read()["tool"]["poetry"] content = complete.read()["tool"]["poetry"]
assert Factory.validate(content) == {"errors": [], "warnings": []} assert Factory.validate(content) == {"errors": [], "warnings": []}
def test_validate_fails(): def test_validate_fails():
complete = TomlFile(fixtures_dir / "complete.toml") complete = TOMLFile(fixtures_dir / "complete.toml")
content = complete.read()["tool"]["poetry"] content = complete.read()["tool"]["poetry"]
content["this key is not in the schema"] = "" content["this key is not in the schema"] = ""
......
# This is a TOML document.
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00 # First class dates
[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
# Indentation (tabs and/or spaces) is allowed but not required
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
[clients]
data = [ ["gamma", "delta"], [1, 2] ]
# Line breaks are OK when inside arrays
hosts = [
"alpha",
"omega"
]
str_multiline = """
Roses are red
Violets are blue"""
str_quoted = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
str2 = """
The quick brown \
fox jumps over \
the lazy dog."""
key3 = """\
The quick brown \
fox jumps over \
the lazy dog.\
"""
# What you see is what you get.
winpath = 'C:\Users\nodejs\templates'
winpath2 = '\\ServerX\admin$\system32\'
quoted = 'Tom "Dubs" Preston-Werner'
regex = '<\i\c*\s*>'
regex2 = '''I [dw]on't need \d{2} apples'''
lines = '''
The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
'''
[[fruit]]
name = "apple"
[fruit.physical]
color = "red"
shape = "round"
[[fruit.variety]]
name = "red delicious"
[[fruit.variety]]
name = "granny smith"
[[fruit]]
name = "banana"
[[fruit.variety]]
name = "plantain"
points = [ { x = 1, y = 2, z = 3 }, # This value is so special to me
{ x = 7, y = 8, z = 9 },
{ x = 2, y = 4, z = 8 } ]
...@@ -11,6 +11,7 @@ import tomlkit ...@@ -11,6 +11,7 @@ import tomlkit
from clikit.io import NullIO from clikit.io import NullIO
from poetry.core.semver import Version from poetry.core.semver import Version
from poetry.core.toml.file import TOMLFile
from poetry.factory import Factory from poetry.factory import Factory
from poetry.utils._compat import PY2 from poetry.utils._compat import PY2
from poetry.utils._compat import Path from poetry.utils._compat import Path
...@@ -19,7 +20,6 @@ from poetry.utils.env import EnvManager ...@@ -19,7 +20,6 @@ from poetry.utils.env import EnvManager
from poetry.utils.env import NoCompatiblePythonVersionFound from poetry.utils.env import NoCompatiblePythonVersionFound
from poetry.utils.env import SystemEnv from poetry.utils.env import SystemEnv
from poetry.utils.env import VirtualEnv from poetry.utils.env import VirtualEnv
from poetry.utils.toml_file import TomlFile
MINIMAL_SCRIPT = """\ MINIMAL_SCRIPT = """\
...@@ -138,7 +138,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( ...@@ -138,7 +138,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file(
Path(tmp_dir) / "{}-py3.7".format(venv_name), executable="python3.7" Path(tmp_dir) / "{}-py3.7".format(venv_name), executable="python3.7"
) )
envs_file = TomlFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
assert envs_file.exists() assert envs_file.exists()
envs = envs_file.read() envs = envs_file.read()
assert envs[venv_name]["minor"] == "3.7" assert envs[venv_name]["minor"] == "3.7"
...@@ -174,7 +174,7 @@ def test_activate_activates_existing_virtualenv_no_envs_file( ...@@ -174,7 +174,7 @@ def test_activate_activates_existing_virtualenv_no_envs_file(
m.assert_not_called() m.assert_not_called()
envs_file = TomlFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
assert envs_file.exists() assert envs_file.exists()
envs = envs_file.read() envs = envs_file.read()
assert envs[venv_name]["minor"] == "3.7" assert envs[venv_name]["minor"] == "3.7"
...@@ -192,7 +192,7 @@ def test_activate_activates_same_virtualenv_with_envs_file( ...@@ -192,7 +192,7 @@ def test_activate_activates_same_virtualenv_with_envs_file(
venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent)) venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
envs_file = TomlFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
doc = tomlkit.document() doc = tomlkit.document()
doc[venv_name] = {"minor": "3.7", "patch": "3.7.1"} doc[venv_name] = {"minor": "3.7", "patch": "3.7.1"}
envs_file.write(doc) envs_file.write(doc)
...@@ -231,7 +231,7 @@ def test_activate_activates_different_virtualenv_with_envs_file( ...@@ -231,7 +231,7 @@ def test_activate_activates_different_virtualenv_with_envs_file(
del os.environ["VIRTUAL_ENV"] del os.environ["VIRTUAL_ENV"]
venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent)) venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
envs_file = TomlFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
doc = tomlkit.document() doc = tomlkit.document()
doc[venv_name] = {"minor": "3.7", "patch": "3.7.1"} doc[venv_name] = {"minor": "3.7", "patch": "3.7.1"}
envs_file.write(doc) envs_file.write(doc)
...@@ -272,7 +272,7 @@ def test_activate_activates_recreates_for_different_patch( ...@@ -272,7 +272,7 @@ def test_activate_activates_recreates_for_different_patch(
del os.environ["VIRTUAL_ENV"] del os.environ["VIRTUAL_ENV"]
venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent)) venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
envs_file = TomlFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
doc = tomlkit.document() doc = tomlkit.document()
doc[venv_name] = {"minor": "3.7", "patch": "3.7.0"} doc[venv_name] = {"minor": "3.7", "patch": "3.7.0"}
envs_file.write(doc) envs_file.write(doc)
...@@ -326,7 +326,7 @@ def test_activate_does_not_recreate_when_switching_minor( ...@@ -326,7 +326,7 @@ def test_activate_does_not_recreate_when_switching_minor(
del os.environ["VIRTUAL_ENV"] del os.environ["VIRTUAL_ENV"]
venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent)) venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
envs_file = TomlFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
doc = tomlkit.document() doc = tomlkit.document()
doc[venv_name] = {"minor": "3.7", "patch": "3.7.0"} doc[venv_name] = {"minor": "3.7", "patch": "3.7.0"}
envs_file.write(doc) envs_file.write(doc)
...@@ -410,7 +410,7 @@ def test_deactivate_activated(tmp_dir, manager, poetry, config, mocker): ...@@ -410,7 +410,7 @@ def test_deactivate_activated(tmp_dir, manager, poetry, config, mocker):
/ "{}-py{}.{}".format(venv_name, other_version.major, other_version.minor) / "{}-py{}.{}".format(venv_name, other_version.major, other_version.minor)
).mkdir() ).mkdir()
envs_file = TomlFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
doc = tomlkit.document() doc = tomlkit.document()
doc[venv_name] = { doc[venv_name] = {
"minor": "{}.{}".format(other_version.major, other_version.minor), "minor": "{}.{}".format(other_version.major, other_version.minor),
...@@ -447,7 +447,7 @@ def test_get_prefers_explicitly_activated_virtualenvs_over_env_var( ...@@ -447,7 +447,7 @@ def test_get_prefers_explicitly_activated_virtualenvs_over_env_var(
config.merge({"virtualenvs": {"path": str(tmp_dir)}}) config.merge({"virtualenvs": {"path": str(tmp_dir)}})
(Path(tmp_dir) / "{}-py3.7".format(venv_name)).mkdir() (Path(tmp_dir) / "{}-py3.7".format(venv_name)).mkdir()
envs_file = TomlFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
doc = tomlkit.document() doc = tomlkit.document()
doc[venv_name] = {"minor": "3.7", "patch": "3.7.0"} doc[venv_name] = {"minor": "3.7", "patch": "3.7.0"}
envs_file.write(doc) envs_file.write(doc)
...@@ -529,7 +529,7 @@ def test_remove_also_deactivates(tmp_dir, manager, poetry, config, mocker): ...@@ -529,7 +529,7 @@ def test_remove_also_deactivates(tmp_dir, manager, poetry, config, mocker):
side_effect=check_output_wrapper(Version.parse("3.6.6")), side_effect=check_output_wrapper(Version.parse("3.6.6")),
) )
envs_file = TomlFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
doc = tomlkit.document() doc = tomlkit.document()
doc[venv_name] = {"minor": "3.6", "patch": "3.6.6"} doc[venv_name] = {"minor": "3.6", "patch": "3.6.6"}
envs_file.write(doc) envs_file.write(doc)
...@@ -815,7 +815,7 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( ...@@ -815,7 +815,7 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir(
m.assert_called_with(poetry.file.parent / ".venv", executable="python3.7") m.assert_called_with(poetry.file.parent / ".venv", executable="python3.7")
envs_file = TomlFile(Path(tmp_dir) / "virtualenvs" / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "virtualenvs" / "envs.toml")
assert not envs_file.exists() assert not envs_file.exists()
......
...@@ -2,17 +2,17 @@ import sys ...@@ -2,17 +2,17 @@ import sys
import pytest import pytest
from poetry.core.toml.file import TOMLFile
from poetry.factory import Factory from poetry.factory import Factory
from poetry.packages import Locker as BaseLocker from poetry.packages import Locker as BaseLocker
from poetry.repositories.legacy_repository import LegacyRepository from poetry.repositories.legacy_repository import LegacyRepository
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.exporter import Exporter from poetry.utils.exporter import Exporter
from poetry.utils.toml_file import TomlFile
class Locker(BaseLocker): class Locker(BaseLocker):
def __init__(self): def __init__(self):
self._lock = TomlFile(Path.cwd().joinpath("poetry.lock")) self._lock = TOMLFile(Path.cwd().joinpath("poetry.lock"))
self._locked = True self._locked = True
self._content_hash = self._get_content_hash() self._content_hash = self._get_content_hash()
......
import pytest
from poetry.utils._compat import Path
from poetry.utils.toml_file import TomlFile
@pytest.fixture()
def fixture():
return Path(__file__).parent / "fixtures" / "test.toml"
def test_toml_file(fixture):
f = TomlFile(fixture)
content = f.read()
assert content["title"] == "TOML Example"
assert content["owner"]["name"] == "Tom Preston-Werner"
assert isinstance(content["owner"], dict)
assert isinstance(content["database"]["ports"], list)
assert content["database"]["ports"] == [8001, 8001, 8002]
assert content["database"]["connection_max"] == 5000
assert content["database"]["enabled"]
servers = content["servers"]
assert len(servers) == 2
alpha = servers["alpha"]
assert len(alpha) == 2
assert alpha["ip"] == "10.0.0.1"
assert alpha["dc"] == "eqdc10"
beta = servers["beta"]
assert len(beta) == 2
assert beta["ip"] == "10.0.0.2"
assert beta["dc"] == "eqdc10"
clients = content["clients"]
assert len(clients["data"]) == 2
assert clients["data"] == [["gamma", "delta"], [1, 2]]
assert clients["hosts"] == ["alpha", "omega"]
assert clients["str_multiline"] == "Roses are red\nViolets are blue"
fruits = content["fruit"]
assert len(fruits) == 2
apple = fruits[0]
assert len(apple) == 3
banana = fruits[1]
assert len(banana["variety"][0]["points"]) == 3
def test_pyproject_parsing(fixture):
f = TomlFile(fixture.with_name("pyproject.toml"))
content = f.read()
assert "dependencies" in content["tool"]["poetry"]
assert content["tool"]["poetry"]["dependencies"]["python"] == "^3.6"
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