mirror of
https://github.com/TECHNOFAB11/bumpver.git
synced 2025-12-12 14:30:09 +01:00
readme updates
This commit is contained in:
parent
b466ca9d39
commit
fd1b7bd05f
1 changed files with 147 additions and 134 deletions
281
README.md
281
README.md
|
|
@ -8,7 +8,7 @@
|
||||||
# [PyCalVer: Automatic Calendar Versioning][url_repo]
|
# [PyCalVer: Automatic Calendar Versioning][url_repo]
|
||||||
|
|
||||||
|
|
||||||
PyCalVer is a CLI-tool to search and replace version strings ([calver][url_calver_org], [semver][url_semver_org] or other) in your project files.
|
PyCalVer is a CLI-tool to search and replace version strings in your project files ([calver][url_calver_org], [semver][url_semver_org] or otherwise) .
|
||||||
|
|
||||||
[url_repo]: https://gitlab.com/mbarkhau/pycalver
|
[url_repo]: https://gitlab.com/mbarkhau/pycalver
|
||||||
[url_calver_org]: https://calver.org/
|
[url_calver_org]: https://calver.org/
|
||||||
|
|
@ -101,6 +101,123 @@ Code Quality/CI:
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Search and Replace
|
||||||
|
|
||||||
|
With PyCalVer, you only have to specify one `version_pattern` which is used both to search for version strings as well as to generate the replacement when you do `pycalver bump`. Compare this e.g. to `bumpversion` where you declare separate configurations for `parse` and `serialize`.
|
||||||
|
|
||||||
|
```
|
||||||
|
[bumpversion]
|
||||||
|
current_version = 1.alpha
|
||||||
|
parse = (?P<major>\d+)\.(?P<release>.*)
|
||||||
|
serialize =
|
||||||
|
{major}.{release}
|
||||||
|
{major}
|
||||||
|
```
|
||||||
|
|
||||||
|
A similar version schema with PyCalVer would be:
|
||||||
|
|
||||||
|
```
|
||||||
|
[pycalver]
|
||||||
|
current_version = 1.alpha
|
||||||
|
version_pattern = MAJOR.RELEASE
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly you must specify file specific search and replace strings.
|
||||||
|
|
||||||
|
```
|
||||||
|
[bumpversion:file:requirements.txt]
|
||||||
|
search = MyProject=={current_version}
|
||||||
|
replace = MyProject=={new_version}
|
||||||
|
```
|
||||||
|
|
||||||
|
The same with PyCalVer would be:
|
||||||
|
|
||||||
|
```
|
||||||
|
[pycalver:file_patterns]
|
||||||
|
requirements.txt
|
||||||
|
MyProject=={version}
|
||||||
|
```
|
||||||
|
|
||||||
|
The string `{version}` is a placeholder which references whatever you specified in your `version_pattern`.
|
||||||
|
You can also be explicit and write the expanded version yourself if you prefer:
|
||||||
|
|
||||||
|
```
|
||||||
|
[pycalver:file_patterns]
|
||||||
|
requirements.txt
|
||||||
|
MyProject==MAJOR.RELEASE
|
||||||
|
```
|
||||||
|
|
||||||
|
> You may be asking at this point, "what if I want to match `MAJOR.RELEASE` as a literal string?".
|
||||||
|
> Well, tough luck. Realistically speaking, this has not been an issue.
|
||||||
|
|
||||||
|
In other words, you don't specify regular expressions manually, they are generated for by PyCalVer based on the parts defined below. Everything except for a valid part (in all caps) is treated as literal text.
|
||||||
|
|
||||||
|
### Patterns/Parts
|
||||||
|
|
||||||
|
> These patterns are closely based on [calver.org][url_calver_org_scheme].
|
||||||
|
|
||||||
|
[url_calver_org_scheme]: https://calver.org/#scheme
|
||||||
|
|
||||||
|
| part | range / example(s) | comment |
|
||||||
|
|-----------|---------------------------|--------------------------------------------|
|
||||||
|
| `YYYY` | 2019, 2020... | Full year, based on `strftime('%Y')` |
|
||||||
|
| `YY` | 18, 19..99, 1, 2 | Short year, based on `int(strftime('%y'))` |
|
||||||
|
| `MM` | 9, 10, 11, 12 | Month, based on `int(strftime('%m'))` |
|
||||||
|
| `DD` | 1, 2, 3..31 | Day, based on `int(strftime('%d'))` |
|
||||||
|
| `MAJOR` | 0..9, 10..99, 100.. | `pycalver bump --major` |
|
||||||
|
| `MINOR` | 0..9, 10..99, 100.. | `pycalver bump --minor` |
|
||||||
|
| `PATCH` | 0..9, 10..99, 100.. | `pycalver bump --patch` |
|
||||||
|
| `RELEASE` | alpha, beta, rc, post | `--release=<tag>` |
|
||||||
|
| `PYTAG` | a, b, rc, post | `--release=<tag>` |
|
||||||
|
| `NUM` | 0, 1, 2... | `-r/--release-num` |
|
||||||
|
| `BUILD` | 1001, 1002 .. 1999, 22000 | build number (maintains lexical order) |
|
||||||
|
| `INC0` | 0, 1, 2... | 0-based auto incrementing number |
|
||||||
|
| `INC1` | 1, 2... | 1-based auto incrementing number |
|
||||||
|
|
||||||
|
|
||||||
|
The above are the most commonly used. The following are also available, but you should be aware of the [Normalization Caveats](#normalization-caveats) if you want to use them.
|
||||||
|
|
||||||
|
|
||||||
|
| part | range / example(s) | comment |
|
||||||
|
|--------|---------------------|----------------------------------------------|
|
||||||
|
| `Q` | 1, 2, 3, 4 | Quarter |
|
||||||
|
| `0Y` | 18, 19..99, 01, 02 | Short Year `strftime('%y')`(zero-padded) |
|
||||||
|
| `0M` | 09, 10, 11, 12 | Month `strftime('%m')` (zero-padded) |
|
||||||
|
| `0D` | 01, 02, 03..31 | Day `strftime('%d')` (zero-padded) |
|
||||||
|
| `JJJ` | 1,2,3..366 | Day of year `int(strftime('%j'))` |
|
||||||
|
| `00J` | 001, 002..366 | Day of year `strftime('%j')` (zero-padded) |
|
||||||
|
| `WW` | 0, 1, 2..52 | Week number¹ `int(strftime('%W'))` |
|
||||||
|
| `0W` | 00, 01, 02..52 | Week number¹ `strftime('%W')` (zero-padded) |
|
||||||
|
| `UU` | 0, 1, 2..52 | Week number² `int(strftime('%U'))` |
|
||||||
|
| `0U` | 00, 01, 02..52 | Week number² `strftime('%U')` (zero-padded) |
|
||||||
|
| `VV` | 1, 2..53 | Week number¹³ `int(strftime('%V'))` |
|
||||||
|
| `0V` | 01, 02..53 | Week number¹³ `strftime('%V')` (zero-padded) |
|
||||||
|
| `GGGG` | 2019, 2020... | `strftime("%G")` ISO 8601 week-based year |
|
||||||
|
| `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 |
|
||||||
|
|
||||||
|
- ¹ Monday is the first day of the week.
|
||||||
|
- ² Sunday is the first day of the week.
|
||||||
|
- ³ ISO 8601 week. Week 1 contains Jan 4th.
|
||||||
|
|
||||||
|
> On 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?
|
||||||
|
>
|
||||||
|
> If you use `VV`/`0V`, be aware that you cannot also use `YYYY`.
|
||||||
|
> Instead use `GGGG`. This is to avoid an edge case where your version
|
||||||
|
> number would run backwards if it was created around New Year.
|
||||||
|
|
||||||
|
|
||||||
|
### Rollover
|
||||||
|
|
||||||
|
TODO
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
The fastest way to setup a project is to use `pycalver init`.
|
The fastest way to setup a project is to use `pycalver init`.
|
||||||
|
|
@ -242,116 +359,7 @@ ERROR - Pattern compiles to regex 'img\.shields\.io/static/v1\.svg\?label=PyCa
|
||||||
|
|
||||||
The internally used regular expression is also shown, which you can use to debug the issue, for example on [regex101.com](https://regex101.com/r/ajQDTz/2).
|
The internally used regular expression is also shown, which you can use to debug the issue, for example on [regex101.com](https://regex101.com/r/ajQDTz/2).
|
||||||
|
|
||||||
|
TODO Update above link
|
||||||
### Pattern Search and Replacement
|
|
||||||
|
|
||||||
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` |
|
|
||||||
| `MAJOR` | 0..9, 10..99, 100.. | `--major` |
|
|
||||||
| `MINOR` | 0..9, 10..99, 100.. | `-m/--minor` |
|
|
||||||
| `PATCH` | 0..9, 10..99, 100.. | `-p/--patch` |
|
|
||||||
| `INC0` | 0, 1, 2... | |
|
|
||||||
| `INC1` | 1, 2... | |
|
|
||||||
| `BUILD` | 0011, 1001, 1002, .. | build number (lexid) |
|
|
||||||
| `BLD` | 11, 1001, 1002, .. | zero truncated `BUILD` |
|
|
||||||
| `RELEASE` | alpha, beta, rc | `--release=<tag>` |
|
|
||||||
| `PYTAG` | a, b, rc | `--release=<tag>` |
|
|
||||||
| `NUM` | 0, 1, 2... | `-r/--release-num` |
|
|
||||||
|
|
||||||
|
|
||||||
### 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 | `%V` iso_week |
|
|
||||||
| `GGGG` | 2019, 2020... | `strftime("%G")` ISO 8601 week-based year |
|
|
||||||
| `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[-RELEASE]`
|
|
||||||
- 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.
|
|
||||||
|
|
||||||
It may also be confusing to your users if they a list of version numbers, sorted lexiographically by some tool (e.g. a list of git tags) and a newer version is listed after older versions like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
3.9.1
|
|
||||||
3.8.1
|
|
||||||
3.8.0
|
|
||||||
3.10.0
|
|
||||||
```
|
|
||||||
|
|
||||||
If you wish to avoid this, you should use a pattern which maintains lexiographical ordering.
|
|
||||||
|
|
||||||
|
|
||||||
| pattern | example | lexio. | PEP440 | lexio. |
|
|
||||||
|---------------------------|---------|--------|--------|--------|
|
|
||||||
| `YYYY0M.BUILD[-RELEASE]` | | yes | | yes |
|
|
||||||
| `YYYY.BUILD[-RELEASE]` | | yes | | yes |
|
|
||||||
| `YYYY0M.MINOR[-RELEASE]` | | yes² | | yes |
|
|
||||||
| `YY0M.BUILD[-RELEASE]` | | yes¹ | | yes¹ |
|
|
||||||
| `YYYY.MM.MINOR[-RELEASE]` | | no | | no |
|
|
||||||
| `YYYY.0M.MINOR[-RELEASE]` | | yes² | | no |
|
|
||||||
| `YYYY.WW.MINOR[-RELEASE]` | | no | | no |
|
|
||||||
| `YYYY.0W.MINOR[-RELEASE]` | | yes² | | no |
|
|
||||||
| `YYYY.0M.0D` | | yes | | no |
|
|
||||||
| `YYYY.MM.DD` | | no | | no |
|
|
||||||
| `vYYYY.0W` | | yes | | no |
|
|
||||||
| `vYYYY.WW` | | no | | no |
|
|
||||||
| `YYYY.0M` | | yes | | no |
|
|
||||||
| `YYYY.MM` | | no | | 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
|
### Legacy Patterns
|
||||||
|
|
||||||
> These patterns use curly braces `{}` and were the initial implementation. They are still supported and still follow their original semantics.
|
> These patterns use curly braces `{}` and were the initial implementation. They are still supported and still follow their original semantics.
|
||||||
|
|
@ -493,12 +501,15 @@ the local checkout, the same version might be generated for
|
||||||
different commits.
|
different commits.
|
||||||
|
|
||||||
To avoid this issue, pycalver treats VCS tags as the canonical /
|
To avoid this issue, pycalver treats VCS tags as the canonical /
|
||||||
[SSOT][ssot_ref] for the most recent version and attempts to
|
[SSOT][url_ssot] for the most recent version and attempts to
|
||||||
change this state in the most atomic way possible. This is why
|
change this state in the most atomic way possible. This is why
|
||||||
some actions of the `pycalver` command can take a while, as it is
|
some actions of the `pycalver` command can take a while, as it is
|
||||||
synchronizing with the remote repository to get the most recent
|
synchronizing with the remote repository to get the most recent
|
||||||
versions and to push any new version tags as soon as possible.
|
versions and to push any new version tags as soon as possible.
|
||||||
|
|
||||||
|
[url_ssot]: https://en.wikipedia.org/wiki/Single_source_of_truth
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### The Current Version
|
### The Current Version
|
||||||
|
|
||||||
|
|
@ -689,9 +700,12 @@ Options:
|
||||||
|
|
||||||
<!-- END pycalver bump --help -->
|
<!-- END pycalver bump --help -->
|
||||||
|
|
||||||
<!-- BEGIN pycalver bump --help -->
|
### Related Projects/Alternatives
|
||||||
|
|
||||||
|
The bump2version project maintains a good list of alternative and related projects: [bump2version/RELATED.md][url_bump2version_related]
|
||||||
|
|
||||||
|
[url_bump2version_related] https://github.com/c4urself/bump2version/blob/master/RELATED.md
|
||||||
|
|
||||||
<!-- END pycalver --help -->
|
|
||||||
|
|
||||||
|
|
||||||
## The PyCalVer Format
|
## The PyCalVer Format
|
||||||
|
|
@ -705,7 +719,7 @@ The PyCalVer format for version strings has three parts:
|
||||||
| | o Release Tag (optional)
|
| | o Release Tag (optional)
|
||||||
| | |
|
| | |
|
||||||
---+--- --+-- --+--
|
---+--- --+-- --+--
|
||||||
v202008 .0123 -beta
|
v202010 .1001 -beta
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -722,9 +736,9 @@ v202207.18133
|
||||||
v202207.18134
|
v202207.18134
|
||||||
```
|
```
|
||||||
|
|
||||||
This slightly verbose format was chosen in part to be distinctive from
|
This format was chosen in part to be distinctive from
|
||||||
others, so that users of your package can see at a glance that your project
|
others, so that users of your package can see at a glance that your project
|
||||||
will strive to maintain the one semantic that really matters: **newer ==
|
will strive to maintain the one semantic that really matters: **newer is
|
||||||
better**.
|
better**.
|
||||||
|
|
||||||
To convince you of the merits of not breaking things, here are some
|
To convince you of the merits of not breaking things, here are some
|
||||||
|
|
@ -805,33 +819,34 @@ To see how version strings are incremented, we can use
|
||||||
`pycalver test`:
|
`pycalver test`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ pycalver test v201801.0033-beta
|
$ pycalver test v201801.1033-beta
|
||||||
New Version: v201902.0034-beta
|
New Version: v201902.1034-beta
|
||||||
PEP440 : 201902.34b0
|
PEP440 : 201902.1034b0
|
||||||
```
|
```
|
||||||
|
|
||||||
This is the simple case:
|
This is the simple case:
|
||||||
|
|
||||||
- The calendar component is updated to the current year and
|
- The calendar component is updated to the current year and month.
|
||||||
month.
|
|
||||||
- The build number is incremented by 1.
|
- The build number is incremented by 1.
|
||||||
- The optional release tag is preserved as is.
|
- The optional release tag is preserved as is.
|
||||||
|
|
||||||
You can explicitly update the release tag by using the
|
You can explicitly update the release tag by using the `--release=<tag>` argument:
|
||||||
`--release=<tag>` argument:
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ pycalver test v201801.0033-alpha --release=beta
|
$ pycalver test v201801.1033-alpha --release=beta
|
||||||
New Version: v201902.0034-beta
|
New Version: v201902.1034-beta
|
||||||
PEP440 : 201902.34b0
|
PEP440 : 201902.1034b0
|
||||||
|
|
||||||
$ pycalver test v201902.0034-beta --release=final
|
$ pycalver test v201902.1034-beta --release=final
|
||||||
New Version: v201902.0035
|
New Version: v201902.1035
|
||||||
PEP440 : 201902.35
|
PEP440 : 201902.1035
|
||||||
```
|
```
|
||||||
|
|
||||||
To maintain lexical ordering of version numbers, the version number is padded
|
To maintain lexical ordering of version numbers, the version number is padded with extra zeros using [Lexical Ids][url_pypi_lexid].
|
||||||
with extra zeros (see [Lexical Ids](#lexical-ids) ).
|
This means that the expression `older_id < newer_id` will always be true, whether you are dealing with integers or strings.
|
||||||
|
|
||||||
|
[url_pypi_lexid]: https://pypi.org/project/lexid/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Semantics of PyCalVer
|
## Semantics of PyCalVer
|
||||||
|
|
@ -1103,8 +1118,6 @@ artifact of a package, eg. a `.whl` file.
|
||||||
|
|
||||||
[setuptools_ref]: https://setuptools.readthedocs.io/en/latest/setuptools.html#specifying-your-project-s-version
|
[setuptools_ref]: https://setuptools.readthedocs.io/en/latest/setuptools.html#specifying-your-project-s-version
|
||||||
|
|
||||||
[ssot_ref]: https://en.wikipedia.org/wiki/Single_source_of_truth
|
|
||||||
|
|
||||||
[pep_440_ref]: https://www.python.org/dev/peps/pep-0440/
|
[pep_440_ref]: https://www.python.org/dev/peps/pep-0440/
|
||||||
|
|
||||||
[pep_440_normalzation_ref]: https://www.python.org/dev/peps/pep-0440/#id31
|
[pep_440_normalzation_ref]: https://www.python.org/dev/peps/pep-0440/#id31
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue