def _parse_version(package_version: str): """Parse release part from version string.""" try: package_version = Version.parse(package_version.replace( "==", "")).normalize() except ValueError: package_version = Version.parse("0.0.0") return package_version
def bump_version(version: parver.Version, args) -> parver.Version: if args.release: return version.base_version() if args.dev: if args.to is not None: return version.replace(dev=args.to) else: return version.bump_dev() version = version.replace(dev=None) if args.post: if args.to is not None: return version.replace(post=args.to) else: return version.bump_post() if args.rc: if version.is_postrelease: version = version.replace(post=None) if args.to is not None: return version.replace(pre_tag="rc", pre=args.to) else: return version.bump_pre("rc")
def test_parse_strict_error(version): v = Version.parse(version) # Exclude already normalized versions assume(str(v.normalize()) != version) # 0!1 normalizes to '1' assume(v.epoch != 0 or v.epoch_implicit) with pytest.raises(ParseError): Version.parse(version, strict=True)
def test_bump_by_error(by): v = Version(release=1) with pytest.raises(TypeError): v.bump_epoch(by=by) with pytest.raises(TypeError): v.bump_dev(by=by) with pytest.raises(TypeError): v.bump_pre('a', by=by) with pytest.raises(TypeError): v.bump_post(by=by)
def test_bump_by_value_error(): v = Version(release=1) with pytest.raises(ValueError, match='negative'): v.bump_epoch(by=-1) with pytest.raises(ValueError, match='negative'): v.bump_dev(by=-1) with pytest.raises(ValueError, match='negative'): v.bump_pre(by=-1) with pytest.raises(ValueError, match='negative'): v.bump_post(by=-1)
def check_update_changelog( changelog: bytes, release_version: Version, ignore_changelog_version: bool ) -> bytes | bool: unreleased = match(br'[Uu]nreleased\n-+\n', changelog) if unreleased is None: v_match = match(br'v([\d.]+\w+)\n', changelog) if v_match is None: raise RuntimeError( 'CHANGELOG.rst does not start with a version or "Unreleased"') changelog_version = Version.parse(v_match[1].decode()) if changelog_version == release_version: print("* CHANGELOG's version matches release_version") return True if ignore_changelog_version is not False: print('* ignoring non-matching CHANGELOG version') return True raise RuntimeError( f"CHANGELOG's version ({changelog_version}) does not " f"match release_version ({release_version}). " "Use --ignore-changelog-version ignore this error.") if SIMULATE is True: print( '* replace the "Unreleased" section of "CHANGELOG.rst" with ' f'v{release_version}') return True ver_bytes = f'v{release_version}'.encode() return b'%b\n%b\n%b' % ( ver_bytes, b'-' * len(ver_bytes), changelog[unreleased.end():])
def test_version_pre(self, version, pre): v = Version.parse(version) if pre is None: assert v.pre is None and v.pre_tag is None return assert v.pre == pre[1] assert v.pre_tag == pre[0]
def bump_version(ctx, dry_run=False, increment=True, release=False, dev=False, pre=False, tag=None, clear=False): current_version = Version.parse(__version__) today = datetime.date.today() next_month_number = today.month + 1 if today.month != 12 else 1 next_year_number = today.year if next_month_number != 1 else today.year+1 next_month = (next_year_number, next_month_number, 0) if pre and not tag: print('Using "pre" requires a corresponding tag.') return if release and not dev and not pre: new_version = current_version.replace(release=today.timetuple()[:3]).clear(pre=True, dev=True) elif release and (dev or pre): new_version = current_version.replace(release=today.timetuple()[:3]) if dev: new_version = new_version.bump_dev() elif pre: new_version = new_version.bump_pre(tag=tag) else: new_version = current_version.replace(release=next_month) if dev: new_version = new_version.bump_dev() elif pre: new_version = new_version.bump_pre(tag=tag) if clear: new_version = new_version.clear(dev=True, pre=True, post=True) log('Updating version to %s' % new_version.normalize()) version_file = get_version_file(ctx) file_contents = version_file.read_text() log('Found current version: %s' % __version__) if dry_run: log('Would update to: %s' % new_version.normalize()) else: log('Updating to: %s' % new_version.normalize()) version_file.write_text(file_contents.replace(__version__, str(new_version.normalize())))
def get_semver_version(): # __name__ is set to the fully-qualified name of the current module, In our case, it will be # <some module>._utilities. <some module> is the module we want to query the version for. root_package, *rest = __name__.split('.') # pkg_resources uses setuptools to inspect the set of installed packages. We use it here to ask # for the currently installed version of the root package (i.e. us) and get its version. # Unfortunately, PEP440 and semver differ slightly in incompatible ways. The Pulumi engine expects # to receive a valid semver string when receiving requests from the language host, so it's our # responsibility as the library to convert our own PEP440 version into a valid semver string. pep440_version_string = pkg_resources.require(root_package)[0].version pep440_version = PEP440Version.parse(pep440_version_string) (major, minor, patch) = pep440_version.release prerelease = None if pep440_version.pre_tag == 'a': prerelease = f"alpha.{pep440_version.pre}" elif pep440_version.pre_tag == 'b': prerelease = f"beta.{pep440_version.pre}" elif pep440_version.pre_tag == 'rc': prerelease = f"rc.{pep440_version.pre}" elif pep440_version.dev is not None: prerelease = f"dev.{pep440_version.dev}" # The only significant difference between PEP440 and semver as it pertains to us is that PEP440 has explicit support # for dev builds, while semver encodes them as "prerelease" versions. In order to bridge between the two, we convert # our dev build version into a prerelease tag. This matches what all of our other packages do when constructing # their own semver string. return SemverVersion(major=major, minor=minor, patch=patch, prerelease=prerelease)
def tag_version(ctx, push=False): version = Version.parse(__version__) log('Tagging revision: v%s' % version) ctx.run('git tag v%s' % version) if push: log('Pushing tags...') ctx.run('git push --tags')
def test_validation_value(kwargs): if 'release' not in kwargs: kwargs['release'] = 1 with pytest.raises(ValueError): # print so we can see output when test fails print(Version(**kwargs))
def test_attributes(kwargs, values, version): # save us repeating ourselves in test data above kwargs.setdefault('release', 1) v = Version(**kwargs) assert str(v) == version for key, value in values.items(): assert getattr(v, key) == value
def check_pyproject_toml(): # https://packaging.python.org/tutorials/packaging-projects/ try: with open('pyproject.toml', encoding='utf8') as f: pyproject_toml = f.read() except FileNotFoundError: with open('pyproject.toml', 'w', encoding='utf8') as f: f.write(PYPROJECT_TOML) raise FileNotFoundError('pyproject.toml was not found; sample created') m = search(r'setuptools>=([\d.]+)', pyproject_toml) if not m or (Version.parse(m[1]) < Version((46, 4, 0))): raise RuntimeError( 'Please require `setuptools>=46.4.0` in pyproject.toml\n' "That's the minimum version that supports `attr` in setup.cfg.") if 'build-backend = "setuptools.build_meta"' not in pyproject_toml: raise RuntimeError( '`build-backend = "setuptools.build_meta"` not in pyproject.toml')
def tag_version(ctx, push=False): version = find_version(ctx) version = Version.parse(version) log("Tagging revision: v%s" % version.normalize()) ctx.run("git tag v%s" % version.normalize()) if push: log("Pushing tags...") ctx.run("git push origin master") ctx.run("git push --tags")
def tag_version(ctx, push=False): version = find_version(ctx) version = Version.parse(version) log('Tagging revision: v%s' % version.normalize()) ctx.run('git tag v%s' % version.normalize()) if push: log('Pushing tags...') ctx.run('git push origin master') ctx.run('git push --tags')
def get_release_version( current_version: Version, release_type: ReleaseType = None ) -> Version: """Return the next version according to git log.""" if release_type is DEV: if current_version.is_devrelease: return current_version.bump_dev() return current_version.bump_release(index=2).bump_dev() if release_type is None: release_type = get_release_type() if SIMULATE is True: print(f'* {release_type}') base_version = current_version.base_version() # removes devN if release_type is PATCH: return base_version if release_type is MINOR or current_version < Version(1): # do not change an early development version to a major release # that type of change should be more explicit (edit versions). return base_version.bump_release(index=1) return base_version.bump_release(index=0)
def __init__(self, path: Path): file = self._file = path.open('r+', newline='\n') text = file.read() if SIMULATE is True: print(f'* reading {path}') from io import StringIO self._file = StringIO(text) match = search(r'\b__version__\s*=\s*([\'"])(.*?)\1', text) self._offset, end = match.span(2) self._trail = text[end:] self._version = Version.parse(match[2])
def bump_version( ctx, dry_run=False, major=False, minor=False, micro=True, dev=False, pre=False, post=False, tag=None, clear=False, commit=False, ): _current_version = get_version(ctx) current_version = Version.parse(_current_version) new_version = current_version if pre and not tag and not clear: print('Using "pre" requires a corresponding tag.') return if pre and dev and not clear: print("Pre and dev cannot be used together.") return if not dev and not pre and not post: new_version = new_version.clear(pre=True, dev=True, post=True) elif dev: new_version = new_version.bump_dev() elif pre: new_version = new_version.bump_pre(tag=tag) if major: new_version = new_version.bump_release(0) elif minor: new_version = new_version.bump_release(1) elif micro: new_version = new_version.bump_release(2) elif post: new_version = new_version.bump_post("post").bump_post("post") if clear: new_version = new_version.clear(dev=True, pre=True, post=True) log('Updating version to %s' % new_version.normalize()) version_file = get_version_file(ctx) file_contents = version_file.read_text() log('Found current version: %s' % _current_version) if dry_run: log('Would update to: %s' % new_version.normalize()) else: log('Updating to: %s' % new_version.normalize()) version_file.write_text( file_contents.replace(_current_version, str(new_version.normalize()))) if commit: ctx.run('git add {0}'.format(get_version_file(ctx))) log('Committing...') ctx.run('git commit -s -m "Bumped version."')
def bump_version(ctx, dry_run=False, dev=False, pre=False, tag=None, commit=False, month_offset="0", trunc_month=False): current_version = Version.parse(__version__) today = datetime.date.today() day_offset = 0 tomorrow = today + datetime.timedelta(days=1) month_offset = int(month_offset) if month_offset: # if we are offsetting by a month, grab the first day of the month trunc_month = True else: target_day = today if dev or pre: target_day = date_offset(today, day_offset=1) target_day = date_offset(today, month_offset=month_offset, day_offset=day_offset, truncate=trunc_month) log("target_day: {0}".format(target_day)) target_timetuple = target_day.timetuple()[:3] new_version = current_version.replace(release=target_timetuple) if pre and dev: raise RuntimeError("Can't use 'pre' and 'dev' together!") if dev: new_version = new_version.replace(pre=None).bump_dev() elif pre: if not tag: print('Using "pre" requires a corresponding tag.') return new_version = new_version.bump_pre(tag=tag) else: new_version = new_version.replace(pre=None, dev=None) log("Updating version to %s" % new_version.normalize()) version = find_version(ctx) log("Found current version: %s" % version) if dry_run: log("Would update to: %s" % new_version.normalize()) else: log("Updating to: %s" % new_version.normalize()) version_file = get_version_file(ctx) file_contents = version_file.read_text() version_file.write_text( file_contents.replace(version, str(new_version.normalize()))) if commit: ctx.run("git add {0}".format(version_file.as_posix())) log("Committing...") ctx.run('git commit -s -m "Bumped version."')
def build_docs(ctx): _current_version = get_version(ctx) minor = [str(i) for i in Version.parse(_current_version).release[:2]] docs_folder = (_get_git_root(ctx) / 'docs').as_posix() if not docs_folder.endswith('/'): docs_folder = '{0}/'.format(docs_folder) args = ["--ext-autodoc", "--ext-viewcode", "-o", docs_folder] args.extend(["-A", "'Dan Ryan <*****@*****.**>'"]) args.extend(["-R", _current_version]) args.extend(["-V", ".".join(minor)]) args.extend(["-e", "-M", "-F", "src/requirementslib"]) log("Building docs...") ctx.run("sphinx-apidoc {0}".format(" ".join(args)))
def bump_version(ctx, dry_run=False, increment=True, release=False, dev=False, pre=False, tag=None, clear=False, commit=False,): current_version = Version.parse(__version__) today = datetime.date.today() next_month_number = today.month + 1 if today.month != 12 else 1 next_year_number = today.year if next_month_number != 1 else today.year+1 next_month = (next_year_number, next_month_number, 0) if pre and not tag: print('Using "pre" requires a corresponding tag.') return if release and not dev and not pre and increment: new_version = current_version.replace(release=today.timetuple()[:3]).clear(pre=True, dev=True) elif release and (dev or pre): if increment: new_version = current_version.replace(release=today.timetuple()[:3]) else: new_version = current_version if dev: new_version = new_version.bump_dev() elif pre: new_version = new_version.bump_pre(tag=tag) else: if not release: increment = False if increment: new_version = current_version.replace(release=next_month) else: new_version = current_version if dev: new_version = new_version.bump_dev() elif pre: new_version = new_version.bump_pre(tag=tag) if clear: new_version = new_version.clear(dev=True, pre=True, post=True) log('Updating version to %s' % new_version.normalize()) version_file = get_version_file(ctx) file_contents = version_file.read_text() log('Found current version: %s' % __version__) if dry_run: log('Would update to: %s' % new_version.normalize()) else: log('Updating to: %s' % new_version.normalize()) version_file.write_text(file_contents.replace(__version__, str(new_version.normalize()))) if commit: ctx.run('git add {0}'.format(version_file)) log('Committing...') ctx.run('git commit -s -m "Bumped version."')
def bump_version(ctx, dry_run=False, dev=False, pre=False, tag=None, commit=False): current_version = Version.parse(__version__) today = datetime.date.today() tomorrow = today + datetime.timedelta(days=1) next_month = datetime.date.today().replace(month=today.month + 1, day=1) next_year = datetime.date.today().replace(year=today.year + 1, month=1, day=1) if pre and not tag: print('Using "pre" requires a corresponding tag.') return if not (dev or pre or tag): new_version = current_version.replace( release=today.timetuple()[:3]).clear(pre=True, dev=True) if pre and dev: raise RuntimeError("Can't use 'pre' and 'dev' together!") if dev or pre: new_version = current_version.replace( release=tomorrow.timetuple()[:3]).clear(pre=True, dev=True) if dev: new_version = new_version.bump_dev() else: new_version = new_version.bump_pre(tag=tag) log('Updating version to %s' % new_version.normalize()) version = find_version(ctx) log('Found current version: %s' % version) if dry_run: log('Would update to: %s' % new_version.normalize()) else: log('Updating to: %s' % new_version.normalize()) version_file = get_version_file(ctx) file_contents = version_file.read_text() version_file.write_text( file_contents.replace(version, str(new_version.normalize()))) if commit: ctx.run('git add {0}'.format(version_file.as_posix())) log('Committing...') ctx.run('git commit -s -m "Bumped version."')
def test_init(vargs, s): args, kwargs = vargs assert str(Version(*args, **kwargs)) == s
def test_ambiguous(): with pytest.raises(ValueError, match='post_tag.*pre'): Version(release=1, pre_tag='rc', post=2, post_tag=None)
def test_is_release_candidate(version): v = Version.parse(version) assert not v.is_alpha assert not v.is_beta assert v.is_release_candidate
def test_release_tuple(): v = Version(release=[1, 2]) assert isinstance(v.release, tuple)
def test_bump_dev(before, after): assert str(Version.parse(before).bump_dev()) == after
def test_bump_post(before, kwargs, after): assert str(Version.parse(before).bump_post(**kwargs)) == after
def test_bump_pre_error(version, tag): with pytest.raises(ValueError): print(Version.parse(version).bump_pre(tag))
def test_bump_pre(before, tag, after): assert str(Version.parse(before).bump_pre(tag)) == after
def test_bump_release_error(index, exc): with pytest.raises(exc): print(Version(release=1).bump_release(index))