diff --git a/CHANGELOG.md b/CHANGELOG.md index dbfe0d8..8c5fb41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ # Changelog for https://github.com/mbarkhau/pycalver -## NEXT +## BumpVer 2020.1042-beta + +Rename package and module from PyCalVer to BumpVer. This name change is due to confusion that this project is either Python specific, or only suitible for CalVer versioning schemes, neither of which is the case. This release includes a new syntax for patterns. @@ -34,7 +36,7 @@ The previous syntax will continue to be supported, but all documentation has bee - New [gitlab#9][gitlab_i9]: Make commit message configurable. - Fix [gitlab#12][gitlab_i12]: Error with sorting non-lexical version tags (e.g. SemVer). - Fix [gitlab#11][gitlab_i11]: Show regexp when `--verbose` is used. -- Fix [gitlab#8][gitlab_i8]: `pycalver push ` will now also push HEAD (previously only the tag itself was pushed). +- Fix [gitlab#8][gitlab_i8]: `bumpver update` will now also push HEAD (previously only the tag itself was pushed). - Fix: Disallow `--release=dev`. The semantics of a `dev` releases are different than for other release tags and further development would be required to support them correctly. - Fix: Entries in `file_patterns` were ignored if there were multiple entries for the same file. @@ -51,12 +53,12 @@ Many thanks to contributors of this release: @LucidOne, @khanguslee, @chaudum [gitlab_i8]: https://gitlab.com/mbarkhau/pycalver/-/issues/8 -## v201907.0036 +## PyCalVer v201907.0036 - Fix: Don't use git/hg command if `commit=False` is configured (thanks @valentin87) -## v201907.0035 +## PyCalVer v201907.0035 - Fix [gitlab#6][gitlab_i6]: Add parts `{month_short}`, `{dom_short}`, `{doy_short}`. - Fix [gitlab#5][gitlab_i5]: Better warning when using bump with SemVer (one of --major/--minor/--patch is required) @@ -67,43 +69,43 @@ Many thanks to contributors of this release: @LucidOne, @khanguslee, @chaudum [gitlab_i4]: https://gitlab.com/mbarkhau/pycalver/-/issues/4 -## v201903.0030 +## PyCalVer v201903.0030 - Fix: Use pattern from config instead of hard-coded {pycalver} pattern. - Fix: Better error messages for git/hg issues. - Add: Implicit default pattern for config file. -## v201903.0028 +## PyCalVer v201903.0028 - Fix: Add warnings when configured files are not under version control. - Add: Colored output for bump --dry -## v201902.0027 +## PyCalVer v201902.0027 - Fix: Allow --release=post - Fix: Better error reporting for bad patterns - Fix: Regex escaping issue with "?" -## v201902.0024 +## PyCalVer v201902.0024 - Added: Support for globs in file patterns. - Fixed: Better error reporting for invalid config. -## v201902.0020 +## PyCalVer v201902.0020 - Added: Support for many more custom version patterns. -## v201812.0018 +## PyCalVer v201812.0018 - Fixed: Better handling of pattern replacements with "-final" releases. -## v201812.0017 +## PyCalVer v201812.0017 - Fixed [github#2]. `pycalver init` was broken. - Fixed pattern escaping issues. @@ -113,7 +115,7 @@ Many thanks to contributors of this release: @LucidOne, @khanguslee, @chaudum [gihlab_i2]: https://github.com/mbarkhau/pycalver/-/issues/2 -## v201812.0011-beta +## PyCalVer v201812.0011-beta - Add version tags using git/hg. - Use git/hg tags as SSOT for most recent version. @@ -121,6 +123,6 @@ Many thanks to contributors of this release: @LucidOne, @khanguslee, @chaudum - Move to https://gitlab.com/mbarkhau/pycalver -## v201809.0001-alpha +## PyCalVer v201809.0001-alpha - Initial release diff --git a/Makefile b/Makefile index 9139654..1d477a6 100644 --- a/Makefile +++ b/Makefile @@ -74,6 +74,6 @@ pycalver_deps.svg: ## Update cli reference in README.md -README.md: src/pycalver/__main__.py scripts/update_readme_examples.py Makefile +README.md: src/pycalver2/cli.py scripts/update_readme_examples.py Makefile @git add README.md @$(DEV_ENV)/bin/python scripts/update_readme_examples.py diff --git a/README.md b/README.md index 6806f98..aa729cb 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,28 @@

- logo + logo

-# [Python CalVer: Automatic Calendar Versioning][url_repo] +# [BumpVer: Automatic Versioning][url_repo] -Python CalVer provides the CLI command `calver`. You can use it to search and update version strings in your project files. It has a flexible pattern syntax to support many version string schemes ([calver][url_calver_org], [semver][url_semver_org] or otherwise). PyCalVer features: +With the CLI command `bumpver`, you can search for and update version strings in your project files. It has a flexible pattern syntax to support many version schemes ([SemVer][url_semver_org], [CalVer][url_calver_org] or otherwise). BumpVer features: - Configurable version patterns -- Git, Mercurial or no VCS -- Operates only on plaintext files, so it can be used for any project, not just python projects. +- Optional Git or Mercurial integration +- Works with plaintext, so you can use it with any project. -[url_repo]: https://gitlab.com/mbarkhau/pycalver -[url_calver_org]: https://calver.org/ +[url_repo]: https://gitlab.com/mbarkhau/bumpver [url_semver_org]: https://semver.org/ +[url_calver_org]: https://calver.org/ Project/Repo: [![MIT License][img_license]][url_license] [![Supported Python Versions][img_pyversions]][url_pyversions] -[![CalVer v2020.1041-beta][img_version]][url_version] +[![CalVer 2020.1041-beta][img_version]][url_version] [![PyPI Releases][img_pypi]][url_pypi] [![PyPI Downloads][img_downloads]][url_downloads] @@ -40,310 +40,385 @@ Code Quality/CI: | Manuel Barkhau (mbarkhau@gmail.com) | author/maintainer | 2018-09 | - | +[img_github_build]: https://github.com/mbarkhau/bumpver/workflows/CI/badge.svg +[url_github_build]: https://github.com/mbarkhau/bumpver/actions?query=workflow%3ACI -[img_github_build]: https://github.com/mbarkhau/pycalver/workflows/CI/badge.svg -[url_github_build]: https://github.com/mbarkhau/pycalver/actions?query=workflow%3ACI +[img_gitlab_build]: https://gitlab.com/mbarkhau/bumpver/badges/master/pipeline.svg +[url_gitlab_build]: https://gitlab.com/mbarkhau/bumpver/pipelines -[img_gitlab_build]: https://gitlab.com/mbarkhau/pycalver/badges/master/pipeline.svg -[url_gitlab_build]: https://gitlab.com/mbarkhau/pycalver/pipelines - -[img_codecov]: https://gitlab.com/mbarkhau/pycalver/badges/master/coverage.svg -[url_codecov]: https://mbarkhau.gitlab.io/pycalver/cov +[img_codecov]: https://gitlab.com/mbarkhau/bumpver/badges/master/coverage.svg +[url_codecov]: https://mbarkhau.gitlab.io/bumpver/cov [img_license]: https://img.shields.io/badge/License-MIT-blue.svg -[url_license]: https://gitlab.com/mbarkhau/pycalver/blob/master/LICENSE +[url_license]: https://gitlab.com/mbarkhau/bumpver/blob/master/LICENSE [img_mypy]: https://img.shields.io/badge/mypy-checked-green.svg -[url_mypy]: https://mbarkhau.gitlab.io/pycalver/mypycov +[url_mypy]: https://mbarkhau.gitlab.io/bumpver/mypycov [img_style]: https://img.shields.io/badge/code%20style-%20sjfmt-f71.svg [url_style]: https://gitlab.com/mbarkhau/straitjacket/ -[img_downloads]: https://pepy.tech/badge/pycalver/month -[url_downloads]: https://pepy.tech/project/pycalver +[img_downloads]: https://pepy.tech/badge/bumpver/month +[url_downloads]: https://pepy.tech/project/bumpver -[img_version]: https://img.shields.io/static/v1.svg?label=CalVer&message=v2020.1041-beta&color=blue -[url_version]: https://pypi.org/project/pycalver/ +[img_version]: https://img.shields.io/static/v1.svg?label=CalVer&message=2020.1041-beta&color=blue +[url_version]: https://pypi.org/project/bumpver/ [img_pypi]: https://img.shields.io/badge/PyPI-wheels-green.svg -[url_pypi]: https://pypi.org/project/pycalver/#files +[url_pypi]: https://pypi.org/project/bumpver/#files -[img_pyversions]: https://img.shields.io/pypi/pyversions/pycalver.svg -[url_pyversions]: https://pypi.python.org/pypi/pycalver +[img_pyversions]: https://img.shields.io/pypi/pyversions/bumpver.svg +[url_pyversions]: https://pypi.python.org/pypi/bumpver + -[](TOC) + -- [PyCalVer: Automatic Calendar Versioning](#pycalver-automatic-calendar-versioning) - - [Usage](#usage) - - [Configuration](#configuration) - - [Pattern Search and Replacement](#pattern-search-and-replacement) - - [Week Numbering](#week-numbering) - - [Normalization Caveats](#normalization-caveats) - - [Legacy Patterns](#legacy-patterns) - - [Pattern Usage](#pattern-usage) - - [Examples](#examples) - - [Version State](#version-state) - - [The Current Version](#the-current-version) - - [Bump It Up](#bump-it-up) - - [Config Parameters](#config-parameters) - - [CLI Reference](#cli-reference) - - [The PyCalVer Format](#the-pycalver-format) - - [Parsing](#parsing) - - [Incrementing Behaviour](#incrementing-behaviour) - - [Semantics of PyCalVer](#semantics-of-pycalver) - - [Pitch](#pitch) - - [blah](#blah) - - [Intentional Breaking Changes](#intentional-breaking-changes) - - [Costs and Benefits](#costs-and-benefits) - - [Unintentional Breaking Changes](#unintentional-breaking-changes) - - [Pinning is not a Panacea](#pinning-is-not-a-panacea) - - [Zeno's 1.0 and The Eternal Beta](#zenos-10-and-the-eternal-beta) +- [Overview](#overview) + - [Search and Replace](#search-and-replace) + - [Related Projects/Alternatives](#related-projectsalternatives) +- [Example Usage](#example-usage) + - [Testing a version pattern](#testing-a-version-pattern) + - [SemVer: `MAJOR`/`MINOR`/`PATCH`](#semver-majorminorpatch) + - [Auto Increment Parts: `BUILD`/`INC0`/`INC1`](#auto-increment-parts-buildinc0inc1) + - [Persistent Parts: `BUILD`/`TAG`/`PYTAG`](#persistent-parts-buildtagpytag) + - [Searching for Patterns with `grep`](#searching-for-patterns-with-grep) +- [Reference](#reference) + - [Command Line](#command-line) + - [Part Overview](#part-overview) + - [Normalization Caveats](#normalization-caveats) + - [Pattern Examples](#pattern-examples) + - [Week Numbering](#week-numbering) +- [Configuration](#configuration) + - [Configuration Setup](#configuration-setup) + - [Debugging Configuration](#debugging-configuration) +- [Bump It Up](#bump-it-up) + - [Version State](#version-state) + - [The Current Version](#the-current-version) + - [Dry Mode](#dry-mode) + - [VCS Parameters (git/mercurial)](#vcs-parameters-gitmercurial) +- [Depricated Pattern Syntax](#depricated-pattern-syntax) -[](TOC) + ## Overview ### Search and Replace -With `calver`, you configure a single `version_pattern` which is then used to +With `bumpver`, you configure a single `version_pattern` which is then used to 1. Search for version strings in your project files -2. Replace these occurrences with an updated/bumped version number. +2. Replace these with an updated/bumped version number. Your configuration might look something like this: ``` -[calver] -current_version = "2020.9.0" -version_pattern = "YYYY.MM.PATCH" +[bumpver] +current_version = "1.5.2" +version_pattern = "MAJOR.MINOR.PATCH" -[calver:file_patterns] +[bumpver:file_patterns] +setup.py + version="{version}", src/mymodule/__init__.py __version__ = "{version}" -src/mymodule/__main__.py - @click.version_option(version="{version}") -setup.py - version="{version}", ``` -> Throughout the examples, we use the `--date` argument. Without this argument `calver` will just use the current UTC date. We use it here so that you can easily reproduce the examples. - -Using this configuration, the output of `calver bump --dry` might look something like this: +Using this configuration, the output of `bumpver update --dry` might look something like this: ```diff -$ calver bump --date 2020-10-21 --dry -INFO - fetching tags from remote (to turn off use: -n / --no-fetch) -INFO - Old Version: 2020.9.0 -INFO - New Version: 2020.10.0 +$ bumpver update --patch --dry +INFO - Old Version: 1.5.2 +INFO - New Version: 1.5.3 --- setup.py +++ setup.py @@ -63,7 +63,7 @@ - setuptools.setup( name="mymodule", -- version="2020.9.0", -+ version="2020.10.0", +- version="1.5.2", ++ version="1.5.3", description=description, - long_description=long_description, --- src/mymodule/__init__.py +++ src/mymodule/__init__.py @@ -3,3 +3,3 @@ --__version__ = "2020.9.0" -+__version__ = "2020.10.0" - - ---- src/mymodule/__main__.py -+++ src/mymodule/__main__.py -@@ -101,7 +101,7 @@ - - @click.group() --@click.version_option(version="2020.9.0") -+@click.version_option(version="2020.10.0") - @click.help_option() - @click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.") +-__version__ = "1.5.2" ++__version__ = "1.5.3" ``` +### Name Change PyCalVer -> BumpVer + +This project was originally developed under the name PyCalVer, with the intent to support various CalVer schemes. The package and CLI command have since been renamed from PyCalVer/`pycalver` to BumpVer/`bumpver`. + +This name change is due to confusion that this project is either Python specific, or only suitible for CalVer versioning schemes, neither of which is the case. + ### Related Projects/Alternatives -If PyCalVer does not serve your purposes, you may wish to look at the [bump2version][url_bump2version] project, by which PyCalVer was heavily inspired. You may also wish to take a look at their list of related projects: [bump2version/RELATED.md][url_bump2version_related] +If you are looking for an alternative, BumpVer was heavily influenced by [bumpversion / bump2version][url_bump2version]. You may also wish to take a look at their list of related projects: [bump2version/RELATED.md][url_bump2version_related] [url_bump2version] https://github.com/c4urself/bump2version/ [url_bump2version_related] https://github.com/c4urself/bump2version/blob/master/RELATED.md + ## Example Usage -### Testing a version pattern - -You can validate a pattern and how it is incremented using `calver test`. +You can override the date used by `bumpver` with the `--date=` option. Adding this every time would be distracting, so the examples assume the following date: ```shell -$ calver test --date 2020-09-22 '2020.37' 'YYYY.WW' -New Version: 2020.38 -PEP440 : 2020.38 +$ date --iso +2020-10-15 +``` -$ calver test --date 2020-09-22 '2020.37' 'YYYY.MM' # expected to fail because 37 is not valid for part MM + +### Testing a `version_pattern` + +To test a `version_pattern` and how to increment it, you can use `bumpver test`: + +```shell +$ bumpver test 'v2020.37' 'vYYYY.WW' +New Version: v2020.41 +``` + +A `version_pattern` consists of three kinds of characters: + +- Literal text, such as `v`, `.`, and `-`, typically used as delimiters. +- A [valid part](#parts-overview) such as `YYYY`/`WW` in the previous example. +- Square brackets `[]` to mark an optional segment. + +The following example uses all three: `vYYYY.WW[-TAG]` + +``` + vYYYY.WW[-TAG] +literal text ^ ^ ^ +``` + +```shell +$ bumpver test 'v2020.37-beta' 'vYYYY.WW[-TAG]' +New Version: v2020.41-beta +PEP440 : 2020.41b0 +``` + +Here we see the week number changed from 37 to 41. The test command also shows the normalized version pattern according to [PEP440][pep_440_ref]. This removes the `"v"` prefix and shortens the release tag from `-beta` to `b0`. + +[pep_440_ref]: https://www.python.org/dev/peps/pep-0440/ + +To remove the release tag, use the option `--tag=final`. + +```shell +$ bumpver test 'v2020.37-beta' 'vYYYY.WW[-TAG]' --tag=final +New Version: v2020.41 +PEP440 : 2020.41 +``` + +### Using `MAJOR`/`MINOR`/`PATCH` (SemVer Parts) + +A CalVer `version_pattern` may not require any flags to determine which part should be incremented, so long as the date has changed. +With SemVer you must always specify one of `--major/--minor/--patch`. + +```shell +$ bumpver test '1.2.3' 'MAJOR.MINOR.PATCH[PYTAGNUM]' --major +New Version: 2.0.0 + +$ bumpver test '1.2.3' 'MAJOR.MINOR.PATCH[PYTAGNUM]' --minor +New Version: 1.3.0 + +$ bumpver test '1.2.3' 'MAJOR.MINOR.PATCH[PYTAGNUM]' --patch +New Version: 1.2.4 + +$ bumpver test '1.2.3' 'MAJOR.MINOR.PATCH[PYTAGNUM]' --patch --tag=beta +New Version: 1.2.4b0 + +$ bumpver test '1.2.4b0' 'MAJOR.MINOR.PATCH[PYTAGNUM]' --tag-num +New Version: 1.2.4b1 +``` + +These non date based parts also make sense for a CalVer `version_pattern`, so that you can create multiple releases in the same month. It is common to include e.g. a `PATCH` part. + +```shell +$ bumpver test '2020.10.0' 'YYYY.MM.PATCH' --patch +New Version: 2020.10.1 +``` + +Without this flag, we would get an error if the date is still in October. + +```shell +$ date --iso +2020-10-15 + +$ bumpver test '2020.10.0' 'YYYY.MM.PATCH' +ERROR - Invalid arguments or pattern, version did not change. +ERROR - Version did not change: '2020.10.0'. Invalid version and/or pattern 'YYYY.MM.PATCH'. +INFO - Perhaps try: bumpver test --patch +``` + +Once the date is in November, the `PATCH` part will roll over back to zero. This happens whenever parts to the left change (in this case the year and month), just as it does if `MAJOR` or `MINOR` were incremented in SemVer. + +```shell +$ bumpver test '2020.10.1' 'YYYY.MM.PATCH' --date 2020-11-01 +New Version: 2020.11.0 +``` + +The rollover to zero will happen even if you use the `--patch` argument, so that your first release in a month will always have a `PATCH` set to 0 instead of 1. You can make the `PATCH` part optional with `[.PATCH]` and always supply the `--patch` flag in your build script. This will cause the part to be omitted when 0 and added when > 0. + +```shell +$ bumpver test '2020.9.1' 'YYYY.MM[.PATCH]' --patch +New Version: 2020.10 + +$ bumpver test '2020.10' 'YYYY.MM[.PATCH]' --patch +New Version: 2020.10.1 + +$ bumpver test '2020.10.1' 'YYYY.MM[.PATCH]' --patch +New Version: 2020.10.2 +``` + + +With CalVer, the version is based on a calendar date, so you only have to specify such flags if you've already published a release for the current date. Without such a flag, BumpVer will show the error, that the "version did not change". + +```shell +$ bumpver test 'v2020.41-beta0' 'vYYYY.WW[-TAGNUM]' +ERROR - Invalid arguments or pattern, version did not change. +ERROR - Invalid version 'v2020.41-beta0' and/or pattern 'vYYYY.WW[-TAGNUM]'. +``` + +In this case you have to change one of the parts that are not based on a calendar date. + +```shell +$ bumpver test 'v2020.41-beta0' 'vYYYY.WW[-TAGNUM]' --tag-num +New Version: v2020.41-beta1 +PEP440 : 2020.41b1 + +$ bumpver test 'v2020.41-beta0' 'vYYYY.WW[-TAGNUM]' --tag=final +New Version: v2020.41 +PEP440 : 2020.41 +``` + +If a pattern is not applicable to a version string, then you will get an error message. + +```shell +$ bumpver test '2020.37' 'YYYY.MM' # expected to fail because 37 is not valid for part MM ERROR - Incomplete match '2020.3' for version string '2020.37' with pattern 'YYYY.MM'/'(?P[1-9][0-9]{3})\.(?P1[0-2]|[1-9])' ERROR - Invalid version '2020.37' and/or pattern 'YYYY.MM'. ``` -This illustrates that each pattern is internally translated to a regular expression which must match your version string. The `--verbose` flag shows a slightly more readable form. +This illustrates that each pattern is internally translated to a regular expression which must match the version string. The `--verbose` flag will show a verbose form of the regular expression, which may help to debug the discrepancy between the pattern and the version. ```shell -$ calver test --date 2018-09-22 'v2018.37' 'YYYY.WW' --verbose +$ bumpver test 'v2020.37' 'YYYY.WW' --verbose # missing "v" prefix INFO - Using pattern YYYY.WW INFO - regex = re.compile(r""" (?P[1-9][0-9]{3}) \. (?P5[0-2]|[1-4][0-9]|[0-9]) """, flags=re.VERBOSE) -ERROR - Invalid version string 'v2018.37' for pattern ... +ERROR - Invalid version string 'v2020.37' for pattern ... ``` -In other words, you don't specify regular expressions manually, they are generated for by PyCalVer based on the parts defined in the [Parts Overview](#parts-overview). - - -### SemVer: `MAJOR`/`MINOR`/`PATCH` - -You can do tradition SemVer without any kind of calendar component if you like. +To fix the above, you can either remove the "v" prefix from the version or add it to the pattern. ```shell -$ calver test '1.2.3' 'MAJOR.MINOR.PATCH' --patch -New Version: 1.2.4 -PEP440 : 1.2.4 - -$ calver test '1.2.3' 'MAJOR.MINOR.PATCH' --minor -New Version: 1.3.0 -PEP440 : 1.3.0 - -$ calver test '1.2.3' 'MAJOR.MINOR.PATCH' --major -New Version: 2.0.0 -PEP440 : 2.0.0 -``` - -These are the same CLI flags as are accepted by the `calver bump` command. - -In the context of a CalVer version, a typical use would be to include a `PATCH` part in your version pattern, so that you can create multiple releases in the same month. - -```shell -$ calver test --date 2018-09-22 '2018.9.0' 'YYYY.MM.PATCH' -ERROR - Invalid arguments or pattern, version did not change. -ERROR - Version did not change: '2018.9.0'. Invalid version and/or pattern 'YYYY.MM.PATCH'. -INFO - Perhaps try: calver test --patch - -$ calver test --date 2018-09-22 '2018.9.0' 'YYYY.MM.PATCH' --patch -New Version: 2018.9.1 -PEP440 : 2018.9.1 -``` - -The `PATCH` part will roll over back to zero when leading parts change (in this case the year and month). - -```shell -$ calver test --date 2018-10-22 '2018.9.1' 'YYYY.MM.PATCH' -New Version: 2018.10.0 -PEP440 : 2018.10.0 -``` - -This will happen even if you use the `--patch` argument, so that your first release of the month has a `PATCH` of 0 instead of 1. - -```shell -$ calver test --date 2018-10-22 '2018.9.1' 'YYYY.MM.PATCH' --patch -New Version: 2018.10.0 -PEP440 : 2018.10.0 +$ bumpver test 'v2020.37' 'vYYYY.WW' # added "v" prefix +New Version: v2020.41 +PEP440 : 2020.41 ``` ### Auto Increment Parts: `BUILD`/`INC0`/`INC1` -The following parts are incremented automatically, and do not use/require a CLI flag: `BUILD`/`INC0`/`INC1`. This means you can just do `calver bump` without any further CLI flags and special cases, which can simplify your build scripts. +These parts are incremented automatically, and do not use/require a CLI flag: `BUILD`/`INC0`/`INC1`. ```shell -$ calver test --date 2018-09-22 '2018.9.1' 'YYYY.MM.INC0' -New Version: 2018.9.2 -PEP440 : 2018.9.2 +$ bumpver test '2020.10.1' 'YYYY.MM.INC0' +New Version: 2020.10.2 -$ calver test --date 2018-10-22 '2018.9.2' 'YYYY.MM.INC0' -New Version: 2018.10.0 -PEP440 : 2018.10.0 - -$ calver test --date 2018-10-22 '2018.9.2' 'YYYY.MM.INC1' -New Version: 2018.10.1 -PEP440 : 2018.10.1 +$ bumpver test '2020.10.2' 'YYYY.MM.INC0' --date 2020-11-01 +New Version: 2020.11.0 ``` -If it is rare for you to make multiple releases within a given period, you can make such a part optional using the `[PART]` syntax with square brackets: +You can make the part optional using the `[PART]` syntax and it will be added/removed as needed. ```shell -$ calver test --date 2018-09-22 '2018.9' 'YYYY.MM[.INC0]' -New Version: 2018.9.1 -PEP440 : 2018.9.1 +$ bumpver test '2020.10' 'YYYY.MM[.INC0]' +New Version: 2020.10.1 -$ calver test --date 2018-10-22 '2018.9.1' 'YYYY.MM[.INC0]' -New Version: 2018.10 -PEP440 : 2018.10 +$ bumpver test '2020.10.1' 'YYYY.MM[.INC0]' --date 2020-11-01 +New Version: 2020.11 ``` -If the extra `INC0` part is needed, it is added. If the date rolls over and it's no longer needed, it is omitted. Any literal text enclosed in the brackets (such as a separator) will also be added or omitted as needed. +### Persistent Parts: `BUILD`/`TAG`/`PYTAG` -### Persistent Parts: `BUILD`/`RELEASE`/`PYTAG` - -The `BUILD` and `RELEASE` parts are not reset. Instead they are carried forward. +The `BUILD` and `TAG` parts will not rollover/reset. Instead they are carried forward from one version to the next. ```shell -$ calver test --date 2018-09-22 '201809.1051-beta' 'YYYY0M.BUILD[-RELEASE]' -New Version: 201809.1052-beta -PEP440 : 201809.1052b0 +$ bumpver test 'v2020.1051-beta' 'vYYYY.BUILD[-TAG]' +New Version: v2020.1052-beta +PEP440 : 2020.1052b0 -$ calver test --date 2018-09-22 '201809.1051-beta' 'YYYY0M.BUILD[-RELEASE]' --release rc -New Version: 201809.1052-rc -PEP440 : 201809.1052rc0 +$ bumpver test 'v2020.1051-beta' 'vYYYY.BUILD[-TAG]' --date 2021-01-01 +New Version: v2021.1052-beta +PEP440 : 2021.1052b0 + +$ bumpver test 'v2020.1051-beta' 'vYYYY.BUILD[-TAG]' --tag=rc +New Version: v2020.1052-rc +PEP440 : 2020.1052rc0 ``` -To remove a release tag, mark it as final with `--release final`. +To remove a release tag, mark it as final with `--tag=final`. ```shell -$ calver test --date 2018-09-22 '201809.1051-beta' 'YYYY0M.BUILD[-RELEASE]' --release final -New Version: 201809.1052 -PEP440 : 201809.1052 +$ bumpver test 'v2020.1051-beta' 'vYYYY.BUILD[-TAG]' --tag=final +New Version: v2020.1052 +PEP440 : 2020.1052 ``` ### Searching for Patterns with `grep` -When searching for a pattern, There are some limitations to keep in mind: - - 1. A version string cannot span multiple lines. - 2. There is no mechanism for escaping parts. - 3. Brackets `[]` can be escaped with backslash. - -Using `calver grep`, you can search for occurrences of a version pattern in your project files. +You can use `bumpver grep` to test and debug entries for your configuration. ```shell -$ calver grep '__version__ = "YYYY.MM[-RELEASENUM]"' src/module/__init__.py -src/module/__init__.py +$ bumpver grep \ + '__version__ = "YYYY.MM[-TAGNUM]"' \ + src/module/__init__.py + 3: 4: __version__ = "2020.9-beta1" 5: ``` +When searching your project files for version strings, there are some limitations to keep in mind: + + 1. A version string cannot span multiple lines. + 2. Brackets `[]` can be escaped with backslash: `\[\]`. + 3. There is no way to escape a valid part (so you cannot match the literal text `YYYY`). + Note that everything in the pattern is treated as literal text, except for a valid part (in all caps). +``` + __version__ = "YYYY.MM[-TAGNUM]" +literal text ^^^^^^^^^^^^^^^ ^ ^ ^ +``` + When you write your configuration, you can avoid repeating your version pattern in every search pattern, by using these placeholders - `{version}` - `{pep440_version}` -Applied to the above example, you can instead use this: +Applied to the above example, you can instead write this: ```shell -$ calver grep --version-pattern "YYYY.MM[-RELEASENUM]" '__version__ = "{version}"' src/module/__init__.py -src/module/__init__.py +$ bumpver grep \ + --version-pattern "YYYY.MM[-TAGNUM]" \ + '__version__ = "{version}"' \ + src/module/__init__.py + 3: 4: __version__ = "2020.9-beta1" 5: @@ -352,35 +427,35 @@ src/module/__init__.py The corresponding configuration would look like this. ```ini -[calver] +[bumpver] current_version = "2020.9-beta1" -version_pattern = "YYYY.MM[-RELEASENUM]" +version_pattern = "YYYY.MM[-TAGNUM]" ... -[calver:file_patterns] +[bumpver:file_patterns] src/module/__init__.py __version__ = "{version}" ... ``` -If your pattern produces non PEP440 version numbers, you may wish to use the placeholder `{pep440_version}` in your search pattern and specify your `--version-pattern` separately. +If you use a version pattern that is not in the PEP440 normalized form (such as the one above), you can nonetheless match version strings in your project files which *are* in the [PEP440 normalized form][url_pep_440]. To do this, you can use the placeholder `{pep440_version}` instead of the `{version}` placeholder. ```shell -$ calver grep --version-pattern "YYYY.MM[-RELEASENUM]" 'version="{pep440_version}"' setup.py +$ bumpver grep --version-pattern "YYYY.MM[-TAGNUM]" 'version="{pep440_version}"' setup.py setup.py 65: url="https://github.com/org/project", 66: version="2020.9b1", 67: description=description, ``` -The placeholder `{version}` matches `2020.9-beta1`, while the placeholder `{pep440_version}` matches `2020.9b1` (excluding the "v" prefix, the "-" separator and with a short form release tag "b1" instead of "beta1"). These two placeholders make it possible to mostly use your preferred format for version strings, but use a [PEP440][url_pep_440] compliant/normalized version string where appropriate. +The placeholder `{version}` matches `2020.9-beta1`, while the placeholder `{pep440_version}` matches `2020.9b1` (excluding the "v" prefix, the "-" separator and with a short form release tag "b1" instead of "beta1"). These two placeholders make it possible to mostly use your preferred format for version strings, but use a PEP440 compliant/normalized version string where appropriate. [url_pep_440]: https://www.python.org/dev/peps/pep-0440/ -As a further illustration of how the search and replace works, you might want use a file pattern entry to keep the year of your copyright header up to date. +As a ~~neat trick~~ further illustration of how the search and replace works, you might wish to keep the year of your copyright headers up to date. -``` -$ calver grep 'Copyright (c) 2018-YYYY' src/mymodule/*.py | head +```shell +$ bumpver grep 'Copyright (c) 2018-YYYY' src/mymodule/*.py | head src/mymodule/__init__.py 3: 4: # Copyright (c) 2018-2020 Vandelay Industries - All rights reserved. @@ -395,24 +470,40 @@ src/mymodule/config.py The corresponding configuration for this pattern would look like this. ```ini -[calver:file_patterns] +[bumpver:file_patterns] ... src/mymodule/*.py Copyright (c) 2018-YYYY Vandelay Industries - All rights reserved. ``` +Note that there must be a match for every entry in `file_patterns`. If there is no match, `bumpver` will show an error. This ensures that a pattern is not skipped when your project changes. In this case the side effect is to make sure that every file has a copyright header. + +```shell +$ bumpver update --dry +ERROR - No match for pattern 'Copyright (c) 2018-YYYY Vandelay Industries - All rights reserved.' +ERROR - +# https://regex101.com/?flavor=python&flags=gmx®ex=Copyright%5B%20%5D%5C%28c%5C%29%0A%5B%20%5D2018%5C-%0A%28%3FP%3Cyear_y%3E%5B1-9%5D%5B0-9%5D%7B3%7D%29%0A%5B%20%5DVandelay%5B%20%5DIndustries%5B%20%5D%5C-%5B%20%5DAll%5B%20%5Drights%5B%20%5Dreserved%5C. +regex = re.compile(r""" + Copyright[ ]\(c\) + [ ]2018\- + (?P[1-9][0-9]{3}) + [ ]Vandelay[ ]Industries[ ]\-[ ]All[ ]rights[ ]reserved\. +""", flags=re.VERBOSE) +ERROR - No patterns matched for file 'src/mymodule/utils.py' +``` + ## Reference ### Command Line - + ``` -$ calver --help -Usage: calver [OPTIONS] COMMAND [ARGS]... +$ bumpver --help +Usage: bumpver [OPTIONS] COMMAND [ARGS]... - Automatically update PyCalVer version strings in all project files. + Automatically update CalVer version strings in plaintext files. Options: --version Show the version and exit. @@ -420,20 +511,20 @@ Options: -v, --verbose Control log level. -vv for debug level. Commands: - bump Increment the current version string and update project files. - grep Search file(s) for a version pattern. - init Initialize [calver] configuration. - show Show current version of your project. - test Increment a version number for demo purposes. + update Increment the current version string and update project files. + grep Search file(s) for a version pattern. + init Initialize [bumpver] configuration. + show Show current version of your project. + test Increment a version number for demo purposes. ``` - + - + ``` -$ calver bump --help -Usage: calver bump [OPTIONS] +$ bumpver update --help +Usage: bumpver update [OPTIONS] Increment the current version string and update project files. @@ -441,10 +532,6 @@ Options: -v, --verbose Control log level. -vv for debug level. -f, --fetch / -n, --no-fetch Sync tags from remote origin. -d, --dry Display diff of changes, don't rewrite files. - --release Override release name of current_version. - Valid options are: alpha, beta, rc, post, - final. - --allow-dirty Commit even when working directory is has uncomitted changes. (WARNING: The commit will still be aborted if there are uncomitted to @@ -453,35 +540,40 @@ Options: --major Increment major component. -m, --minor Increment minor component. -p, --patch Increment patch component. - -r, --release-num Increment release number (rc1, rc2, rc3..). + -t, --tag Override release tag of current_version. Valid + options are: alpha, beta, rc, post, final. + + --tag-num Increment release tag number (rc1, rc2, + rc3..). + --pin-date Leave date components unchanged. --date Set explicit date in format YYYY-0M-0D (e.g. - 2020-10-09). + 2020-10-16). --help Show this message and exit. ``` - + ### Part Overview -> Where possible, these patterns match the conventions from [calver.org][url_calver_org_scheme]. +> Where possible, these patterns match the conventions from [CalVer.org][url_calver_org_scheme]. [url_calver_org_scheme]: https://calver.org/#scheme -| part | range / example(s) | comment | +| part | range / example(s) | info | |---------|---------------------------|--------------------------------------------| +| `MAJOR` | 0..9, 10..99, 100.. | `bumpver update --major` | +| `MINOR` | 0..9, 10..99, 100.. | `bumpver update --minor` | +| `PATCH` | 0..9, 10..99, 100.. | `bumpver update --patch` | +| `TAG` | alpha, beta, rc, post | `--tag=` | +| `PYTAG` | a, b, rc, post | `--tag=` | +| `NUM` | 0, 1, 2... | `-r/--tag-num` | | `YYYY` | 2019, 2020... | Full year, based on `strftime('%Y')` | | `YY` | 18, 19..99, 0, 1 | 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.. | `calver bump --major` | -| `MINOR` | 0..9, 10..99, 100.. | `calver bump --minor` | -| `PATCH` | 0..9, 10..99, 100.. | `calver bump --patch` | -| `TAG` | alpha, beta, rc, post | `--tag=` | -| `PYTAG` | a, b, rc, post | `--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 | @@ -515,7 +607,7 @@ The following are also available, but you should review the [Normalization Cavea ### Normalization Caveats -Package managers and installation tools will parse your version numbers. When doing so, your version number may go through a normalization process and may not be displayed as you specified it. In the case of Python, the packaging tools (such as pip, twine, setuptools) follow [PEP440 normalization rules][pep_440_normalzation_ref]. +Package managers and installation tools will parse your version numbers. When doing so, your version number may go through a normalization process and may not be exactly as you specified. In the case of Python, the packaging tools (such as pip, twine, [setuptools][setuptools_ref]) follow [PEP440 normalization rules][pep_440_normalzation_ref]. According to these rules (among other things): @@ -525,13 +617,13 @@ According to these rules (among other things): For example: -- Pattern: `vYY.0M.0D[-RELEASE]` +- Pattern: `vYY.0M.0D[-TAG]` - Version: `v20.08.02-beta` - PEP440 : `20.8.2b0` -It may not be obvious to everyone that `v20.08.02-beta` is the same `20.8.2b0` on pypi. To avoid this confusion, you should choose a pattern which is always in a normalized form or as close to it as possible. +I am not aware of any technical reason to use a normalized representation everywhere in your project. However, if you choose a pattern which is always in a normalized, it will help to avoid confusion. For example, it may not be obvious at a glance, that `v20.08.02-beta` is the same as `20.8.2b0` . -A further consideration for the choice of your version format is that it may be processed by tools that *do not* interpret it as a version number, but treat it just like any other string. It may also be confusing to your users if they a list of version numbers, sorted lexicographically by some tool (e.g. from `git tags`) and versions are not listed in order of their release as here: +A further consideration for the choice of your `version_pattern` is that it may be processed by tools that *do not* interpret it as a version number, but treat it just like any other string. It may also be confusing to your users if they a list of version numbers, sorted lexicographically by some tool (e.g. from `git tags`) and versions are not listed in order of their release: ``` $ git tag @@ -545,6 +637,11 @@ $ git tag If you wish to avoid this, you should use a pattern which maintains lexicographical ordering. +[setuptools_ref]: https://setuptools.readthedocs.io/en/latest/setuptools.html#specifying-your-project-s-version + +[pep_440_normalzation_ref]: https://www.python.org/dev/peps/pep-0440/#id31 + + ### Pattern Examples @@ -554,10 +651,10 @@ If you wish to avoid this, you should use a pattern which maintains lexicographi | `MAJOR.MINOR.PATCH[PYTAGNUM]` | `0.13.10 0.16.10rc1` | yes | no | | `MAJOR.MINOR[.PATCH[PYTAGNUM]]` | `1.11 0.3.0b5` | yes | no | | `YYYY.BUILD[PYTAGNUM]` | `2020.1031 2020.1148a0` | yes | yes | -| `YYYY.BUILD[-RELEASE]` | `2021.1393-beta 2022.1279` | no | yes | +| `YYYY.BUILD[-TAG]` | `2021.1393-beta 2022.1279` | no | yes | | `YYYY.INC0[PYTAGNUM]` | `2020.10 2021.12b2` | yes | no | -| `YYYY0M.PATCH[-RELEASE]` | `202005.12 202210.15-beta` | no | no¹ | -| `YYYY0M.BUILD[-RELEASE]` | `202106.1071 202106.1075-beta` | no | yes | +| `YYYY0M.PATCH[-TAG]` | `202005.12 202210.15-beta` | no | no¹ | +| `YYYY0M.BUILD[-TAG]` | `202106.1071 202106.1075-beta` | no | yes | | `YYYY.0M` | `2020.02 2022.09` | no | yes | | `YYYY.MM` | `2020.8 2020.10` | yes | no | | `YYYY.WW` | `2020.8 2021.14` | yes | no | @@ -578,10 +675,9 @@ If you wish to avoid this, you should use a pattern which maintains lexicographi 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 multiple years? -- If a week spans multiple years, what is the year number? +- First day of the week is either Monday or Sunday. +- Range either from 0-52 or 1-53. +- At the beginning/end of the year, you either have partial weeks or a week that spans multiple years. 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 @@ -590,7 +686,7 @@ number would run backwards if it was created around New Year. -``` +```sql YYYY WW UU GGGG VV 2020-12-26 (Sat): 2020 51 51 2020 52 2020-12-27 (Sun): 2020 51 52 2020 52 @@ -611,145 +707,184 @@ number would run backwards if it was created around New Year. ### Configuration Setup -The fastest way to setup the configuration for project is to use `calver init`. +The create an initial configuration for project with `bumpver init`. ```shell -$ pip install python-calver +$ pip install bumpver ... -Installing collected packages: click lexid pathlib2 typing toml python-calver -Successfully installed python-calver-2020.1041b0 +Installing collected packages: click toml lexid bumpver +Successfully installed bumpver-2020.1042 $ cd myproject ~/myproject/ -$ calver init --dry -Exiting because of '-d/--dry'. Would have written to calver.toml: - [calver] - current_version = "v202010.1001-alpha" - version_pattern = "vYYYY0M.BUILD[-RELEASE]" +$ bumpver init --dry +Exiting because of '-d/--dry'. Would have written to bumpver.toml: + + [bumpver] + current_version = "2020.1001a0" + version_pattern = "YYYY.BUILD[PYTAGNUM]" commit_message = "bump version to {new_version}" commit = true tag = true push = true - [calver.file_patterns] + [bumpver.file_patterns] "README.md" = [ "{version}", "{pep440_version}", ] - "calver.toml" = [ + "bumpver.toml" = [ 'current_version = "{version}"', ] ``` -If you already have configuration file in your project (such as a `setup.cfg` file), then `calver init` will update that file instead. +If you already have configuration file in your project (such as `setup.cfg` or `pyproject.toml`), then `bumpver init` will update that file instead. ``` ~/myproject -$ calver init +$ bumpver init Updated setup.cfg ``` Your `setup.cfg` may now look something like this: ```ini -[calver] +[bumpver] current_version = "2019.1001-alpha" -version_pattern = "YYYY.BUILD[-RELEASE]" +version_pattern = "YYYY.BUILD[-TAG]" commit_message = "bump version to {new_version}" commit = True tag = True push = True -[calver:file_patterns] +[bumpver:file_patterns] setup.cfg = current_version = "{version}" setup.py = - "{pep440_version}", + version="{pep440_version}", README.md = {version} {pep440_version} ``` -For the entries in `[pycalver:file_patterns]` you can expect two failure modes: -- A pattern won't match a version number in the associated file. -- A pattern will match something it shouldn't (less likely). +### Debugging Configuration -To debug such issues, you can use `pycalver grep` . +For the entries in `[bumpver:file_patterns]` you can expect two failure modes: -``` -$ pycalver grep 'Copyright (c) 2018-YYYY' src/module/*.py -src/module/__init__.py - 3: # - 4: # Copyright (c) 2018-2020 Vandelay Industries - All rights reserved. - 5: # SPDX-License-Identifier: MIT +- False negative: A pattern *will not* match a version number in the associated file *which it should* match. +- False positive: A pattern *will* match something it *should not match* (less likely). -src/module/config.py - 3: # - 4: # Copyright (c) 2018-2020 Vandelay Industries - All rights reserved. - 5: # SPDX-License-Identifier: MIT -``` - -Of course, you may not get the pattern correct right away. If your pattern is not found, `pycalver grep` will show an error message with the regular expression it uses, to help you debug the issue. - -``` -$ pycalver grep 'Copyright 2018-YYYY' src/pycalver/*.py -ERROR - Pattern not found: 'Copyright 2018-YYYY' -# https://regex101.com/?flavor=python&flags=gmx®ex=Copyright%5B%20%5D2018%5C-%0A%28%3FP%3Cyear_y%3E%5B1-9%5D%5B0-9%5D%7B3%7D%29 -re.compile(r""" - Copyright[ ]2018\- - (?P[1-9][0-9]{3}) -""", flags=re.VERBOSE) -``` - - - -Let's say you want to keep a badge your README.md up to date. - -``` -$ pycalver grep --version-pattern='vYYYY0M.BUILD[-RELEASE]' 'img.shields.io/static/v1.svg?label=PyCalVer&message={version}&color=blue' README.md - - 61: - 62: [img_version]: https://img.shields.io/static/v1.svg?label=PyCalVer&message=v202010.1040-beta&color=blue - 63: [url_version]: https://pypi.org/org/package/ - -Found 1 match for pattern 'img.shields.io/static/v1.svg?label=PyCalVer&message=vYYYY0M.BUILD[-RELEASE]&color=blue' in README.md -``` - - - -This probably won't cover all version numbers present in your project, so you will have to manually add entries to `pycalver:file_patterns`. To determine what to add, you can use `pycalver grep` : - -``` -$ pycalver grep 'Copyright (c) 2018-YYYY' src/project/*.py -``` - - - -Something like the following may illustrate additional changes you might need to make. - -```ini -[pycalver:file_patterns] -setup.cfg = - current_version = {version} -setup.py = - version="{pep440_version}" -src/mymodule_v*/__init__.py = - __version__ = "{version}" -README.md = - [CalVer {version}] - img.shields.io/static/v1.svg?label=CalVer&message={version}&color=blue -``` - -To see if a pattern is found, you can use `pycalver bump --dry`, which will -leave your project files untouched and only show you a diff of the changes -it would have made. +Most obviously you will see such cases when you first attempt to use `bumpver update`: ```shell -$ pycalver bump --dry --no-fetch -INFO - Old Version: v201901.1001-beta -INFO - New Version: v201902.1002-beta +$ bumpver update --dry --no-fetch +INFO - Old Version: 2020.1001-alpha +INFO - New Version: 2020.1002-alpha +ERROR - No match for pattern 'version="YYYY.BUILD[PYTAGNUM]",' +ERROR - +# https://regex101.com/?flavor=python&flags=gmx®ex=version%3D%5C%22%0A%28%3FP%3Cyear_y%3E%5B1-9%5D%5B0-9%5D%7B3%7D%29%0A%5C.%0A%28%3FP%3Cbid%3E%5B1-9%5D%5B0-9%5D%2A%29%0A%28%3F%3A%0A%20%20%20%20%28%3FP%3Cpytag%3Epost%7Crc%7Ca%7Cb%29%0A%20%20%20%20%28%3FP%3Cnum%3E%5B0-9%5D%2B%29%0A%29%3F%0A%5C%22%2C +regex = re.compile(r""" + version=\" + (?P[1-9][0-9]{3}) + \. + (?P[1-9][0-9]*) + (?: + (?Ppost|rc|a|b) + (?P[0-9]+) + )? + \", +""", flags=re.VERBOSE) +ERROR - No patterns matched for file 'setup.py' +``` + +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). + +To debug such issues, you can simplify your pattern and see if you can find a match with `bumpver grep` . + +```shell +$ bumpver grep 'YYYY.BUILD[PYTAGNUM]' setup.py + 45: name='myproject', + 46: version='2019.1001b0', + 47: license='MIT', + +``` + +Here we can see that the pattern for setup.py should be changed to used single quotes instead of doublequotes. + +As with `bumpver update`, if your pattern is not found, `bumpver grep` will show an error message with the regular expression it uses, to help you debug the issue. + +```shell +$ bumpver grep 'YYYY.BUILD[PYTAGNUM]' setup.py +ERROR - Pattern not found: 'YYYY.BUILD[PYTAGNUM]' +# https://regex101.com/... +``` + +An example of a more complex pattern is one where you want to keep a version badge in your README up to date. + +```shell +$ bumpver grep 'shields.io/badge/CalVer-YYYY.BUILD[--TAG]-blue' README.md + 61: + 62: [img_version]: https://img.shields.io/badge/CalVer-2020.1001--beta-blue + 63: [url_version]: https://pypi.org/org/package/ +``` + + +## Bump It Up + + +### Version State + +The `current_version` is considered global state and must be stored somewhere. Typically this might be in a `VERSION` file, or some other file which is part of the repository. This creates the risk that parallel branches can have different states. If the `current_version` were defined only by files in the local checkout, the same version might be generated on different systems for different commits. + +To avoid this issue, `bumpver` treats Git/Mercurial tags as the canonical / [SSOT][url_ssot] for the most recent version and attempts to change this state in the most atomic way possible. This is why some actions of the `bumpver` command can take a few seconds, as it is synchronizing with the remote repository to get the most recent 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 is either + + - Typically: The largest Git/Mercurial tag which matches the `version_pattern` from your config, sorted using [`pkg_resources.parse_version`][url_setuptools_pkg_resources]. + - Rarely: Before any tags have been created, the value of `current_version` in `bumpver.toml` / `setup.cfg` / `pyproject.toml`. + +[url_setuptools_pkg_resources]: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#parsing-utilities + +As part of doing `bumpver update` and `bumpver show`, your local tags are updated using `git fetch --tags`/`hg pull`. + +```shell +$ bumpver show -vv +2020-10-18T20:20:58.062 DEBUG bumpver.cli - Logging configured. +2020-10-18T20:20:58.065 DEBUG bumpver.config - Config Parsed: Config( + ... +2020-10-18T20:20:58.067 DEBUG bumpver.vcs - vcs found: git +2020-10-18T20:20:58.067 INFO bumpver.vcs - fetching tags from remote (to turn off use: -n / --no-fetch) +2020-10-18T20:20:58.068 DEBUG bumpver.vcs - git fetch +2020-10-18T20:21:00.886 DEBUG bumpver.vcs - git tag --list +2020-10-18T20:21:00.890 INFO bumpver.cli - Latest version from git tag: 2020.1019 +Current Version: 2020.1019 +``` + +Here we see that: + +- Git had a newer version than we had locally (`2020.1019` vs `2020.1018`). +- It took 2 seconds to fetch the tags from the remote repository. + +The approach of fetching tags before the version is bumped/incremented, helps to reduce the risk that the newest tag is not known locally. This means that it less likely for the same version to be generated by different systems for different commits. This would result in an ambiguous version tag, which may not be the end of the world, but is better to avoid. Typically this might happen if you have a build system where multiple builds are triggered at the same time. + +For a small project (with only one maintainer and no automated packaging) this is a non-issue and you can always use `-n/--no-fetch` to skip fetching the tags. + + +### Dry Mode + +Once you have a valid configuration, you can use `bumpver update --dry` to see the changes it would make (and leave your project files untouched). + +```diff +$ bumpver update --dry --no-fetch +INFO - Old Version: 2019.1001-beta +INFO - New Version: 2019.1002-beta --- README.md +++ README.md @@ -11,7 +11,7 @@ @@ -780,671 +915,50 @@ INFO - New Version: v201902.1002-beta license="MIT", ``` -If there is no match for a pattern, bump will report an error. -```shell -# TODO (mb 2020-08-29): update regex pattern -$ pycalver bump --dry --no-fetch -INFO - Old Version: v201901.1001-beta -INFO - New Version: v201902.1002-beta -ERROR - No match for pattern 'img.shields.io/static/v1.svg?label=CalVer&message={version}&color=blue' -ERROR - Pattern compiles to regex 'img\.shields\.io/static/v1\.svg\?label=CalVer&message=(?P\d{4})(?P(?:0[0-9]|1[0-2]))\.(?P\d{4,})(?:-(?P -(?:alpha|beta|dev|rc|post|final)))?)&color=blue' -``` +### VCS Parameters (git/mercurial) -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 individual steps performed by `bumpver update`: -TODO Update above link -### Legacy Patterns +0. Check that you have no local changes that are uncommitted. +1. *Fetch* the most recent global VCS tags from origin. +2. Generate the updated version string. +3. Replace version strings in all files configured in `file_patterns`. +4. *Commit* the updated files. +5. *Tag* the new commit. +6. *Push* the new commit and tag. -> These patterns use curly braces `{}` and were the initial implementation. They are still supported and still follow their original semantics. +The configuration for these steps can be done with the following parameters: -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. +| Parameter | Type | Description | +|------------------|----------|-----------------------------------------| +| `commit_message` | string¹ | Template for commit message in step 4. | +| `commit` | boolean | Create a commit with all updated files. | +| `tag` | boolean² | Tag the newly created commit. | +| `push` | boolean² | Push to the default remote. | -Available placeholders are: +- ¹ Available placeholders for the `commit_message`: `{new_version}`, `{old_version}`, `{new_version_pep440}`, `{old_version_pep440}` +- ² Requires `commit = True` - -| placeholder | range / example(s) | comment | -|---------------------|---------------------|-----------------| -| `{year}` | 2019... | `%Y` | -| `{yy}` | 18, 19..99, 01, 02 | `%y` | -| `{quarter}` | 1, 2, 3, 4 | | -| `{month}` | 09, 10, 11, 12 | `%m` | -| `{iso_week}` | 00..53 | `%W` | -| `{us_week}` | 00..53 | `%U` | -| `{dom}` | 01..31 | `%d` | -| `{doy}` | 001..366 | `%j` | -| `{build}` | .1023 | lexical id | -| `{build_no}` | 1023, 20345 | ... | -| `{release}` | -alpha, -beta, -rc | --release= | -| `{release_tag}` | alpha, beta, rc | ... | - - - -| placeholder | range / example(s) | comment | -|---------------------|---------------------|-----------------| -| `{pycalver}` | v201902.1001-beta | | -| `{pep440_pycalver}` | 201902.1b0 | | -| `{semver}` | 1.2.3 | | - - -### Pattern Usage - - - -There are some limitations to keep in mind: - - 1. A version string cannot span multiple lines. - 2. Characters generated by a placeholder cannot be escaped. - 3. The timezone is always UTC. - -The lack of escaping may for example be an issue with badge URLs. -You may want to put the following text in your README.md (note -that shields.io parses the two "-" dashes before `beta` as one -literal "-"): - -``` -https://img.shields.io/badge/myproject-v202010.1116--beta-blue.svg -``` - -While you could use the following pattern, which will work fine for a -while: +An example configuration might look like this: ```ini -README.md = - /badge/myproject-{vYYYY0M.BUILD[--RELEASE]}-blue.svg -``` - -Eventually this will break, when you do a `final` release, at -which point the following will be put in your README.md: - -``` -https://img.shields.io/badge/myproject-v202010.1117--final-blue.svg -``` - -When what you probably wanted was this (with the `--final` tag omitted): - -``` -https://img.shields.io/badge/myproject-v202010.1117-blue.svg -``` - - - - -### Version State - -The "current version" is considered global state that needs to be -stored somewhere. Typically this might be stored in a `VERSION` -file, or some other file which is part of the repository. This -creates the risk that parallel branches can have different -states. If the "current version" were defined only by files in -the local checkout, the same version might be generated for -different commits. - -To avoid this issue, pycalver treats VCS tags as the canonical / -[SSOT][url_ssot] for the most recent version and attempts to -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 -synchronizing with the remote repository to get the most recent -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 that will be bumped is defined either as - - - Typically: The lexically largest git/mercurial tag which matches the - `version_pattern` from your config. - - Initially: Before any tags have been created (or you're not using a - supported VCS), the value of `pycalver.current_version` in `setup.cfg` / - `pyproject.toml` / `pycalver.toml`. - -As part of doing `pycalver bump` and `pycalver show`, your local VCS -index is updated using `git fetch --tags`/`hg pull`. - -```shell -$ time pycalver show --verbose -INFO - fetching tags from remote (to turn off use: -n / --no-fetch) -INFO - Working dir version : v202010.1018 -INFO - Latest version from git tag: v202010.1019-beta -Current Version: v202010.1019-beta -PEP440 : 202010.1019b0 - -real 0m4,254s - -$ time pycalver show --verbose --no-fetch +[bumpver] ... -real 0m0,840s -``` - -Here we see that: - -- The VCS had a newer version than we had locally. -- It took 4 seconds to fetch the tags from the remote repository. - -This approach reduces the risk that new tags are unknown locally and makes it -less likely that the same version string is generated for different commits, -which would result in an ambiguous version tag. This can happen if multiple -maintainers produce a release at the same time or if a build system is triggered -multiple times and multiple builds run concurrently to each other. - -For a small project (with only one maintainer and no build system) this is a -non-issue and you can always use `-n/--no-fetch` to skip updating the tags. - - -### Bump It Up - -To increment the current version and publish a new version, you can use the -`pycalver bump` sub-command. `bump` is configured in the `pycalver` config -section: - -```ini -[pycalver] -current_version = "v202010.1006-beta" -version_pattern = "vYYYY0M.BUILD[-RELEASE]" commit_message = "bump version to {new_version}" commit = True tag = True push = True ``` -This configuration is appropriate to create a commit which +If everything looks OK, you can do `bumpver update`. -1. contains the changes to the version strings, -2. contains no other changes (unrelated to bumping the version), -3. is tagged with the new version, -4. has a version tag that is unique in the repository. - -In order to make sure only changes to version strings are in the commit, -you need to make sure you have a clean VCS checkout when you invoke -`pycalver bump`. - -The steps performed by `bump` are: - -0. Check that your repo doesn't have any local changes. -1. *Fetch* the most recent global VCS tags from origin - (`-n`/`--no-fetch` to disable). -2. Generate a new version, incremented from the current version. -3. Update version strings in all files configured in `file_patterns`. -4. *Commit* the updated version strings. -5. *Tag* the new commit. -6. *Push* the new commit and tag. - -Again, you can use `-d/--dry` to inspect the changes first. - -``` -$ pycalver bump --dry ---- setup.cfg -+++ setup.cfg -@@ -65,7 +65,7 @@ - - [pycalver] --current_version = v202010.1005-beta -+current_version = v202010.1006-beta - version_pattern = "vYYYY0M.BUILD[-RELEASE]" - commit_message = "bump version to {new_version}" - commit = True -... -``` - -If everything looks OK, you can do `pycalver bump`. - -``` -$ pycalver bump --verbose +```shell +$ bumpver update --verbose INFO - fetching tags from remote (to turn off use: -n / --no-fetch) -INFO - Old Version: v202010.1005-beta -INFO - New Version: v202010.1006-beta -INFO - git commit --message 'bump version to v202010.1006-beta' -INFO - git tag --annotate v202010.1006-beta --message v202010.1006-beta -INFO - git push origin v202010.1006-beta +INFO - Old Version: 2020.1005 +INFO - New Version: 2020.1006 +INFO - git commit --message 'bump version to 2020.1006' +INFO - git tag --annotate 2020.1006 --message 2020.1006 +INFO - git push origin --follow-tags 2020.1006 HEAD ``` - -### Config Parameters - - - - -| Config Parameter | Type | Description | -| ----------------- | -------- | ---------------------------- | -| `current_version` | string | | -| `version_pattern` | string | | -| `commit_message` | string | Template for commit message¹ | -| `commit` | boolean | | -| `tag` | boolean² | | -| `push` | boolean² | | - -- ¹ Available placeholders: `{new_version}`, `{old_version}`, `{new_version_pep440}`, `{old_version_pep440}` -- ² Requires `commit = True` - - -## The PyCalVer Format - -The PyCalVer format for version strings has three parts: - -``` - - o Year of Release - | o Sequential Build Number - | | o Release Tag (optional) - | | | - --+-- --+-- --+-- - v2020 .1001 -beta - -``` - -Some examples: - -``` -2017.1001-alpha -2017.1027-beta -2018.1031 -2018.1032-post -... -2022.28133 -2022.28134 -``` - -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 -will strive to maintain the one semantic that really matters: **newer is -better**. - -To convince you of the merits of not breaking things, here are some -resources which PyCalVer was inspired by: - - - ["Speculation" talk by Rich - Hicky](https://www.youtube.com/watch?v=oyLBGkS5ICk) - - [Designing a Version by Mahmoud - Hashemi](http://sedimental.org/designing_a_version.html) - - [calver.org](https://calver.org/) - - ["The cargo cult of versioning" by Kartik - Agaram](http://akkartik.name/post/versioning) - - The [bumpversion][bumpversion_ref] project, upon which - PyCalVer is partially based. - - ["Our Software Dependency Problem" by Russ Cox](https://research.swtch.com/deps) - - -### Parsing - -These version strings can be parsed with the following regular expression: - -```python -import re - -# https://regex101.com/r/fnj60p/14 -PYCALVER_PATTERN = r""" -\b -(?P - (?P - v # "v" version prefix - (?P\d{4}) - ) - (?P - \. # "." build nr prefix - (?P\d{4,}) - ) - (?P - \- # "-" release prefix - (?Palpha|beta|dev|rc|post) - )? -)(?:\s|$) -""" -PYCALVER_REGEX = re.compile(PYCALVER_PATTERN, flags=re.VERBOSE) - -version_str = "v2017.1001-alpha" -version_match = PYCALVER_REGEX.match(version_str) - -assert version_match.groupdict() == { - "pycalver" : "v2017.1001-alpha", - "vYYYY0M" : "v2017", - "year" : "2017", - "build" : ".1001", - "build_no" : "1001", - "release" : "-alpha", - "release_tag": "alpha", -} - -version_str = "v201712.1033" -version_match = PYCALVER_REGEX.match(version_str) - -assert version_match.groupdict() == { - "pycalver" : "v2017.1033", - "vYYYY" : "v2017", - "year" : "2017", - "build" : ".1033", - "build_no" : "1033", - "release" : None, - "release_tag": None, -} -``` - -### Incrementing Behaviour - -To see how version strings are incremented, we can use -`calver test`: - -```shell -$ calver test v2018.1033-beta -New Version: v2019.1034-beta -PEP440 : 2019.1034b0 -``` - -This is the simple case: - - - The calendar component is updated to the current year and month. - - The build number is incremented by 1. - - The optional release tag is preserved as is. - -You can explicitly update the release tag by using the `--release=` argument: - -```shell -$ calver test v2018.1033-alpha --release=beta -New Version: v2019.1034-beta -PEP440 : 2019.1034b0 - -$ calver test v2019.1034-beta --release=final -New Version: v2019.1035 -PEP440 : 2019.1035 -``` - -To maintain lexical ordering of version numbers, the version number is padded with extra zeros using [Lexical Ids][url_pypi_lexid]. -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 - -> Disclaimer: This section is of course only aspirational. Nothing will -> stop a package maintainer from publishing updates that violate the -> semantics presented here. - - -### Pitch - -- dates are good information - - how old is the software - - is the software maintained - - is my dependency outdated - - can I trust an update? - - -### blah - -PyCalVer places a greater burden on package maintainers than SemVer. -Backward incompatibility is not encoded in the version string, because -**maintainers should not intentionally introduce breaking changes**. This -is great for users of a package, who can worry a bit less about an update -causing their project to break. A paranoid user can of course still pin to -a known good version, and freezing dependencies for deployments is still a -good practice, but for development, users ideally shouldn't need any -version specifiers in their requirements.txt. This way they always get the -newest bug fixes and features. - -Part of the reason for the distinctive PyCalVer version string, is for -users to be able to recognize, just from looking at the version string, -that a package comes with the promise (or at least aspiration) that it -won't break, that it is safe for users to update. Compare this to a SemVer -version string, where maintainers explicitly state that an update _might_ -break their program and that they _may_ have to do extra work after -updating and even if it hasn't in the past, the package maintainers -anticipate that they might make such breaking changes in the future. - -In other words, the onus is on the user of a package to update their -software, if they want to update to the latest version of a package. With -PyCalVer the onus is on package maintainer to maintain backward -compatibility. - -Ideally users can trust the promise of a maintainer that the following -semantics will always be true: - - - Newer is compatible. - - Newer has fewer bugs. - - Newer has more features. - - Newer has equal or better performance. - -Alas, the world is not ideal. So how do users and maintainers deal with changes -that violate these promises? - - -### Intentional Breaking Changes - -> Namespaces are a honking great idea -> - let's do more of those! -> -> - The Zen of Python - -If you must make a breaking change to a package, **instead of incrementing a -number**, the recommended approach with PyCalVer is to **create a whole new -namespace**. Put differently, the major version becomes part of the name of the -module or even of the package. Typically you might add a numerical suffix, eg. -`mypkg -> mypkg2`. - -In the case of python distributions, you can include multiple module -packages like this. - -```python -# setup.py -setuptools.setup( - name="my-package", - license="MIT", - packages=["mypkg", "mypkg2"], - package_dir={"": "src"}, - ... -) -``` - -In other words, you can ship older versions side by side with newer ones, -and users can import whichever one they need. Alternatively you can publish -a new package distribution, with new namespace, but please consider also -renaming the module. - -```python -# setup.py -setuptools.setup( - name="my-package-v2", - license="MIT", - packages=["mypkg2"], - package_dir={"": "src"}, - ... -) -``` - -Users will have an easier time working with your package if `import mypkg2` -is enough to determine which version of your project they are using. A further -benefit of creating multiple modules is that users can import both old and -new modules in the same environment and can use some packages which depend -on the old version as well as some that depend on the new version. The -downside for users, is that they may have to do minimal changes to their -code, even if the breaking change did not affect them. - -```diff -- import mypkg -+ import mypkg2 - - def usage_code(): -- mypkg.myfun() -+ mypkg2.myfun() -``` - - -### Costs and Benefits - -If this seems like overkill because it's a lot of work for you as a -maintainer, consider first investing some time in your tools, so you -minimize future work required to create new packages. I've [done this for -my personal projects][bootstrapit_ref], but you may find [other -approaches][cookiecutter_ref] to be more appropriate for your use. - -If this seems like overkill because you're not convinced that imposing a -very small burden on users is such a big deal, consider that your own -projects may indirectly depend on dozens of libraries which you've never -even heard of. If every maintainer introduced breaking changes only once -per year, users who depend on only a dozen libraries would be dealing with -packaging issues every month! In other words: *Breaking things is a big -deal*. A bit of extra effort for a few maintainers seems like a fair trade -to lower the effort imposed on many users, who would be perfectly happy to -continue using the old code until _they_ decide when to upgrade. - - -### Unintentional Breaking Changes - -The other kind of breaking change is the non-intentional kind, otherwise -known as a "bug" or "regression". Realize first of all, that it is -impossible for any versioning system to encode that this has happened: -Since the maintainer isn't knowingly introducing a bug they naturally can't -update their version numbers to reflect what they don't know about. Instead -we have to deal with these issues after the fact. - -The first thing a package maintainer can do is to minimize the chance of -inflicting buggy software on users. After any non-trivial (potentially breaking) -change, it is a good practice to first create an `-alpha`/`-beta`/`-rc` release. -These so called `--pre` releases are intended to be downloaded only by the few -and the brave: Those who are willing to participate in testing. After any issues -are ironed out with the `--pre` releases, a `final` release can be made for the -wider public. - -Note that the default behaviour of `pip install ` (without any version -specifier) is to download the latest `final` release. It will download a `--pre` -release *only* if - - 1. no `final` release is available - 2. the `--pre` flag is explicitly used, or - 3. if the requirement specifier _explicitly_ includes the version number of a - pre release, eg. `pip install mypkg==v202009.1007-alpha`. - -Should a release include a bug (heaven forbid and despite all precautions), -then the maintainer should publish a new release which either fixes the bug -or reverts the change. If users previously downloaded a version of the -package which included the bug, they only have to do `pip install --upgrade -` and the issue will be resolved. - -Perhaps a timeline will illustrate more clearly: - -``` -v2020.1665 # last stable release -v2020.1666-beta # pre release for testers -v2019.1667 # final release after testing - -# bug is discovered which effects v2020.1666-beta and v2019.1667 - -v2019.1668-beta # fix is issued for testers -v2019.1669 # fix is issued everybody - -# Alternatively, revert before fixing - -v2019.1668 # same as v2020.1665 -v2019.1669-beta # reintroduce change from v2020.1666-beta + fix -v2019.1670 # final release after testing -``` - -In the absolute worst case, a change is discovered to break backward -compatibility, but the change is nonetheless considered to be desirable. At that -point, a new release should be made to revert the change. - -This allows 1. users who _were_ exposed to the breaking change to update to the -latest release and get the old (working) code again, and 2. users who _were not_ -exposed to the breaking change to never even know anything was broken. - -Remember that the goal is to always make things easy for users who have -your package as a dependency. If there is any issue whatsoever, all they -should have to do is `pip install --update`. If this doesn't work, they may -have to *temporarily* pin to a known good version, until a fixed release -has been published. - -After this immediate fire has been extinguished, if the breaking change is -worth keeping, then **create a new module or even a new package**. This -package will perhaps have 99% overlap to the previous one and the old one -may eventually be abandoned. - -``` -mypkg v2020.1665 # last stable release -mypkg v2020.1666-rc # pre release for testers -mypkg v2019.1667 # final release after testing period - -# bug is discovered in v2020.1666-beta and v2019.1667 - -mypkg v2019.1668 # same as v2020.1665 - -# new package is created with compatibility breaking code - -mypkg2 v2019.1669 # same as v2019.1667 -mypkg v2019.1669 # updated readme, declaring support - # level for mypkg, pointing to mypgk2 - # and documenting how to upgrade. -``` - - -### Pinning is not a Panacea - -Freezing your dependencies by using `pip freeze` to create a file with packages -pinned to specific version numbers is great to get a stable and repeatable -deployment. - -The main problem with pinning is that it is another burden imposed on users, -and it is a burden which in practice only some can bear. The vast majority of -users either 1) pin their dependencies and update them without determining what -changed or if it is safe for them to update, or 2) pin their dependencies and -forget about them. In case 1 the only benefit is that users might at least be -aware of when an update happened, so they can perhaps correlate that a new bug -in their software might be related to a recent update. Other than that, keeping -tabs on dependencies and updating without diligence is hardly better than not -having pinned at all. In case 2, an insurmountable debt will pile up and the -dependencies of a project are essentially frozen in the past. - -Yes, it is true that users will be better off if they have sufficient test -coverage to determine for themselves that their code is not broken even after -their dependencies are updated. It is also true however, that a package -maintainer is usually in a better position to judge if a change might cause -something to break. - - -### Zeno's 1.0 and The Eternal Beta - -There are two opposite approaches to backward compatibility which find a -reflection in the version numbers they use. In the case of SemVer, if a -project has a commitment to backward compatibility, it may end up never -incriminating the major version, leading to the [Zeno 1.0 -paradox][zeno_1_dot_0_ref]. On the other end are projects that avoid any -commitment to backward compatibility and forever keep the "beta" label. - -Of course an unpaid Open Source developer *does not owe anybody a -commitment to backward compatibility*. Especially when a project is young -and going through major changes, such a commitment may not make any sense. -For these cases you can still use PyCalVer, just so long as there is a big -fat warning at the top of your README, that your project is not ready for -production yet. - -Note that there is a difference between software that is considered to be -in a "beta" state and individual releases which have a `-beta` tag. These -do not mean the same thing. In the case of releases of python packages, the -release tag (`-alpha`, `-beta`, `-rc`) says something about the stability -of a *particular release*. This is similar ([perhaps -identical][pep_101_ref]) to the meaning of release tags used by the CPython -interpreter. A release tag is not a statement about the general stability -of the software as a whole, it is metadata about a particular release -artifact of a package, eg. a `.whl` file. - - -[setuptools_ref]: https://setuptools.readthedocs.io/en/latest/setuptools.html#specifying-your-project-s-version - -[pep_440_ref]: https://www.python.org/dev/peps/pep-0440/ - -[pep_440_normalzation_ref]: https://www.python.org/dev/peps/pep-0440/#id31 - -[zeno_1_dot_0_ref]: http://sedimental.org/designing_a_version.html#semver-and-release-blockage - -[pep_101_ref]: https://www.python.org/dev/peps/pep-0101/ - -[bumpversion_ref]: https://github.com/peritus/bumpversion - -[bootstrapit_ref]: https://gitlab.com/mbarkhau/bootstrapit - -[cookiecutter_ref]: https://cookiecutter.readthedocs.io - diff --git a/bootstrapit.sh b/bootstrapit.sh index 4a03da4..cde4d52 100644 --- a/bootstrapit.sh +++ b/bootstrapit.sh @@ -4,19 +4,19 @@ AUTHOR_NAME="Manuel Barkhau" AUTHOR_EMAIL="mbarkhau@gmail.com" -KEYWORDS="version versioning calver semver bumpversion pep440" -DESCRIPTION="CalVer for python packages." +KEYWORDS="version bumpver calver semver versioning bumpversion pep440" +DESCRIPTION="Bump version numbers in project files." LICENSE_ID="MIT" -PACKAGE_NAME="pycalver" +PACKAGE_NAME="bumpver" GIT_REPO_NAMESPACE="mbarkhau" GIT_REPO_DOMAIN="github.com" -PACKAGE_VERSION="v2020.1041-beta" +PACKAGE_VERSION="2020.1041-beta" DEFAULT_PYTHON_VERSION="python=3.8" -SUPPORTED_PYTHON_VERSIONS="python=2.7 python=3.6 python=3.8 pypy2.7 pypy3.5" +SUPPORTED_PYTHON_VERSIONS="python=2.7 python=3.6 pypy2.7 pypy3.5 python=3.8" DOCKER_REGISTRY_DOMAIN=registry.gitlab.com diff --git a/scripts/update_readme_examples.py b/scripts/update_readme_examples.py index 2c60bdf..8eba9e3 100644 --- a/scripts/update_readme_examples.py +++ b/scripts/update_readme_examples.py @@ -11,7 +11,7 @@ import rich import rich.box import rich.table -from pycalver import v2version +from bumpcalver import v2version def update(content, marker, value): @@ -73,10 +73,10 @@ def pattern_examples(): ("MAJOR.MINOR.PATCH[PYTAGNUM]" , ""), ("MAJOR.MINOR[.PATCH[PYTAGNUM]]", ""), ("YYYY.BUILD[PYTAGNUM]" , ""), - ("YYYY.BUILD[-RELEASE]" , ""), + ("YYYY.BUILD[-TAG]" , ""), ("YYYY.INC0[PYTAGNUM]" , ""), - ("YYYY0M.PATCH[-RELEASE]" , "¹"), - ("YYYY0M.BUILD[-RELEASE]" , ""), + ("YYYY0M.PATCH[-TAG]" , "¹"), + ("YYYY0M.BUILD[-TAG]" , ""), ("YYYY.0M" , ""), ("YYYY.MM" , ""), ("YYYY.WW" , ""), @@ -184,8 +184,8 @@ def pattern_examples(): old_content = io.open("README.md").read() new_content = old_content -new_content = update_md_code_output(new_content, "calver --help") -new_content = update_md_code_output(new_content, "calver bump --help") +new_content = update_md_code_output(new_content, "bumpver --help") +new_content = update_md_code_output(new_content, "bumpver update --help") new_content = update(new_content, "pattern_examples", pattern_examples()) new_content = update(new_content, "weeknum_example" , weeknum_example()) @@ -197,20 +197,3 @@ elif "--dry" in sys.argv: else: with io.open("README.md", mode="w") as fobj: fobj.write(new_content) - - -# @printf '\n```\n$$ calver --help\n' > /tmp/pycalver_help.txt -# @$(DEV_ENV)/bin/calver --help >> /tmp/pycalver_help.txt -# @printf '```\n\n' >> /tmp/pycalver_help.txt - -# sed -i -ne '// {p; r /tmp/pycalver_help.txt' \ -# -e ':a; n; // {p; b}; ba}; p' \ -# README.md - -# @printf '\n```\n$$ pycalver bump --help\n' > /tmp/pycalver_help.txt -# @$(DEV_ENV)/bin/pycalver bump --help >> /tmp/pycalver_help.txt -# @printf '```\n\n' >> /tmp/pycalver_help.txt - -# sed -i -ne '// {p; r /tmp/pycalver_help.txt' \ -# -e ':a; n; // {p; b}; ba}; p' \ -# README.md diff --git a/setup.cfg b/setup.cfg index 93087c6..7e4a785 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,7 +19,7 @@ warn_redundant_casts = True [tool:isort] -known_first_party = pycalver2 +known_first_party = bumpver known_third_party = click,pathlib2,lexid,pkg_resources force_single_line = True length_sort = True @@ -88,26 +88,26 @@ exclude = addopts = --doctest-modules -[calver] -current_version = "v2020.1041-beta" -version_pattern = "vYYYY.BUILD[-TAG]" +[bumpver] +current_version = "2020.1041-beta" +version_pattern = "YYYY.BUILD[-TAG]" commit_message = "bump {old_version} -> {new_version}" commit = True tag = True push = True -[calver:file_patterns] +[bumpver:file_patterns] bootstrapit.sh = PACKAGE_VERSION="{version}" setup.cfg = current_version = "{version}" setup.py = - version="{pep440_version}" -src/pycalver2/__init__.py = + version="{pep440_version}", +src/bumpver/__init__.py = __version__ = "{version}" -src/pycalver2/cli.py = +src/bumpver/cli.py = @click.version_option(version="{version}") -src/pycalver2*/*.py = +src/bumpver/*.py = Copyright (c) 2018-YYYY LICENSE = Copyright (c) 2018-YYYY @@ -116,7 +116,7 @@ license.header = README.md = \[CalVer {version}\] img.shields.io/static/v1.svg?label=CalVer&message={version}&color=blue - Successfully installed python-calver-{pep440_version} + Successfully installed bumpver-{pep440_version} [tool:pylint] diff --git a/setup.py b/setup.py index f73329d..0c35a5d 100644 --- a/setup.py +++ b/setup.py @@ -58,14 +58,14 @@ if any(arg.startswith("bdist") for arg in sys.argv): setuptools.setup( - name="python-calver", + name="bumpver", license="MIT", author="Manuel Barkhau", author_email="mbarkhau@gmail.com", - url="https://github.com/mbarkhau/pycalver", + url="https://github.com/mbarkhau/bumpver", version="2020.1041b0", - keywords="version versioning calver semver bumpversion pep440", - description="CalVer for python libraries.", + keywords="version bumpver calver semver versioning bumpversion pep440", + description="Bump version numbers in project files.", long_description=long_description, long_description_content_type="text/markdown", packages=setuptools.find_packages("src/"), @@ -73,7 +73,7 @@ setuptools.setup( install_requires=install_requires, entry_points=""" [console_scripts] - calver=pycalver2.cli:cli + bumpver=bumpver.cli:cli """, python_requires=">=2.7", zip_safe=True, diff --git a/src/pycalver2/__init__.py b/src/bumpver/__init__.py similarity index 71% rename from src/pycalver2/__init__.py rename to src/bumpver/__init__.py index 938d3fe..c6ce541 100644 --- a/src/pycalver2/__init__.py +++ b/src/bumpver/__init__.py @@ -3,6 +3,6 @@ # # Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License # SPDX-License-Identifier: MIT -"""PyCalVer: CalVer for Python Packages.""" +"""BumpVer: A CLI program for versioning.""" -__version__ = "v2020.1041-beta" +__version__ = "2020.1041-beta" diff --git a/src/pycalver2/__main__.py b/src/bumpver/__main__.py similarity index 77% rename from src/pycalver2/__main__.py rename to src/bumpver/__main__.py index f3cf730..588684c 100644 --- a/src/pycalver2/__main__.py +++ b/src/bumpver/__main__.py @@ -5,9 +5,9 @@ # Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License # SPDX-License-Identifier: MIT """ -__main__ module for PyCalVer. +__main__ module for BumpVer. -Enables use as module: $ python -m pycalver --version +Enables use as module: $ python -m bumpver --version """ from . import cli diff --git a/src/pycalver2/cli.py b/src/bumpver/cli.py similarity index 96% rename from src/pycalver2/cli.py rename to src/bumpver/cli.py index d1d6f1c..357e2b4 100755 --- a/src/pycalver2/cli.py +++ b/src/bumpver/cli.py @@ -4,7 +4,7 @@ # # Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License # SPDX-License-Identifier: MIT -"""cli module for PyCalVer.""" +"""cli module for BumpVer.""" import io import sys import typing as typ @@ -39,7 +39,7 @@ except ImportError: click.disable_unicode_literals_warning = True -logger = logging.getLogger("pycalver2.cli") +logger = logging.getLogger("bumpver.cli") _VERBOSE = 0 @@ -140,7 +140,7 @@ def _log_no_change(subcmd: str, version_pattern: str, old_version: str) -> None: ] if available_flags: available_flags_str = "/".join(available_flags) - logger.info(f"Perhaps try: calver {subcmd} {available_flags_str} ") + logger.info(f"Perhaps try: bumpver {subcmd} {available_flags_str} ") def _get_normalized_pattern(raw_pattern: str, version_pattern: typ.Optional[str]) -> str: @@ -164,7 +164,7 @@ def _get_normalized_pattern(raw_pattern: str, version_pattern: typ.Optional[str] @click.group() -@click.version_option(version="v2020.1041-beta") +@click.version_option(version="2020.1041-beta") @click.help_option() @click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.") def cli(verbose: int = 0) -> None: @@ -241,7 +241,8 @@ def test( pep440_version = version.to_pep440(new_version) click.echo(f"New Version: {new_version}") - click.echo(f"PEP440 : {pep440_version}") + if new_version != pep440_version: + click.echo(f"PEP440 : {pep440_version}") def _grep_text(pattern: patterns.Pattern, text: str, color: bool) -> typ.Iterable[str]: @@ -292,7 +293,8 @@ def _grep( match_strs = list(_grep_text(pattern, text, color)) if len(match_strs) > 0: - print(file_io.name) + if len(file_ios) > 1: + print(file_io.name) for match_str in match_strs: print(match_str) print() @@ -365,7 +367,7 @@ def show(verbose: int = 0, fetch: bool = True) -> None: _, cfg = config.init(project_path=".") if cfg is None: - logger.error("Could not parse configuration. Perhaps try 'calver init'.") + logger.error("Could not parse configuration. Perhaps try 'bumpver init'.") sys.exit(1) cfg = _update_cfg_from_vcs(cfg, fetch) @@ -418,6 +420,9 @@ def _print_diff(cfg: config.Config, new_version: str) -> None: try: diff = get_diff(cfg, new_version) _print_diff_str(diff) + except OSError as err: + logger.error(str(err)) + sys.exit(1) except rewrite.NoPatternMatch as ex: logger.error(str(ex)) sys.exit(1) @@ -482,7 +487,7 @@ def incr_dispatch( return new_version -def _bump( +def _update( cfg : config.Config, new_version : str, commit_message: str, @@ -516,14 +521,14 @@ def _bump( vcs.commit(cfg, vcs_api, filepaths, new_version, commit_message) -def _try_bump( +def _try_update( cfg : config.Config, new_version : str, commit_message: str, allow_dirty : bool = False, ) -> None: try: - _bump(cfg, new_version, commit_message, allow_dirty) + _update(cfg, new_version, commit_message, allow_dirty) except sp.CalledProcessError as ex: logger.error(f"Error running subcommand: {ex.cmd}") if ex.stdout: @@ -650,7 +655,7 @@ def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config: metavar="", help=f"Set explicit date in format YYYY-0M-0D (e.g. {_current_date}).", ) -def bump( +def update( verbose : int = 0, dry : bool = False, allow_dirty: bool = False, @@ -663,7 +668,7 @@ def bump( pin_date : bool = False, date : typ.Optional[str] = None, ) -> None: - """Increment the current version string and update project files.""" + """Update project files with the incremented version string.""" verbose = max(_VERBOSE, verbose) _configure_logging(verbose) _validate_release_tag(tag) @@ -672,7 +677,7 @@ def bump( _, cfg = config.init(project_path=".") if cfg is None: - logger.error("Could not parse configuration. Perhaps try 'pycalver init'.") + logger.error("Could not parse configuration. Perhaps try 'bumpver init'.") sys.exit(1) cfg = _update_cfg_from_vcs(cfg, fetch) @@ -691,7 +696,7 @@ def bump( ) if new_version is None: - _log_no_change('bump', cfg.version_pattern, old_version) + _log_no_change('update', cfg.version_pattern, old_version) sys.exit(1) logger.info(f"Old Version: {old_version}") @@ -711,7 +716,7 @@ def bump( } commit_message = cfg.commit_message.format(**commit_message_kwargs) - _try_bump(cfg, new_version, commit_message, allow_dirty) + _try_update(cfg, new_version, commit_message, allow_dirty) if __name__ == '__main__': diff --git a/src/pycalver2/config.py b/src/bumpver/config.py similarity index 90% rename from src/pycalver2/config.py rename to src/bumpver/config.py index e4f8587..69ad6c6 100644 --- a/src/pycalver2/config.py +++ b/src/bumpver/config.py @@ -3,7 +3,7 @@ # # Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License # SPDX-License-Identifier: MIT -"""Parse setup.cfg or pycalver.cfg files.""" +"""Parse bumpver.toml, setup.cfg or pyproject.toml files.""" import re import glob @@ -22,7 +22,7 @@ from . import v1patterns from . import v2patterns from .patterns import Pattern -logger = logging.getLogger("pycalver2.config") +logger = logging.getLogger("bumpver.config") RawPatterns = typ.List[str] RawPatternsByFile = typ.Dict[str, RawPatterns] @@ -32,7 +32,7 @@ PatternsByFile = typ.Dict[str, typ.List[Pattern]] FilePatternsItem = typ.Tuple[str, typ.List[Pattern]] -SUPPORTED_CONFIGS = ["setup.cfg", "pyproject.toml", "pycalver.toml", "calver.toml"] +SUPPORTED_CONFIGS = ["setup.cfg", "pyproject.toml", "pycalver.toml", "bumpver.toml"] DEFAULT_COMMIT_MESSAGE = "bump version to {new_version}" @@ -51,8 +51,8 @@ def _parse_config_and_format(path: pl.Path) -> typ.Tuple[pl.Path, str, str]: if (path / "pycalver.toml").exists(): config_filepath = path / "pycalver.toml" config_format = 'toml' - elif (path / "calver.toml").exists(): - config_filepath = path / "calver.toml" + elif (path / "bumpver.toml").exists(): + config_filepath = path / "bumpver.toml" config_format = 'toml' elif (path / "pyproject.toml").exists(): config_filepath = path / "pyproject.toml" @@ -61,8 +61,8 @@ def _parse_config_and_format(path: pl.Path) -> typ.Tuple[pl.Path, str, str]: config_filepath = path / "setup.cfg" config_format = 'cfg' else: - # fallback to creating a new calver.toml - config_filepath = path / "calver.toml" + # fallback to creating a new bumpver.toml + config_filepath = path / "bumpver.toml" config_format = 'toml' if config_filepath.is_absolute(): @@ -150,8 +150,8 @@ def _parse_cfg_file_patterns( if cfg_parser.has_section("pycalver:file_patterns"): file_pattern_items = cfg_parser.items("pycalver:file_patterns") - elif cfg_parser.has_section("calver:file_patterns"): - file_pattern_items = cfg_parser.items("calver:file_patterns") + elif cfg_parser.has_section("bumpver:file_patterns"): + file_pattern_items = cfg_parser.items("bumpver:file_patterns") else: return @@ -191,10 +191,10 @@ def _parse_cfg(cfg_buffer: typ.IO[str]) -> RawConfig: raw_cfg: RawConfig if cfg_parser.has_section("pycalver"): raw_cfg = dict(cfg_parser.items("pycalver")) - elif cfg_parser.has_section("calver"): - raw_cfg = dict(cfg_parser.items("calver")) + elif cfg_parser.has_section("bumpver"): + raw_cfg = dict(cfg_parser.items("bumpver")) else: - raise ValueError("Missing [calver] section.") + raise ValueError("Missing [bumpver] section.") for option, default_val in BOOL_OPTIONS.items(): val: OptionVal = raw_cfg.get(option, default_val) @@ -213,10 +213,10 @@ def _parse_toml(cfg_buffer: typ.IO[str]) -> RawConfig: raw_full_cfg: typ.Any = toml.load(cfg_buffer) raw_cfg : RawConfig - if 'pycalver' in raw_full_cfg: + if 'bumpver' in raw_full_cfg: + raw_cfg = raw_full_cfg['bumpver'] + elif 'pycalver' in raw_full_cfg: raw_cfg = raw_full_cfg['pycalver'] - elif 'calver' in raw_full_cfg: - raw_cfg = raw_full_cfg['calver'] else: raw_cfg = {} @@ -297,10 +297,18 @@ def _validate_version_with_pattern( is_new_pattern : bool, ) -> None: """Provoke ValueError if version_pattern and current_version are not compatible.""" - if is_new_pattern: - v2version.parse_version_info(current_version, version_pattern) - else: - v1version.parse_version_info(current_version, version_pattern) + try: + if is_new_pattern: + v2version.parse_version_info(current_version, version_pattern) + else: + v1version.parse_version_info(current_version, version_pattern) + except version.PatternError: + errmsg = ( + "Invalid configuration. " + f"current_version='{current_version}' is invalid for " + f"version_pattern='{version_pattern}'" + ) + raise ValueError(errmsg) if is_new_pattern: invalid_chars = re.search(r"([\s]+)", version_pattern) @@ -328,6 +336,7 @@ def _parse_config(raw_cfg: RawConfig) -> Config: version_pattern = raw_cfg['version_pattern'] = version_pattern.strip("'\" ") is_new_pattern = "{" not in version_pattern and "}" not in version_pattern + _validate_version_with_pattern(current_version, version_pattern, is_new_pattern) pep440_version = version.to_pep440(current_version) @@ -365,19 +374,19 @@ def _parse_config(raw_cfg: RawConfig) -> Config: def _parse_current_version_default_pattern(raw_cfg: RawConfig, raw_cfg_text: str) -> str: - is_pycalver_section = False + is_config_section = False for line in raw_cfg_text.splitlines(): - if is_pycalver_section and line.startswith("current_version"): + if is_config_section and line.startswith("current_version"): current_version: str = raw_cfg['current_version'] version_pattern: str = raw_cfg['version_pattern'] return line.replace(current_version, version_pattern) if line.strip() == "[pycalver]": - is_pycalver_section = True - elif line.strip() == "[calver]": - is_pycalver_section = True + is_config_section = True + elif line.strip() == "[bumpver]": + is_config_section = True elif line and line[0] == "[" and line[-1] == "]": - is_pycalver_section = False + is_config_section = False raise ValueError("Could not parse 'current_version'") @@ -449,15 +458,15 @@ def init( DEFAULT_CONFIGPARSER_BASE_TMPL = """ -[calver] +[bumpver] current_version = "{initial_version}" -version_pattern = "vYYYY.BUILD[-TAG]" +version_pattern = "YYYY.BUILD[-TAG]" commit_message = "bump version {{old_version}} -> {{new_version}}" commit = True tag = True push = True -[calver:file_patterns] +[bumpver:file_patterns] """.lstrip() @@ -489,15 +498,15 @@ README.md = DEFAULT_TOML_BASE_TMPL = """ -[calver] +[bumpver] current_version = "{initial_version}" -version_pattern = "vYYYY.BUILD[-TAG]" +version_pattern = "YYYY.BUILD[-TAG]" commit_message = "bump version {{old_version}} -> {{new_version}}" commit = true tag = true push = true -[calver.file_patterns] +[bumpver.file_patterns] """.lstrip() @@ -508,8 +517,8 @@ DEFAULT_TOML_PYCALVER_STR = """ """.lstrip() -DEFAULT_TOML_CALVER_STR = """ -"calver.toml" = [ +DEFAULT_TOML_BUMPVER_STR = """ +"bumpver.toml" = [ 'current_version = "{version}"', ] """.lstrip() @@ -547,7 +556,7 @@ DEFAULT_TOML_README_MD_STR = """ def _initial_version() -> str: - return dt.datetime.utcnow().strftime("v%Y.1001-alpha") + return dt.datetime.utcnow().strftime("%Y.1001-alpha") def _initial_version_pep440() -> str: @@ -572,7 +581,7 @@ def default_config(ctx: ProjectContext) -> str: default_pattern_strs_by_filename = { "pyproject.toml": DEFAULT_TOML_PYPROJECT_STR, "pycalver.toml" : DEFAULT_TOML_PYCALVER_STR, - "calver.toml" : DEFAULT_TOML_CALVER_STR, + "bumpver.toml" : DEFAULT_TOML_BUMPVER_STR, "setup.py" : DEFAULT_TOML_SETUP_PY_STR, "README.rst" : DEFAULT_TOML_README_RST_STR, "README.md" : DEFAULT_TOML_README_MD_STR, @@ -592,7 +601,7 @@ def default_config(ctx: ProjectContext) -> str: if ctx.config_format == 'cfg': cfg_str += DEFAULT_CONFIGPARSER_SETUP_CFG_STR if ctx.config_format == 'toml': - cfg_str += DEFAULT_TOML_CALVER_STR + cfg_str += DEFAULT_TOML_BUMPVER_STR cfg_str += "\n" diff --git a/src/pycalver2/parse.py b/src/bumpver/parse.py similarity index 100% rename from src/pycalver2/parse.py rename to src/bumpver/parse.py diff --git a/src/pycalver2/patterns.py b/src/bumpver/patterns.py similarity index 100% rename from src/pycalver2/patterns.py rename to src/bumpver/patterns.py diff --git a/src/pycalver2/pysix.py b/src/bumpver/pysix.py similarity index 100% rename from src/pycalver2/pysix.py rename to src/bumpver/pysix.py diff --git a/src/pycalver2/regexfmt.py b/src/bumpver/regexfmt.py similarity index 97% rename from src/pycalver2/regexfmt.py rename to src/bumpver/regexfmt.py index 7542d5f..8d7a850 100644 --- a/src/pycalver2/regexfmt.py +++ b/src/bumpver/regexfmt.py @@ -9,7 +9,7 @@ import textwrap from . import pysix -logger = logging.getLogger("pycalver2.regexfmt") +logger = logging.getLogger("bumpver.regexfmt") def format_regex(regex: str) -> str: diff --git a/src/pycalver2/rewrite.py b/src/bumpver/rewrite.py similarity index 100% rename from src/pycalver2/rewrite.py rename to src/bumpver/rewrite.py diff --git a/src/pycalver2/utils.py b/src/bumpver/utils.py similarity index 100% rename from src/pycalver2/utils.py rename to src/bumpver/utils.py diff --git a/src/pycalver2/v1patterns.py b/src/bumpver/v1patterns.py similarity index 99% rename from src/pycalver2/v1patterns.py rename to src/bumpver/v1patterns.py index cb5698b..265fffd 100644 --- a/src/pycalver2/v1patterns.py +++ b/src/bumpver/v1patterns.py @@ -38,7 +38,7 @@ from . import utils from .patterns import RE_PATTERN_ESCAPES from .patterns import Pattern -logger = logging.getLogger("pycalver2.v1patterns") +logger = logging.getLogger("bumpver.v1patterns") # https://regex101.com/r/fnj60p/10 PYCALVER_PATTERN = r""" diff --git a/src/pycalver2/v1rewrite.py b/src/bumpver/v1rewrite.py similarity index 99% rename from src/pycalver2/v1rewrite.py rename to src/bumpver/v1rewrite.py index 99c8da0..bb594dd 100644 --- a/src/pycalver2/v1rewrite.py +++ b/src/bumpver/v1rewrite.py @@ -17,7 +17,7 @@ from . import regexfmt from . import v1version from .patterns import Pattern -logger = logging.getLogger("pycalver2.v1rewrite") +logger = logging.getLogger("bumpver.v1rewrite") def rewrite_lines( diff --git a/src/pycalver2/v1version.py b/src/bumpver/v1version.py similarity index 99% rename from src/pycalver2/v1version.py rename to src/bumpver/v1version.py index 4f6fc80..b149974 100644 --- a/src/pycalver2/v1version.py +++ b/src/bumpver/v1version.py @@ -14,7 +14,7 @@ import lexid from . import version from . import v1patterns -logger = logging.getLogger("pycalver2.v1version") +logger = logging.getLogger("bumpver.v1version") CalInfo = typ.Union[version.V1CalendarInfo, version.V1VersionInfo] diff --git a/src/pycalver2/v2patterns.py b/src/bumpver/v2patterns.py similarity index 98% rename from src/pycalver2/v2patterns.py rename to src/bumpver/v2patterns.py index de31238..ccf41ee 100644 --- a/src/pycalver2/v2patterns.py +++ b/src/bumpver/v2patterns.py @@ -37,7 +37,7 @@ from . import utils from .patterns import RE_PATTERN_ESCAPES from .patterns import Pattern -logger = logging.getLogger("pycalver2.v2patterns") +logger = logging.getLogger("bumpver.v2patterns") # NOTE (mb 2020-09-17): For patterns with different options '(AAA|BB|C)', the # patterns with more digits should be first/left of those with fewer digits: @@ -248,6 +248,8 @@ def _convert_to_pep440(version_pattern: str) -> str: continue substitution = PEP440_PART_SUBSTITUTIONS[part_name] + if substitution in pep440_pattern: + continue is_numerical_part = part_name not in ('TAG', 'PYTAG') if is_numerical_part: diff --git a/src/pycalver2/v2rewrite.py b/src/bumpver/v2rewrite.py similarity index 99% rename from src/pycalver2/v2rewrite.py rename to src/bumpver/v2rewrite.py index 9eb0661..e70ea12 100644 --- a/src/pycalver2/v2rewrite.py +++ b/src/bumpver/v2rewrite.py @@ -18,7 +18,7 @@ from . import v2version from . import v2patterns from .patterns import Pattern -logger = logging.getLogger("pycalver2.v2rewrite") +logger = logging.getLogger("bumpver.v2rewrite") def rewrite_lines( diff --git a/src/pycalver2/v2version.py b/src/bumpver/v2version.py similarity index 99% rename from src/pycalver2/v2version.py rename to src/bumpver/v2version.py index 5601ea2..4dfe62d 100644 --- a/src/pycalver2/v2version.py +++ b/src/bumpver/v2version.py @@ -14,7 +14,7 @@ import lexid from . import version from . import v2patterns -logger = logging.getLogger("pycalver2.v2version") +logger = logging.getLogger("bumpver.v2version") CalInfo = typ.Union[version.V2CalendarInfo, version.V2VersionInfo] diff --git a/src/pycalver2/vcs.py b/src/bumpver/vcs.py similarity index 98% rename from src/pycalver2/vcs.py rename to src/bumpver/vcs.py index 29a9100..87c144d 100644 --- a/src/pycalver2/vcs.py +++ b/src/bumpver/vcs.py @@ -4,7 +4,7 @@ # Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License # SPDX-License-Identifier: MIT # -# pycalver2/vcs.py (this file) is based on code from the +# bumpver/vcs.py (this file) is based on code from the # bumpversion project: https://github.com/peritus/bumpversion # Copyright (c) 2013-2014 Filip Noetzel - MIT License @@ -25,7 +25,7 @@ import subprocess as sp from . import config -logger = logging.getLogger("pycalver2.vcs") +logger = logging.getLogger("bumpver.vcs") VCS_SUBCOMMANDS_BY_NAME = { diff --git a/src/pycalver2/version.py b/src/bumpver/version.py similarity index 100% rename from src/pycalver2/version.py rename to src/bumpver/version.py diff --git a/test/fixtures/project_a/calver.toml b/test/fixtures/project_a/bumpver.toml similarity index 80% rename from test/fixtures/project_a/calver.toml rename to test/fixtures/project_a/bumpver.toml index 3b30ca6..b65155d 100644 --- a/test/fixtures/project_a/calver.toml +++ b/test/fixtures/project_a/bumpver.toml @@ -1,12 +1,12 @@ -[calver] +[bumpver] current_version = "v2017.0123-alpha" version_pattern = "vYYYY.BUILD[-TAG]" commit = true tag = true push = true -[calver.file_patterns] -"calver.toml" = [ +[bumpver.file_patterns] +"bumpver.toml" = [ 'current_version = "{version}"', ] diff --git a/test/fixtures/project_b/setup.cfg b/test/fixtures/project_b/setup.cfg index 08158aa..ccc0cf4 100644 --- a/test/fixtures/project_b/setup.cfg +++ b/test/fixtures/project_b/setup.cfg @@ -1,11 +1,11 @@ -[calver] +[bumpver] current_version = v201307.0456-beta version_pattern = {pycalver} commit = True tag = True push = True -[calver:file_patterns] +[bumpver:file_patterns] setup.cfg = current_version = {version} setup.py = diff --git a/test/fixtures/project_c/pyproject.toml b/test/fixtures/project_c/pyproject.toml index aae94e8..95b7f3b 100644 --- a/test/fixtures/project_c/pyproject.toml +++ b/test/fixtures/project_c/pyproject.toml @@ -1,4 +1,4 @@ -[calver] +[bumpver] current_version = "v2017q1.54321" version_pattern = "v{year}q{quarter}.{build_no}" commit = true diff --git a/test/test_cli.py b/test/test_cli.py index 43b1ec2..a9db268 100644 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -17,9 +17,9 @@ import pytest import pathlib2 as pl from click.testing import CliRunner -from pycalver2 import cli -from pycalver2 import config -from pycalver2 import v2patterns +from bumpver import cli +from bumpver import config +from bumpver import v2patterns # pylint:disable=redefined-outer-name ; pytest fixtures # pylint:disable=protected-access ; allowed for test code @@ -51,11 +51,11 @@ requires = ["setuptools", "wheel"] """ ENV = { - 'GIT_AUTHOR_NAME' : "calver_tester", - 'GIT_COMMITTER_NAME' : "calver_tester", - 'GIT_AUTHOR_EMAIL' : "calver_tester@nowhere.com", - 'GIT_COMMITTER_EMAIL': "calver_tester@nowhere.com", - 'HGUSER' : "calver_tester", + 'GIT_AUTHOR_NAME' : "bumpver_tester", + 'GIT_COMMITTER_NAME' : "bumpver_tester", + 'GIT_AUTHOR_EMAIL' : "bumpver_tester@nowhere.com", + 'GIT_COMMITTER_EMAIL': "bumpver_tester@nowhere.com", + 'HGUSER' : "bumpver_tester", 'PATH' : os.environ['PATH'], } @@ -81,7 +81,7 @@ def runner(tmpdir): _debug = 0 if _debug: - tmpdir = pl.Path("..") / "tmp_test_pycalver_project" + tmpdir = pl.Path("..") / "tmp_test_bumpver_project" if tmpdir.exists(): time.sleep(0.2) shutil.rmtree(str(tmpdir)) @@ -101,7 +101,7 @@ def test_help(runner): result = runner.invoke(cli.cli, ['--help', "-vv"]) assert result.exit_code == 0 assert "CalVer" in result.output - assert "bump " in result.output + assert "update " in result.output assert "test " in result.output assert "init " in result.output assert "show " in result.output @@ -110,8 +110,8 @@ def test_help(runner): def test_version(runner): result = runner.invoke(cli.cli, ['--version', "-vv"]) assert result.exit_code == 0 - assert " version v20" in result.output - pattern = v2patterns.compile_pattern("vYYYY.BUILD[-TAG]") + assert " version 20" in result.output + pattern = v2patterns.compile_pattern("YYYY.BUILD[-TAG]") match = pattern.regexp.search(result.output) assert match @@ -186,25 +186,23 @@ def test_incr_semver_invalid(runner, caplog): def test_incr_to_beta(runner): - pattern = "vYYYY.BUILD[-TAG]" - old_version = "v2017.1999-alpha" - initial_version = config._initial_version() + pattern = "vYYYY.BUILD[-TAG]" + old_version = "v2017.1999-alpha" + new_version = dt.datetime.utcnow().strftime("v%Y.22000-beta") result = runner.invoke(cli.cli, ['test', "-vv", old_version, pattern, "--tag", "beta"]) assert result.exit_code == 0 - new_version = initial_version.replace(".1001-alpha", ".22000-beta") assert f"Version: {new_version}\n" in result.output def test_incr_to_final(runner, caplog): - pattern = "vYYYY.BUILD[-TAG]" - old_version = "v2017.1999-alpha" - initial_version = config._initial_version() + pattern = "vYYYY.BUILD[-TAG]" + old_version = "v2017.1999-alpha" + new_version = dt.datetime.utcnow().strftime("v%Y.22000") result = runner.invoke(cli.cli, ['test', "-vv", old_version, pattern, "--tag", "final"]) _debug_records(caplog) assert result.exit_code == 0 - new_version = initial_version.replace(".1001-alpha", ".22000") assert f"Version: {new_version}\n" in result.output @@ -252,14 +250,14 @@ def _add_project_files(*files): with pl.Path("pycalver.toml").open(mode="wt", encoding="utf-8") as fobj: fobj.write(CALVER_TOML_FIXTURE) - if "calver.toml" in files: - with pl.Path("calver.toml").open(mode="wt", encoding="utf-8") as fobj: - fobj.write(CALVER_TOML_FIXTURE) - if "pyproject.toml" in files: with pl.Path("pyproject.toml").open(mode="wt", encoding="utf-8") as fobj: fobj.write(PYPROJECT_TOML_FIXTURE) + if "bumpver.toml" in files: + with pl.Path("bumpver.toml").open(mode="wt", encoding="utf-8") as fobj: + fobj.write(CALVER_TOML_FIXTURE) + def _update_config_val(filename, **kwargs): with io.open(filename, mode="r", encoding="utf-8") as fobj: @@ -281,7 +279,8 @@ def test_nocfg(runner, caplog): _add_project_files("README.md") result = runner.invoke(cli.cli, ['show', "-vv"]) assert result.exit_code == 1 - expected_msg = "Could not parse configuration. Perhaps try 'calver init'." + expected_msg = "Could not parse configuration. Perhaps try 'bumpver init'." + _debug_records(caplog) assert any(expected_msg in r.message for r in caplog.records) @@ -290,14 +289,14 @@ def test_novcs_nocfg_init(runner, caplog): # dry mode test result = runner.invoke(cli.cli, ['init', "-vv", "--dry"]) assert result.exit_code == 0 - assert not os.path.exists("calver.toml") + assert not os.path.exists("bumpver.toml") # non dry mode result = runner.invoke(cli.cli, ['init', "-vv"]) assert result.exit_code == 0 - assert os.path.exists("calver.toml") - with pl.Path("calver.toml").open(mode="r", encoding="utf-8") as fobj: + assert os.path.exists("bumpver.toml") + with pl.Path("bumpver.toml").open(mode="r", encoding="utf-8") as fobj: cfg_content = fobj.read() base_str = config.DEFAULT_TOML_BASE_TMPL.format(initial_version=config._initial_version()) @@ -305,6 +304,7 @@ def test_novcs_nocfg_init(runner, caplog): assert config.DEFAULT_TOML_README_MD_STR in cfg_content result = runner.invoke(cli.cli, ['show', "-vv"]) + _debug_records(caplog) assert result.exit_code == 0 assert f"Current Version: {config._initial_version()}\n" in result.output assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output @@ -390,7 +390,7 @@ def test_git_init(runner, version_pattern, cur_version, cur_pep440): assert result.exit_code == 0 _update_config_val( - "calver.toml", + "bumpver.toml", version_pattern=version_pattern, current_version='"' + cur_version + '"', ) @@ -409,7 +409,7 @@ def test_hg_init(runner, version_pattern, cur_version, cur_pep440): assert result.exit_code == 0 _update_config_val( - "calver.toml", + "bumpver.toml", version_pattern=version_pattern, current_version='"' + cur_version + '"', ) @@ -430,7 +430,7 @@ def test_v1_git_tag_eval(runner, version_pattern, cur_version, cur_pep440): assert result.exit_code == 0 _update_config_val( - "calver.toml", + "bumpver.toml", version_pattern=version_pattern, current_version='"' + cur_version + '"', ) @@ -456,7 +456,7 @@ def test_hg_tag_eval(runner, version_pattern, cur_version, cur_pep440): assert result.exit_code == 0 _update_config_val( - "calver.toml", + "bumpver.toml", version_pattern=version_pattern, current_version='"' + cur_version + '"', ) @@ -480,7 +480,7 @@ def test_novcs_bump(runner, version_pattern, cur_version, cur_pep440): assert result.exit_code == 0 _update_config_val( - "calver.toml", + "bumpver.toml", version_pattern=version_pattern, current_version='"' + cur_version + '"', ) @@ -488,7 +488,7 @@ def test_novcs_bump(runner, version_pattern, cur_version, cur_pep440): with pl.Path("README.md").open(mode="r") as fobj: content = fobj.read() - result = runner.invoke(cli.cli, ['bump', "-vv"]) + result = runner.invoke(cli.cli, ['update', "-vv"]) assert result.exit_code == 0 calver = cur_version.split(".")[0] @@ -498,7 +498,7 @@ def test_novcs_bump(runner, version_pattern, cur_version, cur_pep440): assert calver + ".1002-alpha !\n" in content assert calver[1:] + ".1002a0 !]\n" in content - result = runner.invoke(cli.cli, ['bump', "-vv", "--tag", "beta"]) + result = runner.invoke(cli.cli, ['update', "-vv", "--tag", "beta"]) assert result.exit_code == 0 with pl.Path("README.md").open() as fobj: @@ -516,15 +516,15 @@ def test_git_bump(runner, caplog, version_pattern, cur_version, cur_pep440): assert result.exit_code == 0 _update_config_val( - "calver.toml", + "bumpver.toml", version_pattern=version_pattern, current_version='"' + cur_version + '"', ) - shell("git", "add", "calver.toml") + shell("git", "add", "bumpver.toml") shell("git", "commit", "-m", "initial commit") - result = runner.invoke(cli.cli, ['bump', "-vv"]) + result = runner.invoke(cli.cli, ['update', "-vv"]) _debug_records(caplog) assert result.exit_code == 0 @@ -544,15 +544,15 @@ def test_hg_bump(runner, version_pattern, cur_version, cur_pep440): assert result.exit_code == 0 _update_config_val( - "calver.toml", + "bumpver.toml", version_pattern=version_pattern, current_version='"' + cur_version + '"', ) - shell("hg", "add", "calver.toml") + shell("hg", "add", "bumpver.toml") shell("hg", "commit", "-m", "initial commit") - result = runner.invoke(cli.cli, ['bump', "-vv"]) + result = runner.invoke(cli.cli, ['update', "-vv"]) assert result.exit_code == 0 calver = cur_version.split(".")[0] @@ -573,12 +573,12 @@ def test_empty_git_bump(runner, caplog): with pl.Path("setup.cfg").open(mode="r") as fobj: default_cfg_data = fobj.read() - assert "[calver]\n" in default_cfg_data + assert "[bumpver]\n" in default_cfg_data assert "\ncurrent_version = " in default_cfg_data - assert "\n[calver:file_patterns]\n" in default_cfg_data + assert "\n[bumpver:file_patterns]\n" in default_cfg_data assert "\nsetup.cfg =\n" in default_cfg_data - result = runner.invoke(cli.cli, ['bump']) + result = runner.invoke(cli.cli, ['update']) assert any(("working directory is not clean" in r.message) for r in caplog.records) assert any(("setup.cfg" in r.message) for r in caplog.records) @@ -595,12 +595,12 @@ def test_empty_hg_bump(runner, caplog): with pl.Path("setup.cfg").open(mode="r") as fobj: default_cfg_text = fobj.read() - assert "[calver]\n" in default_cfg_text + assert "[bumpver]\n" in default_cfg_text assert "\ncurrent_version = " in default_cfg_text - assert "\n[calver:file_patterns]\n" in default_cfg_text + assert "\n[bumpver:file_patterns]\n" in default_cfg_text assert "\nsetup.cfg =\n" in default_cfg_text - result = runner.invoke(cli.cli, ['bump']) + result = runner.invoke(cli.cli, ['update']) assert any(("working directory is not clean" in r.message) for r in caplog.records) assert any(("setup.cfg" in r.message) for r in caplog.records) @@ -640,13 +640,13 @@ def test_v1_bump_semver_warning(runner, caplog, version_pattern): _vcs_init("hg", files=["README.md", "setup.cfg"]) - result = runner.invoke(cli.cli, ['bump', "-vv", "-n", "--dry"]) + result = runner.invoke(cli.cli, ['update', "-vv", "-n", "--dry"]) assert result.exit_code == 1 assert any("version did not change" in r.message for r in caplog.records) assert any("[--major/--minor/--patch] required" in r.message for r in caplog.records) - result = runner.invoke(cli.cli, ['bump', "-vv", "-n", "--dry", "--patch"]) + result = runner.invoke(cli.cli, ['update', "-vv", "-n", "--dry", "--patch"]) assert result.exit_code == 0 @@ -664,7 +664,7 @@ def test_v1_bump_semver_diff(runner, caplog, version_pattern): cases = [("--major", "1.0.0"), ("--minor", "0.2.0"), ("--patch", "0.1.1")] for flag, expected in cases: - result = runner.invoke(cli.cli, ['bump', "-vv", "-n", "--dry", flag]) + result = runner.invoke(cli.cli, ['update', "-vv", "-n", "--dry", flag]) assert result.exit_code == 0 assert len(caplog.records) == 0 @@ -769,13 +769,17 @@ def test_hg_commit_message(runner, caplog): commit_message = """ "bump from {old_version} ({old_version_pep440}) to {new_version} ({new_version_pep440})" """ - _update_config_val("setup.cfg", current_version='"v2019.1001-alpha"') - _update_config_val("setup.cfg", commit_message=commit_message.strip()) + _update_config_val( + "setup.cfg", + current_version='"v2019.1001-alpha"', + version_pattern="vYYYY.BUILD[-TAG]", + commit_message=commit_message.strip(), + ) _vcs_init("hg", ["README.md", "setup.cfg"]) assert len(caplog.records) > 0 - result = runner.invoke(cli.cli, ['bump', "-vv", "--pin-date", "--tag", "beta"]) + result = runner.invoke(cli.cli, ['update', "-vv", "--pin-date", "--tag", "beta"]) assert result.exit_code == 0 tags = shell("hg", "tags").decode("utf-8") @@ -796,13 +800,17 @@ def test_git_commit_message(runner, caplog): commit_message = """ "bump: {old_version} ({old_version_pep440}) -> {new_version} ({new_version_pep440})" """ - _update_config_val("setup.cfg", current_version='"v2019.1001-alpha"') - _update_config_val("setup.cfg", commit_message=commit_message.strip()) + _update_config_val( + "setup.cfg", + current_version='"v2019.1001-alpha"', + version_pattern="vYYYY.BUILD[-TAG]", + commit_message=commit_message.strip(), + ) _vcs_init("git", ["README.md", "setup.cfg"]) assert len(caplog.records) > 0 - result = runner.invoke(cli.cli, ['bump', "-vv", "--pin-date", "--tag", "beta"]) + result = runner.invoke(cli.cli, ['update', "-vv", "--pin-date", "--tag", "beta"]) assert result.exit_code == 0 tags = shell("git", "tag", "--list").decode("utf-8") @@ -870,7 +878,7 @@ def test_multimatch_file_patterns(runner): with pl.Path("setup.cfg").open(mode="w", encoding="utf-8") as fobj: fobj.write(SETUP_CFG_MULTIMATCH_FILE_PATTERNS_FIXTURE) - result = runner.invoke(cli.cli, ['bump', '--tag', 'beta', '--date', "2020-11-22"]) + result = runner.invoke(cli.cli, ['update', '--tag', 'beta', '--date', "2020-11-22"]) assert result.exit_code == 0 with pl.Path("README.md").open(mode="r", encoding="utf-8") as fobj: @@ -921,20 +929,20 @@ def test_get_latest_vcs_version_tag(runner): result = runner.invoke(cli.cli, ['init', "-vv"]) assert result.exit_code == 0 - _update_config_val("calver.toml", push="false") - _update_config_val("calver.toml", current_version='"0.1.8"') - _update_config_val("calver.toml", version_pattern='"MAJOR.MINOR.PATCH"') + _update_config_val("bumpver.toml", push="false") + _update_config_val("bumpver.toml", current_version='"0.1.8"') + _update_config_val("bumpver.toml", version_pattern='"MAJOR.MINOR.PATCH"') - _vcs_init("git", files=["calver.toml"]) + _vcs_init("git", files=["bumpver.toml"]) - result = runner.invoke(cli.cli, ['bump', "--patch"]) + result = runner.invoke(cli.cli, ['update', "--patch"]) assert result.exit_code == 0 _, cfg = config.init() latest_version = cli.get_latest_vcs_version_tag(cfg, fetch=False) assert latest_version == "0.1.9" - result = runner.invoke(cli.cli, ['bump', "--patch"]) + result = runner.invoke(cli.cli, ['update', "--patch"]) assert result.exit_code == 0 _, cfg = config.init() diff --git a/test/test_config.py b/test/test_config.py index c071944..94ae52d 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals import io from test import util -from pycalver2 import config +from bumpver import config # pylint:disable=redefined-outer-name ; pytest fixtures # pylint:disable=protected-access ; allowed for test code @@ -51,33 +51,33 @@ push = false """ CALVER_TOML_FIXTURE_3 = """ -[calver] +[bumpver] current_version = "v201808.0123-alpha" version_pattern = "vYYYY0M.BUILD[-TAG]" commit = true tag = true push = true -[calver.file_patterns] +[bumpver.file_patterns] "README.md" = [ "{version}", "{pep440_version}", ] -"calver.toml" = [ +"bumpver.toml" = [ 'current_version = "{version}"', ] """ SETUP_CFG_FIXTURE = """ -[calver] +[bumpver] current_version = "v201808.0456-beta" version_pattern = "vYYYY0M.BUILD[-TAG]" commit = True tag = True push = True -[calver:file_patterns] +[bumpver:file_patterns] setup.py = {version} {pep440_version} @@ -87,7 +87,7 @@ setup.cfg = NEW_PATTERN_CFG_FIXTURE = """ -[calver] +[bumpver] current_version = "v201808.1456-beta" version_pattern = "vYYYY0M.BUILD[-TAG]" commit_message = "bump version to {new_version}" @@ -95,7 +95,7 @@ commit = True tag = True push = True -[calver:file_patterns] +[bumpver:file_patterns] setup.py = {version} {pep440_version} @@ -172,11 +172,11 @@ def test_parse_toml_3(): assert cfg.push is True files = set(cfg.file_patterns) - assert "calver.toml" in files + assert "bumpver.toml" in files raw_patterns_by_path = _parse_raw_patterns_by_filepath(cfg) - assert raw_patterns_by_path["README.md" ] == ["vYYYY0M.BUILD[-TAG]", "YYYY0M.BLD[PYTAGNUM]"] - assert raw_patterns_by_path["calver.toml"] == ['current_version = "vYYYY0M.BUILD[-TAG]"'] + assert raw_patterns_by_path["README.md" ] == ["vYYYY0M.BUILD[-TAG]", "YYYY0M.BLD[PYTAGNUM]"] + assert raw_patterns_by_path["bumpver.toml"] == ['current_version = "vYYYY0M.BUILD[-TAG]"'] def test_parse_v1_cfg(): @@ -247,8 +247,8 @@ def test_parse_default_cfg(): def test_parse_project_toml(): project_path = util.FIXTURES_DIR / "project_a" - config_path = util.FIXTURES_DIR / "project_a" / "calver.toml" - config_rel_path = "calver.toml" + config_path = util.FIXTURES_DIR / "project_a" / "bumpver.toml" + config_rel_path = "bumpver.toml" with config_path.open() as fobj: config_data = fobj.read() @@ -268,7 +268,7 @@ def test_parse_project_toml(): assert cfg.push is True files = set(cfg.file_patterns.keys()) - assert files == {"calver.toml", "README.md"} + assert files == {"bumpver.toml", "README.md"} def test_parse_project_cfg(): @@ -406,7 +406,7 @@ def test_parse_missing_version(tmpdir): setup_path.write( "\n".join( ( - "[calver]", + "[bumpver]", # f"current_version = v201808.1001-dev", "commit = False", ) @@ -422,7 +422,7 @@ def test_parse_missing_version(tmpdir): def test_parse_invalid_version(tmpdir): setup_path = tmpdir.mkdir("fail").join("setup.cfg") - setup_path.write("\n".join(("[calver]", "current_version = 0.1.0", "commit = False"))) + setup_path.write("\n".join(("[bumpver]", "current_version = 0.1.0", "commit = False"))) ctx = config.init_project_ctx(setup_path) assert ctx diff --git a/test/test_parse.py b/test/test_parse.py index f571ec3..5bccaa2 100644 --- a/test/test_parse.py +++ b/test/test_parse.py @@ -4,8 +4,8 @@ from __future__ import print_function from __future__ import absolute_import from __future__ import unicode_literals -from pycalver2 import parse -from pycalver2 import v1patterns +from bumpver import parse +from bumpver import v1patterns SETUP_PY_FIXTURE = """ # setup.py diff --git a/test/test_patterns.py b/test/test_patterns.py index ae67fbe..9222280 100644 --- a/test/test_patterns.py +++ b/test/test_patterns.py @@ -8,8 +8,8 @@ import re import pytest -from pycalver2 import v1patterns -from pycalver2 import v2patterns +from bumpver import v1patterns +from bumpver import v2patterns V2_PART_PATTERN_CASES = [ (['YYYY', 'GGGG'], "2020" , "2020"), diff --git a/test/test_rewrite.py b/test/test_rewrite.py index 9794ea0..a306920 100644 --- a/test/test_rewrite.py +++ b/test/test_rewrite.py @@ -8,14 +8,14 @@ import re import copy from test import util -from pycalver2 import config -from pycalver2 import rewrite -from pycalver2 import v1rewrite -from pycalver2 import v1version -from pycalver2 import v2rewrite -from pycalver2 import v2version -from pycalver2 import v1patterns -from pycalver2 import v2patterns +from bumpver import config +from bumpver import rewrite +from bumpver import v1rewrite +from bumpver import v1version +from bumpver import v2rewrite +from bumpver import v2version +from bumpver import v1patterns +from bumpver import v2patterns # pylint:disable=protected-access ; allowed for test code @@ -102,7 +102,7 @@ def test_iter_file_paths(): _paths_and_patterns = rewrite.iter_path_patterns_items(cfg.file_patterns) file_paths = {str(file_path) for file_path, patterns in _paths_and_patterns} - assert file_paths == {"calver.toml", "README.md"} + assert file_paths == {"bumpver.toml", "README.md"} def test_iter_file_globs(): @@ -217,13 +217,13 @@ def test_v2_optional_release(): def test_v1_iter_rewritten(): - version_pattern = "v{year}{build}{release}" - new_vinfo = v1version.parse_version_info("v2018.0123", version_pattern) + version_pattern = "{year}{build}{release}" + new_vinfo = v1version.parse_version_info("2018.0123", version_pattern) init_pattern = v1patterns.compile_pattern( - version_pattern, '__version__ = "v{year}{build}{release}"' + version_pattern, '__version__ = "{year}{build}{release}"' ) - file_patterns = {"src/pycalver2/__init__.py": [init_pattern]} + file_patterns = {"src/bumpver/__init__.py": [init_pattern]} rewritten_datas = v1rewrite.iter_rewritten(file_patterns, new_vinfo) rfd = list(rewritten_datas)[0] expected = [ @@ -232,21 +232,21 @@ def test_v1_iter_rewritten(): "#", "# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License", "# SPDX-License-Identifier: MIT", - '"""PyCalVer: CalVer for Python Packages."""', + '"""BumpVer: A CLI program for versioning."""', '', - '__version__ = "v2018.0123"', + '__version__ = "2018.0123"', '', ] assert rfd.new_lines == expected def test_v2_iter_rewritten(): - version_pattern = "vYYYY.BUILD[-TAG]" - new_vinfo = v2version.parse_version_info("v2018.0123", version_pattern) + version_pattern = "YYYY.BUILD[-TAG]" + new_vinfo = v2version.parse_version_info("2018.0123", version_pattern) file_patterns = { - "src/pycalver2/__init__.py": [ - v2patterns.compile_pattern(version_pattern, '__version__ = "vYYYY.BUILD[-TAG]"'), + "src/bumpver/__init__.py": [ + v2patterns.compile_pattern(version_pattern, '__version__ = "YYYY.BUILD[-TAG]"'), ] } @@ -258,38 +258,41 @@ def test_v2_iter_rewritten(): "#", "# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License", "# SPDX-License-Identifier: MIT", - '"""PyCalVer: CalVer for Python Packages."""', + '"""BumpVer: A CLI program for versioning."""', '', - '__version__ = "v2018.0123"', + '__version__ = "2018.0123"', '', ] assert rfd.new_lines == expected def test_v1_diff(): - version_pattern = "v{year}{build}{release}" - raw_pattern = '__version__ = "v{year}{build}{release}"' + version_pattern = "{year}{build}{release}" + raw_pattern = '__version__ = "{year}{build}{release}"' pattern = v1patterns.compile_pattern(version_pattern, raw_pattern) - file_patterns = {"src/pycalver2/__init__.py": [pattern]} + file_patterns = {"src/bumpver/__init__.py": [pattern]} old_vinfo = v1version.parse_version_info("v201809.0123") new_vinfo = v1version.parse_version_info("v201911.1124") assert new_vinfo > old_vinfo - old_vinfo = v1version.parse_version_info("v2018.0123", version_pattern) - new_vinfo = v1version.parse_version_info("v2019.1124", version_pattern) + old_vinfo = v1version.parse_version_info("2018.0123", version_pattern) + new_vinfo = v1version.parse_version_info("2019.1124", version_pattern) diff_str = v1rewrite.diff(old_vinfo, new_vinfo, file_patterns) lines = diff_str.split("\n") - assert lines[:2] == ["--- src/pycalver2/__init__.py", "+++ src/pycalver2/__init__.py"] + assert lines[:2] == [ + "--- src/bumpver/__init__.py", + "+++ src/bumpver/__init__.py", + ] - assert lines[6].startswith('-__version__ = "v20') - assert lines[7].startswith('+__version__ = "v20') + assert lines[6].startswith('-__version__ = "20') + assert lines[7].startswith('+__version__ = "20') - assert not lines[6].startswith('-__version__ = "v2018.0123"') + assert not lines[6].startswith('-__version__ = "2018.0123"') - assert lines[7] == '+__version__ = "v2019.1124"' + assert lines[7] == '+__version__ = "2019.1124"' raw_pattern = "Copyright (c) 2018-{year}" pattern = v1patterns.compile_pattern(version_pattern, raw_pattern) @@ -302,25 +305,28 @@ def test_v1_diff(): def test_v2_diff(): - version_pattern = "vYYYY.BUILD[-TAG]" - raw_pattern = '__version__ = "vYYYY.BUILD[-TAG]"' + version_pattern = "YYYY.BUILD[-TAG]" + raw_pattern = '__version__ = "YYYY.BUILD[-TAG]"' pattern = v2patterns.compile_pattern(version_pattern, raw_pattern) - file_patterns = {"src/pycalver2/__init__.py": [pattern]} + file_patterns = {"src/bumpver/__init__.py": [pattern]} - old_vinfo = v2version.parse_version_info("v2018.0123", version_pattern) - new_vinfo = v2version.parse_version_info("v2019.1124", version_pattern) + old_vinfo = v2version.parse_version_info("2018.0123", version_pattern) + new_vinfo = v2version.parse_version_info("2019.1124", version_pattern) diff_str = v2rewrite.diff(old_vinfo, new_vinfo, file_patterns) lines = diff_str.split("\n") - assert lines[:2] == ["--- src/pycalver2/__init__.py", "+++ src/pycalver2/__init__.py"] + assert lines[:2] == [ + "--- src/bumpver/__init__.py", + "+++ src/bumpver/__init__.py", + ] - assert lines[6].startswith('-__version__ = "v20') - assert lines[7].startswith('+__version__ = "v20') + assert lines[6].startswith('-__version__ = "20') + assert lines[7].startswith('+__version__ = "20') - assert not lines[6].startswith('-__version__ = "v2018.0123"') + assert not lines[6].startswith('-__version__ = "2018.0123"') - assert lines[7] == '+__version__ = "v2019.1124"' + assert lines[7] == '+__version__ = "2019.1124"' raw_pattern = "Copyright (c) 2018-YYYY" pattern = v2patterns.compile_pattern(version_pattern, raw_pattern) diff --git a/test/test_version.py b/test/test_version.py index 2b7b0a1..b2bfa84 100644 --- a/test/test_version.py +++ b/test/test_version.py @@ -9,11 +9,11 @@ import datetime as dt import pytest -from pycalver2 import version -from pycalver2 import v1version -from pycalver2 import v2version -from pycalver2 import v1patterns -from pycalver2 import v2patterns +from bumpver import version +from bumpver import v1version +from bumpver import v2version +from bumpver import v1patterns +from bumpver import v2patterns # pylint:disable=protected-access ; allowed for test code diff --git a/test/util.py b/test/util.py index 86d7a7a..6b62c92 100644 --- a/test/util.py +++ b/test/util.py @@ -29,7 +29,7 @@ FIXTURE_PATH_PARTS = [ ["setup.cfg"], ["setup.py"], ["pycalver.toml"], - ["calver.toml"], + ["bumpver.toml"], ["src", "module_v1", "__init__.py"], ["src", "module_v2", "__init__.py"], ] @@ -41,7 +41,7 @@ class Project: self.tmpdir = tmpdir self.prev_cwd = os.getcwd() - self.dir = tmpdir / "pycalver_project" + self.dir = tmpdir / "bumpver_project" self.dir.mkdir() if project is None: