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 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 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 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 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 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 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 __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 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 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_bump_pre(before, tag, after): assert str(Version.parse(before).bump_pre(tag)) == after
def test_bump_release(before, index, after): assert str(Version.parse(before).bump_release(index)) == after
def test_clear(before, kwargs, after): assert str(Version.parse(before).clear(**kwargs)) == after
def test_replace(before, kwargs, after): """Make sure the keys we expect are passed through.""" assert str(Version.parse(before).replace(**kwargs)) == after
def test_truncate_error(): with pytest.raises(TypeError, match='min_length'): Version.parse('1').truncate(min_length='banana') with pytest.raises(ValueError, match='min_length'): Version.parse('1').truncate(min_length=0)
def test_bump_dev(before, after): assert str(Version.parse(before).bump_dev()) == after
def test_set_release(before, index, value, after): v = Version.parse(before).set_release(index=index, value=value) assert str(v) == after
def test_bump_release_to(before, index, value, after): v = Version.parse(before).bump_release_to(index=index, value=value) assert str(v) == after
def version_strategy(draw, strict=False): return Version.parse(draw(version_string(strict=strict)))
def test_bump_pre_error(version, tag): with pytest.raises(ValueError): print(Version.parse(version).bump_pre(tag))
def test_bump_pre(before, tag, kwargs, after): assert str(Version.parse(before).bump_pre(tag, **kwargs)) == after
def test_bump_post(before, kwargs, after): assert str(Version.parse(before).bump_post(**kwargs)) == after
def test_truncate(before, after, kwargs): v = Version.parse(before).truncate(**kwargs) assert str(v) == after
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_parse_local_strict(version): with pytest.raises(ParseError): Version.parse(version, strict=True) Version.parse(version)