mirror of
https://github.com/TECHNOFAB11/bumpver.git
synced 2025-12-12 06:20:08 +01:00
readme updates
This commit is contained in:
parent
32ad101b9f
commit
28e09fd60a
7 changed files with 356 additions and 214 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -1,6 +1,16 @@
|
|||
# Changelog for https://gitlab.com/mbarkhau/pycalver
|
||||
|
||||
|
||||
## NEXT
|
||||
|
||||
- New gitlab #7: New style patterns, to be in line with CalVer.org
|
||||
- Better support for week numbering.
|
||||
- Better support for optional parts.
|
||||
- New gitlab #10: `--pin-date` to keep date parts unchanged, and only increment non-date parts.
|
||||
- Fix gitlab #8: Push tags only pushed tags, not actual commit.
|
||||
- Fix gitlab #9: Make commit message configurable.
|
||||
|
||||
|
||||
## v201907.0036
|
||||
|
||||
- Fix: Don't use git/hg command if `commit=False` is configured (thanks @valentin87)
|
||||
|
|
|
|||
144
README.md
144
README.md
|
|
@ -212,10 +212,108 @@ The internally used regular expression is also shown, which you can use to debug
|
|||
|
||||
### Pattern Search and Replacement
|
||||
|
||||
The `pycalver:file_patterns` section of the configuration is used both to search
|
||||
and also to replace version strings in your projects files. Everything except
|
||||
The neat thing about PyCalVer is that you don't have to separately declare the search pattern and the replacement template. You declare one pattern that is used to derive both.
|
||||
|
||||
for valid placeholders is treated as literal text. Available placeholders are:
|
||||
|
||||
You define your pattern in the `pycalver:version_pattern` option of your config.
|
||||
|
||||
You can also define custom patterns in the items of the `pycalver:file_patterns` section of your configuration, but usually it will be easier to just use the special `{version}` and `{pep440_version}` patterns, which are derived from what you configure as your `version_pattern`. is used both to search and also to replace version strings in your projects files. Everything except for valid placeholders is treated as literal text. Available placeholders are:
|
||||
|
||||
These patterns are closely based on https://calver.org/
|
||||
|
||||
| placeholder | range / example(s) | comment |
|
||||
|-------------|---------------------|----------------------|
|
||||
| YYYY | 2019, 2020... | `%Y` |
|
||||
| YY | 18, 19..99, 1, 2 | `int(%y)` |
|
||||
| 0Y | 18, 19..99, 01, 02 | `%y` |
|
||||
| Q | 1, 2, 3, 4 | quarter |
|
||||
| MM | 9, 10, 11, 12 | `int(%m)` |
|
||||
| 0M | 09, 10, 11, 12 | `%m` |
|
||||
| DD | 1, 2, 3..31 | `int(%d)` |
|
||||
| 0D | 01, 02, 03..31 | `%d` |
|
||||
| JJJ | 1,2,3..366 | `int(%j)` |
|
||||
| 00J | 001, 002..366 | `%j` |
|
||||
| BUILD | 1001, 1002, 23456 | build number (lexid) |
|
||||
| TAG | alpha, beta, rc | `--release=<tag>` |
|
||||
| PYTAG | a0, b0, rc | `--release=<tag>` |
|
||||
| MAJOR | 0..9, 10..99, 100.. | `--major` |
|
||||
| MINOR | 0..9, 10..99, 100.. | `--minor` |
|
||||
| PATCH | 0..9, 10..99, 100.. | `--patch` |
|
||||
| MICRO | 0..9, 10..99, 100.. | Synonym for PATCH |
|
||||
|
||||
|
||||
### Week Numbering
|
||||
|
||||
Week numbering is a bit special, as it depends on your definition of "week":
|
||||
|
||||
- Does it start on a Monday or a Sunday?
|
||||
- Range from 0-52 or 1-53 ?
|
||||
- At the beginning/end of the year, do you have partial weeks or do you have a week that span mutliple years?
|
||||
- If a week spans multiple years, what is the year number?
|
||||
|
||||
| placeholder | range / example(s) | comment |
|
||||
|-------------|---------------------|------------------------------------------------------------|
|
||||
| `WW` | 0, 1, 2..52 | `int(%W)` |
|
||||
| `0W` | 00, 01, 02..52 | `%W` |
|
||||
| `UU` | 0, 1, 2..52 | `int(%U)` us_week |
|
||||
| `0U` | 00, 01, 02..52 | `%U` us_week |
|
||||
| `VV` | 1, 2..53 | `int(%V)` iso week |
|
||||
| `0V` | 01, 02..53 | `%U` iso_week |
|
||||
| `GGGG` | 2019, 2020... | ISO 8601 week-based year (corresponds to `strftime("%G")`) |
|
||||
| `GG` | 19, 20...99, 0, 1 | Short ISO 8601 week-based year |
|
||||
| `0G` | 19, 20...99, 00, 01 | Zero-padded ISO 8601 week-based year |
|
||||
|
||||
|
||||
### Normalization Caveats
|
||||
|
||||
Since other tools parse your version numbers, they may not care about your choice of formatting. In the case of Python, the packaging tools (such as pypi.org) follow [PEP440 normalization rules][pep_440_normalzation_ref].
|
||||
|
||||
According to these rules:
|
||||
|
||||
- Any non-numerical prefix (such as `v`) is removed
|
||||
- Leading zeros in parts are truncated `XX.08` -> `XX.8`
|
||||
- Tags are converted to a short form (`-alpha` -> `a0`)
|
||||
|
||||
For example:
|
||||
|
||||
- Pattern: `vYY.0M.0D[-TAG]`
|
||||
- Version: `v20.08.02-beta`
|
||||
- PEP440 : `20.8.2b0`
|
||||
|
||||
It may be confusing to your users to see versions displayed in two different forms. It is not immediately obvious that `v20.08.02-beta` is the same `20.8.2b0` on pypi. If you wish to avoid this, you should usa a pattern which is as close as possible to the normalized form of your version.
|
||||
|
||||
| pattern | example | lexical | PEP440 | lexical |
|
||||
|-----------------------|---------|---------|--------|---------|
|
||||
| `YYYY.0M` | | yes | | no |
|
||||
| `YYYY.MM` | | no | | no |
|
||||
| `vYYYY.0W` | | yes | | no |
|
||||
| `vYYYY.WW` | | no | | no |
|
||||
| `YYYY.0M.0D` | | yes | | no |
|
||||
| `YYYY.MM.DD` | | no | | no |
|
||||
| `YYYY0M.BUILD[-TAG]` | | yes | | yes |
|
||||
| `YY0M.BUILD[-TAG]` | | yes¹ | | yes¹ |
|
||||
| `YYYY.BUILD[-TAG]` | | yes | | yes |
|
||||
| `YYYY0M.MINOR[-TAG]` | | yes² | | yes |
|
||||
| `YYYY.MM.MINOR[-TAG]` | | no | | no |
|
||||
| `YYYY.0M.MINOR[-TAG]` | | yes² | | no |
|
||||
| `YYYY.WW.MINOR[-TAG]` | | no | | no |
|
||||
| `YYYY.0W.MINOR[-TAG]` | | yes² | | no |
|
||||
|
||||
- ¹ Until 2099. If your project has new releases after 2099, future maintainers can change `YY`/`0Y` -> `YYYY` so that they don't release `00.xx`.
|
||||
- ² As long as `MINOR <= 9`
|
||||
|
||||
|
||||
### Legacy Patterns
|
||||
|
||||
> These patterns use curly braces `{}` and were the initial implementation. They are still supported and still follow their original semantics.
|
||||
|
||||
The `pycalver:file_patterns` section of the configuration uses a different set
|
||||
of placeholders and does not use curly braces to mark placeholders. It is still
|
||||
supported, but we don't recomend you use it.
|
||||
|
||||
Available placeholders are:
|
||||
|
||||
|
||||
| placeholder | range / example(s) | comment |
|
||||
|---------------------|---------------------|-----------------|
|
||||
|
|
@ -298,29 +396,29 @@ bump` to update the components that are not updated automatically (eg.
|
|||
based on the calendar).
|
||||
|
||||
```shell
|
||||
$ pycalver test 'v18.1.1' 'v{yy}.{MINOR}.{PATCH}'
|
||||
$ pycalver test 'v18.1.1' 'vYY.MINOR.PATCH'
|
||||
New Version: v19.1.1
|
||||
PEP440 : 19.1.1
|
||||
|
||||
$ pycalver test 'v18.1.1' 'v{yy}.{MINOR}.{PATCH}' --patch
|
||||
$ pycalver test 'v18.1.1' 'vYY.MINOR.PATCH' --patch
|
||||
New Version: v19.1.2
|
||||
PEP440 : 19.1.2
|
||||
|
||||
$ pycalver test 'v18.1.2' 'v{yy}.{MINOR}.{PATCH}' --minor
|
||||
$ pycalver test 'v18.1.2' 'vYY.MINOR.PATCH' --minor
|
||||
New Version: v19.2.0
|
||||
PEP440 : 19.2.0
|
||||
|
||||
$ pycalver test 'v201811.0051-beta' '{pycalver}'
|
||||
New Version: v201902.0052-beta
|
||||
PEP440 : 201902.52b0
|
||||
$ pycalver test 'v201811.1051-beta' 'vYYYYMM.BUILD[-TAG]'
|
||||
New Version: v201902.1052-beta
|
||||
PEP440 : 201902.1052b0
|
||||
|
||||
$ pycalver test 'v201811.0051-beta' '{pycalver}' --release rc
|
||||
New Version: v201902.0052-rc
|
||||
PEP440 : 201902.52rc0
|
||||
$ pycalver test 'v201811.0051-beta' 'vYYYYMM.BUILD[-TAG]' --release rc
|
||||
New Version: v201902.1052-rc
|
||||
PEP440 : 201902.1052rc0
|
||||
|
||||
$ pycalver test 'v201811.0051-beta' '{pycalver}' --release final
|
||||
New Version: v201902.0052
|
||||
PEP440 : 201902.52
|
||||
$ pycalver test 'v201811.0051-beta' 'vYYYYMM.BUILD[-TAG]' --release final
|
||||
New Version: v201902.1052
|
||||
PEP440 : 201902.1052
|
||||
```
|
||||
|
||||
Note that pypi/setuptools/pip will normalize version strings to a format
|
||||
|
|
@ -391,8 +489,8 @@ section:
|
|||
|
||||
```ini
|
||||
[pycalver]
|
||||
current_version = "v201812.0006-beta"
|
||||
version_pattern = "{pycalver}"
|
||||
current_version = "202008.1006-beta"
|
||||
version_pattern = "YYYY0M.BUILD[-TAG]"
|
||||
commit = True
|
||||
tag = True
|
||||
push = True
|
||||
|
|
@ -429,8 +527,8 @@ $ pycalver bump --dry
|
|||
@@ -65,7 +65,7 @@
|
||||
|
||||
[pycalver]
|
||||
-current_version = v201812.0005-beta
|
||||
+current_version = v201812.0006-beta
|
||||
-current_version = v202008.1005-beta
|
||||
+current_version = v202008.1006-beta
|
||||
commit = True
|
||||
tag = True
|
||||
push = True
|
||||
|
|
@ -442,11 +540,11 @@ If everything looks OK, you can do `pycalver bump`.
|
|||
```
|
||||
$ pycalver bump --verbose
|
||||
INFO - fetching tags from remote (to turn off use: -n / --no-fetch)
|
||||
INFO - Old Version: v201812.0005-beta
|
||||
INFO - New Version: v201812.0006-beta
|
||||
INFO - Old Version: v202008.0005-beta
|
||||
INFO - New Version: v202008.0006-beta
|
||||
INFO - git commit --file /tmp/tmpph_npey9
|
||||
INFO - git tag --annotate v201812.0006-beta --message v201812.0006-beta
|
||||
INFO - git push origin v201812.0006-beta
|
||||
INFO - git tag --annotate v202008.0006-beta --message v202008.0006-beta
|
||||
INFO - git push origin v202008.0006-beta
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -461,7 +559,7 @@ The PyCalVer format for version strings has three parts:
|
|||
| | o Release Tag (optional)
|
||||
| | |
|
||||
---+--- --+-- --+--
|
||||
v201812 .0123 -beta
|
||||
v202008 .0123 -beta
|
||||
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -3,61 +3,36 @@
|
|||
#
|
||||
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""Compose Regular Expressions from Patterns.
|
||||
# """Compose Regular Expressions from Patterns.
|
||||
|
||||
>>> version_info = PYCALVER_RE.match("v201712.0123-alpha").groupdict()
|
||||
>>> assert version_info == {
|
||||
... "pycalver" : "v201712.0123-alpha",
|
||||
... "vYYYYMM" : "v201712",
|
||||
... "year" : "2017",
|
||||
... "month" : "12",
|
||||
... "build" : ".0123",
|
||||
... "build_no" : "0123",
|
||||
... "release" : "-alpha",
|
||||
... "release_tag" : "alpha",
|
||||
... }
|
||||
>>>
|
||||
>>> version_info = PYCALVER_RE.match("v201712.0033").groupdict()
|
||||
>>> assert version_info == {
|
||||
... "pycalver" : "v201712.0033",
|
||||
... "vYYYYMM" : "v201712",
|
||||
... "year" : "2017",
|
||||
... "month" : "12",
|
||||
... "build" : ".0033",
|
||||
... "build_no" : "0033",
|
||||
... "release" : None,
|
||||
... "release_tag": None,
|
||||
... }
|
||||
"""
|
||||
# >>> pattern = compile_pattern("vYYYY0M.BUILD[-TAG]")
|
||||
# >>> version_info = pattern.regexp.match("v201712.0123-alpha")
|
||||
# >>> assert version_info == {
|
||||
# ... "version": "v201712.0123-alpha",
|
||||
# ... "YYYY" : "2017",
|
||||
# ... "0M" : "12",
|
||||
# ... "BUILD" : "0123",
|
||||
# ... "TAG" : "alpha",
|
||||
# ... }
|
||||
# >>>
|
||||
# >>> version_info = pattern.regexp.match("201712.1234")
|
||||
# >>> assert version_info is None
|
||||
|
||||
# >>> version_info = pattern.regexp.match("v201712.1234")
|
||||
# >>> assert version_info == {
|
||||
# ... "version": "v201712.0123-alpha",
|
||||
# ... "YYYY" : "2017",
|
||||
# ... "0M" : "12",
|
||||
# ... "BUILD" : "0123",
|
||||
# ... "TAG" : None,
|
||||
# ... }
|
||||
# """
|
||||
|
||||
import re
|
||||
import typing as typ
|
||||
|
||||
import pycalver.patterns as v1patterns
|
||||
|
||||
# https://regex101.com/r/fnj60p/10
|
||||
PYCALVER_PATTERN = r"""
|
||||
\b
|
||||
(?P<pycalver>
|
||||
(?P<vYYYYMM>
|
||||
v # "v" version prefix
|
||||
(?P<year>\d{4})
|
||||
(?P<month>\d{2})
|
||||
)
|
||||
(?P<build>
|
||||
\. # "." build nr prefix
|
||||
(?P<build_no>\d{4,})
|
||||
)
|
||||
(?P<release>
|
||||
\- # "-" release prefix
|
||||
(?P<release_tag>alpha|beta|dev|rc|post)
|
||||
)?
|
||||
)(?:\s|$)
|
||||
"""
|
||||
|
||||
PYCALVER_RE: typ.Pattern[str] = re.compile(PYCALVER_PATTERN, flags=re.VERBOSE)
|
||||
|
||||
|
||||
PATTERN_ESCAPES = [
|
||||
("\u005c", "\u005c\u005c"),
|
||||
("-" , "\u005c-"),
|
||||
|
|
@ -73,107 +48,37 @@ PATTERN_ESCAPES = [
|
|||
(")" , "\u005c)"),
|
||||
]
|
||||
|
||||
# NOTE (mb 2020-09-04): These are depricated in favour of explicit patterns
|
||||
COMPOSITE_PART_PATTERNS = {
|
||||
'pep440_pycalver': r"{year}{month}\.{BID}(?:{pep440_tag})?",
|
||||
'pycalver' : r"v{year}{month}\.{bid}(?:-{tag})?",
|
||||
'calver' : r"v{year}{month}",
|
||||
'semver' : r"{MAJOR}\.{MINOR}\.{PATCH}",
|
||||
'release_tag' : r"{tag}",
|
||||
'build' : r"\.{bid}",
|
||||
'release' : r"(?:-{tag})?",
|
||||
# depricated
|
||||
'pep440_version': r"{year}{month}\.{BID}(?:{pep440_tag})?",
|
||||
}
|
||||
|
||||
|
||||
PART_PATTERNS = {
|
||||
# recommended (based on calver.org)
|
||||
'YYYY': r"[1-9]\d{3}",
|
||||
'YY' : r"\d{1,2}",
|
||||
'0Y' : r"\d{2}",
|
||||
# Based on calver.org
|
||||
'YYYY': r"[1-9][0-9]{3}",
|
||||
'YY' : r"[1-9][0-9]?",
|
||||
'0Y' : r"[0-9]{2}",
|
||||
'Q' : r"[1-4]",
|
||||
'MM' : r"(?:[1-9]|1[0-2])",
|
||||
'0M' : r"(?:0[1-9]|1[0-2])",
|
||||
'DD' : r"([1-9]|[1-2][0-9]|3[0-1])",
|
||||
'0D' : r"(0[1-9]|[1-2][0-9]|3[0-1])",
|
||||
'JJJ' : r"(?:[1-9]\d|[1-9]|[1-2]\d\d|3[0-5][0-9]|36[0-6])",
|
||||
'00J' : r"(?:[0-2]\d\d|3[0-5][0-9]|36[0-6])",
|
||||
'WW' : r"(?:[1-9]|[1-4]\d|5[0-2])",
|
||||
'0W' : r"(?:[0-4]\d|5[0-2])",
|
||||
'UU' : r"(?:[1-9]|[0-4]\d|5[0-2])",
|
||||
'0U' : r"(?:[0-4]\d|5[0-2])",
|
||||
'VV' : r"(?:[1-9]|[1-4]\d|5[0-3])",
|
||||
'0V' : r"(?:[0-4]\d|5[0-3])",
|
||||
'GGGG': r"[1-9]\d{3}",
|
||||
'GG' : r"\d{1,2}",
|
||||
'0G' : r"\d{2}",
|
||||
'DD' : r"(?:[1-9]|[1-2][0-9]|3[0-1])",
|
||||
'0D' : r"(?:0[1-9]|[1-2][0-9]|3[0-1])",
|
||||
'JJJ' : r"(?:[1-9]|[1-9][0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|36[0-6])",
|
||||
'00J' : r"(?:00[1-9]|0[1-9][0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|36[0-6])",
|
||||
# week numbering parts
|
||||
'WW' : r"(?:[0-9]|[1-4][0-9]|5[0-2])",
|
||||
'0W' : r"(?:[0-4][0-9]|5[0-2])",
|
||||
'UU' : r"(?:[0-9]|[1-4][0-9]|5[0-2])",
|
||||
'0U' : r"(?:[0-4][0-9]|5[0-2])",
|
||||
'VV' : r"(?:[1-9]|[1-4][0-9]|5[0-3])",
|
||||
'0V' : r"(?:0[1-9]|[1-4][0-9]|5[0-3])",
|
||||
'GGGG': r"[1-9][0-9]{3}",
|
||||
'GG' : r"[1-9][0-9]?",
|
||||
'0G' : r"[0-9]{2}",
|
||||
# non calver parts
|
||||
'MAJOR': r"\d+",
|
||||
'MINOR': r"\d+",
|
||||
'PATCH': r"\d+",
|
||||
'MICRO': r"\d+",
|
||||
'BUILD': r"\d+",
|
||||
'MAJOR': r"[0-9]+",
|
||||
'MINOR': r"[0-9]+",
|
||||
'PATCH': r"[0-9]+",
|
||||
'MICRO': r"[0-9]+",
|
||||
'BUILD': r"[0-9]+",
|
||||
'TAG' : r"(?:alpha|beta|dev|rc|post|final)",
|
||||
'PYTAG': r"(?:a|b|dev|rc|post)?\d*",
|
||||
# supported (but legacy)
|
||||
'year' : r"\d{4}",
|
||||
'month' : r"(?:0[0-9]|1[0-2])",
|
||||
'month_short': r"(?:1[0-2]|[1-9])",
|
||||
'build_no' : r"\d{4,}",
|
||||
'pep440_tag' : r"(?:a|b|dev|rc|post)?\d*",
|
||||
'tag' : r"(?:alpha|beta|dev|rc|post|final)",
|
||||
'yy' : r"\d{2}",
|
||||
'yyyy' : r"\d{4}",
|
||||
'quarter' : r"[1-4]",
|
||||
'iso_week' : r"(?:[0-4]\d|5[0-3])",
|
||||
'us_week' : r"(?:[0-4]\d|5[0-3])",
|
||||
'dom' : r"(0[1-9]|[1-2][0-9]|3[0-1])",
|
||||
'dom_short' : r"([1-9]|[1-2][0-9]|3[0-1])",
|
||||
'doy' : r"(?:[0-2]\d\d|3[0-5][0-9]|36[0-6])",
|
||||
'doy_short' : r"(?:[0-2]\d\d|3[0-5][0-9]|36[0-6])",
|
||||
'bid' : r"\d{4,}",
|
||||
# dropped support (never documented)
|
||||
# 'BID' : r"[1-9]\d*",
|
||||
# 'MM' : r"\d{2,}",
|
||||
# 'MMM' : r"\d{3,}",
|
||||
# 'MMMM' : r"\d{4,}",
|
||||
# 'MMMMM' : r"\d{5,}",
|
||||
# 'PP' : r"\d{2,}",
|
||||
# 'PPP' : r"\d{3,}",
|
||||
# 'PPPP' : r"\d{4,}",
|
||||
# 'PPPPP' : r"\d{5,}",
|
||||
# 'BB' : r"[1-9]\d{1,}",
|
||||
# 'BBB' : r"[1-9]\d{2,}",
|
||||
# 'BBBB' : r"[1-9]\d{3,}",
|
||||
# 'BBBBB' : r"[1-9]\d{4,}",
|
||||
# 'BBBBBB' : r"[1-9]\d{5,}",
|
||||
# 'BBBBBBB' : r"[1-9]\d{6,}",
|
||||
}
|
||||
|
||||
|
||||
FULL_PART_FORMATS = {
|
||||
'pep440_pycalver': "{year}{month:02}.{BID}{pep440_tag}",
|
||||
'pycalver' : "v{year}{month:02}.{bid}{release}",
|
||||
'calver' : "v{year}{month:02}",
|
||||
'semver' : "{MAJOR}.{MINOR}.{PATCH}",
|
||||
'release_tag' : "{tag}",
|
||||
'build' : ".{bid}",
|
||||
# NOTE (mb 2019-01-04): since release is optional, it
|
||||
# is treated specially in version.format
|
||||
# 'release' : "-{tag}",
|
||||
'month' : "{month:02}",
|
||||
'month_short': "{month}",
|
||||
'build_no' : "{bid}",
|
||||
'iso_week' : "{iso_week:02}",
|
||||
'us_week' : "{us_week:02}",
|
||||
'dom' : "{dom:02}",
|
||||
'doy' : "{doy:03}",
|
||||
'dom_short' : "{dom}",
|
||||
'doy_short' : "{doy}",
|
||||
# depricated
|
||||
'pep440_version': "{year}{month:02}.{BID}{pep440_tag}",
|
||||
'version' : "v{year}{month:02}.{bid}{release}",
|
||||
'PYTAG': r"(?:a|b|dev|rc|post)?[0-9]*",
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -198,13 +103,3 @@ def compile_pattern(pattern: str) -> v1patterns.Pattern:
|
|||
pattern_str = compile_pattern_str(pattern)
|
||||
pattern_re = re.compile(pattern_str)
|
||||
return v1patterns.Pattern(pattern, pattern_re)
|
||||
|
||||
|
||||
def _init_composite_patterns() -> None:
|
||||
for part_name, part_pattern in COMPOSITE_PART_PATTERNS.items():
|
||||
part_pattern = part_pattern.replace("{", "\u005c{").replace("}", "\u005c}")
|
||||
pattern_str = _replace_pattern_parts(part_pattern)
|
||||
PART_PATTERNS[part_name] = pattern_str
|
||||
|
||||
|
||||
_init_composite_patterns()
|
||||
|
|
|
|||
|
|
@ -344,14 +344,13 @@ def _parse_version_info(pattern_groups: PatternGroups) -> VersionInfo:
|
|||
return _parse_field_values(field_values)
|
||||
|
||||
|
||||
def parse_version_info(version_str: str, pattern: str = "{pycalver}") -> VersionInfo:
|
||||
# TODO reenable doctest
|
||||
def parse_version_info(version_str: str, pattern: str = "vYYYY0M.BUILD[-TAG]") -> VersionInfo:
|
||||
# """Parse normalized VersionInfo.
|
||||
|
||||
# >>> vnfo = parse_version_info("v201712.0033-beta", pattern="{pycalver}")
|
||||
# >>> vnfo = parse_version_info("v201712.0033-beta", pattern="vYYYY0M.BUILD[-TAG]")
|
||||
# >>> assert vnfo == _parse_version_info({'year': 2017, 'month': 12, 'bid': "0033", 'tag': "beta"})
|
||||
|
||||
# >>> vnfo = parse_version_info("1.23.456", pattern="{semver}")
|
||||
# >>> vnfo = parse_version_info("1.23.456", pattern="MAJOR.MINOR.PATCH")
|
||||
# >>> assert vnfo == _parse_version_info({'MAJOR': "1", 'MINOR': "23", 'PATCH': "456"})
|
||||
# """
|
||||
pattern_tup = v2patterns.compile_pattern(pattern)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import pathlib2 as pl
|
|||
from click.testing import CliRunner
|
||||
|
||||
import pycalver.config as config
|
||||
import pycalver2.patterns as patterns
|
||||
import pycalver.patterns as v1patterns
|
||||
from pycalver.__main__ import cli
|
||||
|
||||
SETUP_CFG_FIXTURE = """
|
||||
|
|
@ -81,7 +81,7 @@ def test_version(runner):
|
|||
result = runner.invoke(cli, ['--version', "-vv"])
|
||||
assert result.exit_code == 0
|
||||
assert " version v20" in result.output
|
||||
match = patterns.PYCALVER_RE.search(result.output)
|
||||
match = v1patterns.PYCALVER_RE.search(result.output)
|
||||
assert match
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,134 @@ import pycalver2.patterns as v2patterns
|
|||
|
||||
# TODO (mb 2020-09-06): test for v2patterns
|
||||
|
||||
V2_PART_PATTERN_CASES = [
|
||||
(['YYYY', 'GGGG'], "2020" , "2020"),
|
||||
(['YYYY', 'GGGG'], "" , None),
|
||||
(['YYYY', 'GGGG'], "A020" , None),
|
||||
(['YYYY', 'GGGG'], "020" , None),
|
||||
(['YYYY', 'GGGG'], "12020", None),
|
||||
(['YY' , 'GG' ], "20" , "20"),
|
||||
(['YY' , 'GG' ], "3" , "3"),
|
||||
(['YY' , 'GG' ], "03" , None),
|
||||
(['YY' , 'GG' ], "2X" , None),
|
||||
(['YY' , 'GG' ], "" , None),
|
||||
(['0Y' , '0G' ], "20" , "20"),
|
||||
(['0Y' , '0G' ], "03" , "03"),
|
||||
(['0Y' , '0G' ], "3" , None),
|
||||
(['0Y' , '0G' ], "2X" , None),
|
||||
(['0Y' , '0G' ], "" , None),
|
||||
# quarter
|
||||
(['Q'], "0", None),
|
||||
(['Q'], "1", "1"),
|
||||
(['Q'], "2", "2"),
|
||||
(['Q'], "3", "3"),
|
||||
(['Q'], "4", "4"),
|
||||
(['Q'], "5", None),
|
||||
(['Q'], "X", None),
|
||||
# months
|
||||
(['MM'], "0" , None),
|
||||
(['MM'], "01", None),
|
||||
(['MM'], "1" , "1"),
|
||||
(['MM'], "10", "10"),
|
||||
(['MM'], "12", "12"),
|
||||
(['MM'], "13", None),
|
||||
(['0M'], "00", None),
|
||||
(['0M'], "1" , None),
|
||||
(['0M'], "01", "01"),
|
||||
(['MM'], "10", "10"),
|
||||
(['MM'], "12", "12"),
|
||||
(['MM'], "13", None),
|
||||
# day of month
|
||||
(['DD'], "0" , None),
|
||||
(['DD'], "01", None),
|
||||
(['DD'], "1" , "1"),
|
||||
(['DD'], "10", "10"),
|
||||
(['DD'], "31", "31"),
|
||||
(['DD'], "32", None),
|
||||
(['0D'], "00", None),
|
||||
(['0D'], "1" , None),
|
||||
(['0D'], "01", "01"),
|
||||
(['0D'], "10", "10"),
|
||||
(['0D'], "31", "31"),
|
||||
(['0D'], "32", None),
|
||||
(['DD'], "0" , None),
|
||||
(['DD'], "01", None),
|
||||
(['DD'], "1" , "1"),
|
||||
(['DD'], "10", "10"),
|
||||
(['DD'], "31", "31"),
|
||||
(['DD'], "32", None),
|
||||
(['0D'], "00", None),
|
||||
(['0D'], "1" , None),
|
||||
(['0D'], "01", "01"),
|
||||
(['0D'], "10", "10"),
|
||||
(['0D'], "31", "31"),
|
||||
(['0D'], "32", None),
|
||||
# day of year
|
||||
(['JJJ'], "0" , None),
|
||||
(['JJJ'], "01" , None),
|
||||
(['JJJ'], "1" , "1"),
|
||||
(['JJJ'], "10" , "10"),
|
||||
(['JJJ'], "31" , "31"),
|
||||
(['JJJ'], "32" , "32"),
|
||||
(['JJJ'], "100", "100"),
|
||||
(['JJJ'], "365", "365"),
|
||||
(['JJJ'], "366", "366"),
|
||||
(['JJJ'], "367", None),
|
||||
(['00J'], "000", None),
|
||||
(['00J'], "01" , None),
|
||||
(['00J'], "1" , None),
|
||||
(['00J'], "001", "001"),
|
||||
(['00J'], "010", "010"),
|
||||
(['00J'], "031", "031"),
|
||||
(['00J'], "032", "032"),
|
||||
(['00J'], "100", "100"),
|
||||
(['00J'], "365", "365"),
|
||||
(['00J'], "366", "366"),
|
||||
(['00J'], "367", None),
|
||||
# week numbers
|
||||
(['WW', 'UU'], "00", None),
|
||||
(['WW', 'UU'], "01", None),
|
||||
(['WW', 'UU'], "0" , "0"),
|
||||
(['WW', 'UU'], "1" , "1"),
|
||||
(['WW', 'UU'], "10", "10"),
|
||||
(['WW', 'UU'], "52", "52"),
|
||||
(['WW', 'UU'], "53", None),
|
||||
(['0W', '0U'], "00", "00"),
|
||||
(['0W', '0U'], "01", "01"),
|
||||
(['0W', '0U'], "0" , None),
|
||||
(['0W', '0U'], "1" , None),
|
||||
(['0W', '0U'], "10", "10"),
|
||||
(['0W', '0U'], "52", "52"),
|
||||
(['0W', '0U'], "53", None),
|
||||
(['VV'], "00", None),
|
||||
(['VV'], "01", None),
|
||||
(['VV'], "0" , None),
|
||||
(['VV'], "1" , "1"),
|
||||
(['VV'], "10", "10"),
|
||||
(['VV'], "52", "52"),
|
||||
(['VV'], "53", "53"),
|
||||
(['VV'], "54", None),
|
||||
(['0V'], "00", None),
|
||||
(['0V'], "01", "01"),
|
||||
(['0V'], "0" , None),
|
||||
(['0V'], "1" , None),
|
||||
(['0V'], "10", "10"),
|
||||
(['0V'], "52", "52"),
|
||||
(['0V'], "53", "53"),
|
||||
(['0V'], "54", None),
|
||||
(['MAJOR', 'MINOR', 'PATCH', 'MICRO'], "0", "0"),
|
||||
# ('TAG', ""),
|
||||
# ('PYTAG', ""),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("parts, testcase, expected", V2_PART_PATTERN_CASES)
|
||||
def test_part_patterns(parts, testcase, expected):
|
||||
for part in parts:
|
||||
pattern_str = v2patterns.PART_PATTERNS[part]
|
||||
match = re.match("^" + pattern_str + "$", testcase)
|
||||
assert (match is None and expected is None) or (match.group(0) == expected)
|
||||
|
||||
|
||||
def _part_re_by_name(name):
|
||||
return re.compile(v1patterns.PART_PATTERNS[name])
|
||||
|
|
|
|||
|
|
@ -5,28 +5,30 @@ import datetime as dt
|
|||
|
||||
import pytest
|
||||
|
||||
from pycalver import version
|
||||
from pycalver import patterns
|
||||
import pycalver.version as v1version
|
||||
import pycalver2.version as v2version
|
||||
import pycalver.patterns as v1patterns
|
||||
import pycalver2.patterns as v2patterns
|
||||
|
||||
|
||||
def test_bump_beta():
|
||||
cur_version = "v201712.0001-beta"
|
||||
assert cur_version < version.incr(cur_version)
|
||||
assert version.incr(cur_version).endswith("-beta")
|
||||
assert version.incr(cur_version, release="alpha").endswith("-alpha")
|
||||
assert version.incr(cur_version, release="final").endswith("0002")
|
||||
assert cur_version < v1version.incr(cur_version)
|
||||
assert v1version.incr(cur_version).endswith("-beta")
|
||||
assert v1version.incr(cur_version, release="alpha").endswith("-alpha")
|
||||
assert v1version.incr(cur_version, release="final").endswith("0002")
|
||||
|
||||
|
||||
def test_bump_final():
|
||||
cur_version = "v201712.0001"
|
||||
assert cur_version < version.incr(cur_version)
|
||||
assert version.incr(cur_version).endswith(".0002")
|
||||
assert version.incr(cur_version, release="alpha").endswith("-alpha")
|
||||
assert cur_version < v1version.incr(cur_version)
|
||||
assert v1version.incr(cur_version).endswith(".0002")
|
||||
assert v1version.incr(cur_version, release="alpha").endswith("-alpha")
|
||||
|
||||
assert version.incr(cur_version, release="final").endswith(".0002")
|
||||
assert v1version.incr(cur_version, release="final").endswith(".0002")
|
||||
|
||||
pre_version = cur_version + "-beta"
|
||||
assert version.incr(pre_version, release="final").endswith(".0002")
|
||||
assert v1version.incr(pre_version, release="final").endswith(".0002")
|
||||
|
||||
|
||||
def test_bump_future():
|
||||
|
|
@ -34,7 +36,7 @@ def test_bump_future():
|
|||
future_date = dt.datetime.today() + dt.timedelta(days=300)
|
||||
future_calver = future_date.strftime("v%Y%m")
|
||||
cur_version = future_calver + ".0001"
|
||||
new_version = version.incr(cur_version)
|
||||
new_version = v1version.incr(cur_version)
|
||||
assert cur_version < new_version
|
||||
|
||||
|
||||
|
|
@ -42,11 +44,11 @@ def test_bump_random(monkeypatch):
|
|||
cur_date = dt.date(2016, 1, 1) + dt.timedelta(days=random.randint(1, 2000))
|
||||
cur_version = cur_date.strftime("v%Y%m") + ".0001-dev"
|
||||
|
||||
monkeypatch.setattr(version, 'TODAY', cur_date)
|
||||
monkeypatch.setattr(v1version, 'TODAY', cur_date)
|
||||
|
||||
for _ in range(1000):
|
||||
cur_date += dt.timedelta(days=int((1 + random.random()) ** 10))
|
||||
new_version = version.incr(
|
||||
new_version = v1version.incr(
|
||||
cur_version, release=random.choice([None, "alpha", "beta", "rc", "final", "post"])
|
||||
)
|
||||
assert cur_version < new_version
|
||||
|
|
@ -55,7 +57,7 @@ def test_bump_random(monkeypatch):
|
|||
|
||||
def test_parse_version_info():
|
||||
version_str = "v201712.0001-alpha"
|
||||
version_info = version.parse_version_info(version_str)
|
||||
version_info = v1version.parse_version_info(version_str)
|
||||
|
||||
# assert version_info.pep440_version == "201712.1a0"
|
||||
# assert version_info.version == "v201712.0001-alpha"
|
||||
|
|
@ -65,7 +67,7 @@ def test_parse_version_info():
|
|||
assert version_info.tag == "alpha"
|
||||
|
||||
version_str = "v201712.0001"
|
||||
version_info = version.parse_version_info(version_str)
|
||||
version_info = v1version.parse_version_info(version_str)
|
||||
|
||||
# assert version_info.pep440_version == "201712.1"
|
||||
# assert version_info.version == "v201712.0001"
|
||||
|
|
@ -77,7 +79,7 @@ def test_parse_version_info():
|
|||
|
||||
def test_readme_pycalver1():
|
||||
version_str = "v201712.0001-alpha"
|
||||
version_info = patterns.PYCALVER_RE.match(version_str).groupdict()
|
||||
version_info = v1patterns.PYCALVER_RE.match(version_str).groupdict()
|
||||
|
||||
assert version_info == {
|
||||
'pycalver' : "v201712.0001-alpha",
|
||||
|
|
@ -93,7 +95,7 @@ def test_readme_pycalver1():
|
|||
|
||||
def test_readme_pycalver2():
|
||||
version_str = "v201712.0033"
|
||||
version_info = patterns.PYCALVER_RE.match(version_str).groupdict()
|
||||
version_info = v1patterns.PYCALVER_RE.match(version_str).groupdict()
|
||||
|
||||
assert version_info == {
|
||||
'pycalver' : "v201712.0033",
|
||||
|
|
@ -109,40 +111,40 @@ def test_readme_pycalver2():
|
|||
|
||||
def test_parse_error_empty():
|
||||
try:
|
||||
version.parse_version_info("")
|
||||
v1version.parse_version_info("")
|
||||
assert False
|
||||
except version.PatternError as err:
|
||||
except v1version.PatternError as err:
|
||||
assert "Invalid version string" in str(err)
|
||||
|
||||
|
||||
def test_parse_error_noprefix():
|
||||
try:
|
||||
version.parse_version_info("201809.0002")
|
||||
v1version.parse_version_info("201809.0002")
|
||||
assert False
|
||||
except version.PatternError as err:
|
||||
except v1version.PatternError as err:
|
||||
assert "Invalid version string" in str(err)
|
||||
|
||||
|
||||
def test_parse_error_nopadding():
|
||||
try:
|
||||
version.parse_version_info("v201809.2b0")
|
||||
v1version.parse_version_info("v201809.2b0")
|
||||
assert False
|
||||
except version.PatternError as err:
|
||||
except v1version.PatternError as err:
|
||||
assert "Invalid version string" in str(err)
|
||||
|
||||
|
||||
def test_part_field_mapping():
|
||||
a_names = set(version.PATTERN_PART_FIELDS.keys())
|
||||
b_names = set(patterns.PART_PATTERNS.keys())
|
||||
c_names = set(patterns.COMPOSITE_PART_PATTERNS.keys())
|
||||
def test_part_field_mapping_v1():
|
||||
a_names = set(v1version.PATTERN_PART_FIELDS.keys())
|
||||
b_names = set(v1patterns.PART_PATTERNS.keys())
|
||||
c_names = set(v1patterns.COMPOSITE_PART_PATTERNS.keys())
|
||||
|
||||
a_extra_names = a_names - b_names
|
||||
assert not any(a_extra_names), sorted(a_extra_names)
|
||||
b_extra_names = b_names - (a_names | c_names)
|
||||
assert not any(b_extra_names), sorted(b_extra_names)
|
||||
|
||||
a_fields = set(version.PATTERN_PART_FIELDS.values())
|
||||
b_fields = set(version.VersionInfo._fields)
|
||||
a_fields = set(v1version.PATTERN_PART_FIELDS.values())
|
||||
b_fields = set(v1version.VersionInfo._fields)
|
||||
|
||||
a_extra_fields = a_fields - b_fields
|
||||
b_extra_fields = b_fields - a_fields
|
||||
|
|
@ -150,8 +152,18 @@ def test_part_field_mapping():
|
|||
assert not any(b_extra_fields), sorted(b_extra_fields)
|
||||
|
||||
|
||||
def test_part_field_mapping_v2():
|
||||
a_names = set(v2version.PATTERN_PART_FIELDS.keys())
|
||||
b_names = set(v2patterns.PART_PATTERNS.keys())
|
||||
|
||||
a_extra_names = a_names - b_names
|
||||
assert not any(a_extra_names), sorted(a_extra_names)
|
||||
b_extra_names = b_names - a_names
|
||||
assert not any(b_extra_names), sorted(b_extra_names)
|
||||
|
||||
|
||||
def vnfo(**field_values):
|
||||
return version._parse_field_values(field_values)
|
||||
return v1version._parse_field_values(field_values)
|
||||
|
||||
|
||||
PARSE_VERSION_TEST_CASES = [
|
||||
|
|
@ -174,7 +186,7 @@ PARSE_VERSION_TEST_CASES = [
|
|||
|
||||
@pytest.mark.parametrize("pattern_str, line, expected_vinfo", PARSE_VERSION_TEST_CASES)
|
||||
def test_parse_versions(pattern_str, line, expected_vinfo):
|
||||
pattern = patterns.compile_pattern(pattern_str)
|
||||
pattern = v1patterns.compile_pattern(pattern_str)
|
||||
version_match = pattern.regexp.search(line)
|
||||
|
||||
if expected_vinfo is None:
|
||||
|
|
@ -184,6 +196,6 @@ def test_parse_versions(pattern_str, line, expected_vinfo):
|
|||
assert version_match is not None
|
||||
|
||||
version_str = version_match.group(0)
|
||||
version_info = version.parse_version_info(version_str, pattern_str)
|
||||
version_info = v1version.parse_version_info(version_str, pattern_str)
|
||||
|
||||
assert version_info == expected_vinfo
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue