Commit 31b9dbf9 by Sébastien Eustace

Change poetry.lock format

parent 85950d71
......@@ -7,6 +7,14 @@
- Added `remove` command.
- Added basic support for VCS (git) dependencies.
### Changed
- Changed `poetry.lock` format.
### Fixed
- Fixed dependencies solving that would lead to dependencies not being written to lock.
## [0.1.0] - 2018-02-28
......
class BaseInstaller:
def install(self, package):
raise NotImplementedError
def update(self, source, target):
raise NotImplementedError
def remove(self, package):
raise NotImplementedError
......@@ -11,6 +11,7 @@ from poetry.puzzle.operations.operation import Operation
from poetry.repositories import Repository
from poetry.repositories.installed_repository import InstalledRepository
from .base_installer import BaseInstaller
from .pip_installer import PipInstaller
......@@ -35,7 +36,7 @@ class Installer:
self._whitelist = {}
self._installer = PipInstaller(self._io.venv, self._io)
self._installer = self._get_installer()
def run(self):
# Force update if there is no lock file present
......@@ -289,3 +290,6 @@ class Installer:
ops.append(Install(locked))
return ops
def _get_installer(self) -> BaseInstaller:
return PipInstaller(self._io.venv, self._io)
from .base_installer import BaseInstaller
class NoopInstaller(BaseInstaller):
def install(self, package) -> None:
pass
def update(self, source, target) -> None:
pass
def remove(self, package) -> None:
pass
from poetry.utils.venv import Venv
from .base_installer import BaseInstaller
class PipInstaller:
class PipInstaller(BaseInstaller):
def __init__(self, venv: Venv, io):
self._venv = venv
......
from .null_io import NullIO
from poetry.utils.venv import Venv
class NullVenv(Venv):
def __init__(self):
super().__init__()
self.executed = []
def run(self, bin: str, *args):
self.executed.append([bin] + list(args))
def _bin(self, bin):
return bin
class NullIO:
def __init__(self):
self._venv = NullVenv()
@property
def venv(self) -> NullVenv:
return self._venv
def is_quiet(self) -> bool:
return False
def is_verbose(self) -> bool:
return False
def is_very_verbose(self) -> bool:
return False
def is_debug(self) -> bool:
return False
def writeln(self, *args, **kwargs):
pass
def write(self, *args, **kwargs):
pass
def new_line(self, *args, **kwargs):
pass
......@@ -48,7 +48,7 @@ class Locker:
if not self._lock.exists():
return False
return 'packages' in self.lock_data
return 'package' in self.lock_data
def is_fresh(self) -> bool:
"""
......@@ -72,10 +72,10 @@ class Locker:
packages = Repository()
if with_dev_reqs:
locked_packages = lock_data['packages']
locked_packages = lock_data['package']
else:
locked_packages = [
p for p in lock_data['packages'] if p['category'] == 'main'
p for p in lock_data['package'] if p['category'] == 'main'
]
if not locked_packages:
......@@ -89,7 +89,7 @@ class Locker:
)
package.category = info['category']
package.optional = info['optional']
package.hashes = info['checksum']
package.hashes = lock_data['metadata']['hashes'][info['name']]
package.python_versions = info['python-versions']
if 'source' in info:
......@@ -103,27 +103,34 @@ class Locker:
def set_lock_data(self,
root, packages) -> bool:
hashes = {}
packages = self._lock_packages(packages)
# Retrieving hashes
for package in packages:
hashes[package['name']] = package['hashes']
del package['hashes']
lock = {
'root': {
'name': root.name,
'version': root.version,
'python_versions': root.python_versions,
'platform': root.platform
},
'packages': self._lock_packages(packages),
'package': packages,
'metadata': {
'content-hash': self._content_hash
'python-versions': root.python_versions,
'platform': root.platform,
'content-hash': self._content_hash,
'hashes': hashes,
}
}
if not self.is_locked() or lock != self.lock_data:
self._lock.write(lock)
self._lock_data = None
self._write_lock_data(lock)
return True
return False
def _write_lock_data(self, data):
self._lock.write(data)
self._lock_data = None
def _get_content_hash(self) -> str:
"""
Returns the sha256 hash of the sorted content of the composer file.
......@@ -153,7 +160,8 @@ class Locker:
return self._lock.read()
def _lock_packages(self, packages: List['poetry.packages.Package']) -> list:
def _lock_packages(self,
packages: List['poetry.packages.Package']) -> list:
locked = []
for package in sorted(packages, key=lambda x: x.name):
......@@ -171,7 +179,7 @@ class Locker:
'optional': package.optional,
'python-versions': package.python_versions,
'platform': package.platform,
'checksum': package.hashes,
'hashes': package.hashes,
}
if package.source_type:
......
......@@ -36,6 +36,10 @@ class Poetry:
def repository(self) -> PyPiRepository:
return self._repository
@property
def installer(self):
return self._instal
@classmethod
def create(cls, cwd) -> 'Poetry':
poetry_file = Path(cwd) / 'poetry.toml'
......
package = []
[metadata]
python-versions = "*"
platform = "*"
content-hash = "123456789"
[metadata.hashes]
[[package]]
name = "A"
version = "1.0"
category = "main"
optional = false
python-versions = "*"
platform = "*"
[metadata]
python-versions = "*"
platform = "*"
content-hash = "123456789"
[metadata.hashes]
"A" = []
[[package]]
name = "A"
version = "1.0"
category = "main"
optional = false
python-versions = "*"
platform = "*"
[[package]]
name = "B"
version = "1.1"
category = "main"
optional = false
python-versions = "*"
platform = "*"
[metadata]
python-versions = "*"
platform = "*"
content-hash = "123456789"
[metadata.hashes]
"A" = []
"B" = []
import pytest
import toml
from pathlib import Path
from poetry.installation import Installer as BaseInstaller
from poetry.installation.noop_installer import NoopInstaller
from poetry.io import NullIO
from poetry.packages import Locker as BaseLocker
from poetry.repositories import Repository
from tests.helpers import get_package
class Installer(BaseInstaller):
def _get_installer(self):
return NoopInstaller()
class Locker(BaseLocker):
def __init__(self):
self._written_data = None
self._locked = False
self._content_hash = self._get_content_hash()
@property
def written_data(self):
return self._written_data
def locked(self, is_locked=True) -> 'Locker':
self._locked = is_locked
return self
def mock_lock_data(self, data) -> None:
self._lock_data = data
def is_locked(self) -> bool:
return self._locked
def _get_content_hash(self) -> str:
return '123456789'
def _write_lock_data(self, data) -> None:
self._written_data = data
@pytest.fixture()
def package():
return get_package('root', '1.0')
@pytest.fixture()
def repo():
return Repository()
@pytest.fixture()
def locker():
return Locker()
def fixture(name):
file = Path(__file__).parent / 'fixtures' / f'{name}.test'
return toml.loads(file.read_text())
@pytest.fixture()
def installer(package, repo, locker):
return Installer(NullIO(), package, locker, repo)
def test_run_no_dependencies(installer, locker):
installer.run()
expected = fixture('no-dependencies')
assert locker.written_data == expected
def test_run_with_dependencies(installer, locker, repo, package):
package_a = get_package('A', '1.0')
package_b = get_package('B', '1.1')
repo.add_package(package_a)
repo.add_package(package_b)
package.add_dependency('A', '~1.0')
package.add_dependency('B', '^1.0')
installer.run()
expected = fixture('with-dependencies')
assert locker.written_data == expected
def test_run_whitelist_add(installer, locker, repo, package):
locker.locked(True)
locker.mock_lock_data({
'package': [{
'name': 'A',
'version': '1.0',
'category': 'main',
'optional': False,
'platform': '*',
'python-versions': '*',
'checksum': []
}],
'metadata': {
'python-versions': '*',
'platform': '*',
'content-hash': '123456789',
'hashes': {
'A': []
}
}
})
package_a = get_package('A', '1.0')
package_a_new = get_package('A', '1.1')
package_b = get_package('B', '1.1')
repo.add_package(package_a)
repo.add_package(package_a_new)
repo.add_package(package_b)
package.add_dependency('A', '~1.0')
package.add_dependency('B', '^1.0')
installer.update(True)
installer.whitelist({'B': '^1.1'})
installer.run()
expected = fixture('with-dependencies')
assert locker.written_data == expected
def test_run_whitelist_remove(installer, locker, repo, package):
locker.locked(True)
locker.mock_lock_data({
'package': [{
'name': 'A',
'version': '1.0',
'category': 'main',
'optional': False,
'platform': '*',
'python-versions': '*',
'checksum': []
}, {
'name': 'B',
'version': '1.1',
'category': 'main',
'optional': False,
'platform': '*',
'python-versions': '*',
'checksum': []
}],
'metadata': {
'python-versions': '*',
'platform': '*',
'content-hash': '123456789',
'hashes': {
'A': [],
'B': []
}
}
})
package_a = get_package('A', '1.0')
package_b = get_package('B', '1.1')
repo.add_package(package_a)
repo.add_package(package_b)
package.add_dependency('A', '~1.0')
installer.update(True)
installer.whitelist({'B': '^1.1'})
installer.run()
expected = fixture('remove')
assert locker.written_data == expected
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