Commit 53b62f4e by Sébastien Eustace

Add the version command

parent 64bdcfe2
......@@ -5,6 +5,7 @@
### Added
- Added compatibility with Python 3.4 and 3.5.
- Added the `version` command to automatically bump the packages' version.
### Changed
......
......@@ -281,3 +281,11 @@ This command locks (without installing) the dependencies specified in `pyproject
```bash
poetry lock
```
## version
This command bumps the version of the project
and writes the new version back to `pyproject.toml`
The new version should ideally be a valid semver string or a valid bump rule:
`patch`, `minor`, `major`, `prepatch`, `preminor`, `premajor`, `prerelease`.
......@@ -21,6 +21,7 @@ from .commands import RemoveCommand
from .commands import RunCommand
from .commands import ShowCommand
from .commands import UpdateCommand
from .commands import VersionCommand
from .commands.debug import DebugInfoCommand
from .commands.debug import DebugResolveCommand
......@@ -99,6 +100,7 @@ class Application(BaseApplication):
RunCommand(),
ShowCommand(),
UpdateCommand(),
VersionCommand(),
]
# Debug commands
......
......@@ -11,3 +11,4 @@ from .remove import RemoveCommand
from .run import RunCommand
from .show import ShowCommand
from .update import UpdateCommand
from .version import VersionCommand
import re
from .command import Command
class VersionCommand(Command):
"""
Bumps the version of the project.
version
{ version=patch }
"""
help = """\
The version command bumps the version of the project
and writes the new version back to <comment>pyproject.toml</>.
The new version should ideally be a valid semver string or a valid bump rule:
patch, minor, major, prepatch, preminor, premajor, prerelease.
"""
RESERVED = {
'major', 'minor', 'patch',
'premajor', 'preminor', 'prepatch',
'prerelease'
}
def handle(self):
version = self.argument('version')
if version in self.RESERVED:
version = self.increment_version(
self.poetry.package.pretty_version, version
)
self.line(
'Bumping version from <comment>{}</> to <info>{}</>'.format(
self.poetry.package.pretty_version, version
)
)
content = self.poetry.file.read()
poetry_content = content['tool']['poetry']
poetry_content['version'] = version
#self.poetry.file.write(content)
def increment_version(self, version, rule):
from poetry.semver.version_parser import VersionParser
parser = VersionParser()
version_regex = (
'v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?{}(?:\+[^\s]+)?'
).format(parser._modifier_regex)
m = re.match(version_regex, version)
if not m:
raise ValueError(
'The project\'s version doesn\'t seem to follow semver'
)
if m.group(3):
index = 2
elif m.group(2):
index = 1
else:
index = 0
matches = m.groups()[:index+1]
base = '.'.join(matches)
extra_matches = list(g or '' for g in m.groups()[4:])
extras = version[len('.'.join(matches)):]
increment = 1
is_prerelease = (extra_matches[0] or extra_matches[1]) != ''
bump_prerelease = rule in {
'premajor', 'preminor', 'prepatch', 'prerelease'
}
position = -1
if rule in {'major', 'premajor'}:
if m.group(1) != '0' or m.group(2) != '0' or not is_prerelease:
position = 0
elif rule in {'minor', 'preminor'}:
if m.group(2) != '0' or not is_prerelease:
position = 1
elif rule in {'patch', 'prepatch'}:
if not is_prerelease:
position = 2
elif rule == 'prerelease' and not is_prerelease:
position = 2
if position != -1:
extra_matches[0] = None
base = parser._manipulate_version_string(
matches,
position,
increment=increment
)
if bump_prerelease:
# We bump the prerelease part of the version
sep = ''
if not extra_matches[0]:
extra_matches[0] = 'alpha'
extra_matches[1] = '.0'
sep = '-'
else:
if extras.startswith(('.', '_', '-')):
sep = extras[0]
prerelease = extra_matches[1]
if not prerelease:
prerelease = '.1'
psep = ''
if prerelease.startswith(('.', '-')):
psep = prerelease[0]
prerelease = prerelease[1:]
new_prerelease = str(int(prerelease) + 1)
extra_matches[1] = '{}{}'.format(psep, new_prerelease)
extras = '{}{}{}{}'.format(
sep,
extra_matches[0],
extra_matches[1],
extra_matches[2]
)
else:
extras = ''
return '.'.join(base.split('.')[:max(index, position)+1]) + extras
......@@ -204,14 +204,14 @@ class VersionParser:
Increment, decrement, or simply pad a version number.
"""
matches = [matches[i]
if i < len(matches) - 1 and matches[i] is not None else '0'
if i <= len(matches) - 1 and matches[i] is not None else pad
for i in range(4)]
for i in range(3, -1, -1):
if i > position:
matches[i] = pad
elif i == position and increment:
matches[i] = int(matches[i]) + increment
# If $matches[i] was 0, carry the decrement
# If matches[i] was 0, carry the decrement
if matches[i] < 0:
matches[i] = pad
position -= 1
......
import pytest
from poetry.console.commands import VersionCommand
@pytest.fixture()
def command():
return VersionCommand()
@pytest.mark.parametrize(
'version, rule, expected',
[
('0.0.0', 'patch', '0.0.1'),
('0.0.0', 'minor', '0.1.0'),
('0.0.0', 'major', '1.0.0'),
('0.0', 'major', '1.0'),
('0.0', 'minor', '0.1'),
('0.0', 'patch', '0.0.1'),
('1.2.3', 'patch', '1.2.4'),
('1.2.3', 'minor', '1.3.0'),
('1.2.3', 'major', '2.0.0'),
('1.2.3', 'prepatch', '1.2.4-alpha.0'),
('1.2.3', 'preminor', '1.3.0-alpha.0'),
('1.2.3', 'premajor', '2.0.0-alpha.0'),
('1.2.3-beta.1', 'patch', '1.2.3'),
('1.2.3-beta.1', 'minor', '1.3.0'),
('1.2.3-beta.1', 'major', '2.0.0'),
('1.2.3-beta.1', 'prerelease', '1.2.3-beta.2'),
('1.2.3-beta1', 'prerelease', '1.2.3-beta2'),
('1.2.3beta1', 'prerelease', '1.2.3beta2'),
('1.2.3b1', 'prerelease', '1.2.3b2'),
('1.2.3', 'prerelease', '1.2.4-alpha.0')
]
)
def test_increment_version(version, rule, expected, command):
assert expected == command.increment_version(version, rule)
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