| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654 | """versioneer.py(like a rocketeer, but for versions)* https://github.com/warner/python-versioneer* Brian Warner* License: Public Domain* Version: 0.7+This file helps distutils-based projects manage their version number by justcreating version-control tags.For developers who work from a VCS-generated tree (e.g. 'git clone' etc),each 'setup.py version', 'setup.py build', 'setup.py sdist' will compute aversion number by asking your version-control tool about the currentcheckout. The version number will be written into a generated _version.pyfile of your choosing, where it can be included by your __init__.pyFor users who work from a VCS-generated tarball (e.g. 'git archive'), it willcompute a version number by looking at the name of the directory created whente tarball is unpacked. This conventionally includes both the name of theproject and a version number.For users who work from a tarball built by 'setup.py sdist', it will get aversion number from a previously-generated _version.py file.As a result, loading code directly from the source tree will not result in areal version. If you want real versions from VCS trees (where you frequentlyupdate from the upstream repository, or do new development), you will need todo a 'setup.py version' after each update, and load code from the build/directory.You need to provide this code with a few configuration values: versionfile_source:    A project-relative pathname into which the generated version strings    should be written. This is usually a _version.py next to your project's    main __init__.py file. If your project uses src/myproject/__init__.py,    this should be 'src/myproject/_version.py'. This file should be checked    in to your VCS as usual: the copy created below by 'setup.py    update_files' will include code that parses expanded VCS keywords in    generated tarballs. The 'build' and 'sdist' commands will replace it with    a copy that has just the calculated version string. versionfile_build:    Like versionfile_source, but relative to the build directory instead of    the source directory. These will differ when your setup.py uses    'package_dir='. If you have package_dir={'myproject': 'src/myproject'},    then you will probably have versionfile_build='myproject/_version.py' and    versionfile_source='src/myproject/_version.py'. tag_prefix: a string, like 'PROJECTNAME-', which appears at the start of all             VCS tags. If your tags look like 'myproject-1.2.0', then you             should use tag_prefix='myproject-'. If you use unprefixed tags             like '1.2.0', this should be an empty string. parentdir_prefix: a string, frequently the same as tag_prefix, which                   appears at the start of all unpacked tarball filenames. If                   your tarball unpacks into 'myproject-1.2.0', this should                   be 'myproject-'.To use it: 1: include this file in the top level of your project 2: make the following changes to the top of your setup.py:     import versioneer     versioneer.versionfile_source = 'src/myproject/_version.py'     versioneer.versionfile_build = 'myproject/_version.py'     versioneer.tag_prefix = '' # tags are like 1.2.0     versioneer.parentdir_prefix = 'myproject-' # dirname like 'myproject-1.2.0' 3: add the following arguments to the setup() call in your setup.py:     version=versioneer.get_version(),     cmdclass=versioneer.get_cmdclass(), 4: run 'setup.py update_files', which will create _version.py, and will    append the following to your __init__.py:     from _version import __version__ 5: modify your MANIFEST.in to include versioneer.py 6: add both versioneer.py and the generated _version.py to your VCS"""import os, sys, refrom distutils.core import Commandfrom distutils.command.sdist import sdist as _sdistfrom distutils.command.build import build as _buildversionfile_source = Noneversionfile_build = Nonetag_prefix = Noneparentdir_prefix = NoneVCS = "git"IN_LONG_VERSION_PY = FalseLONG_VERSION_PY = '''IN_LONG_VERSION_PY = True# This file helps to compute a version number in source trees obtained from# git-archive tarball (such as those provided by githubs download-from-tag# feature). Distribution tarballs (build by setup.py sdist) and build# directories (produced by setup.py build) will contain a much shorter file# that just contains the computed version number.# This file is released into the public domain. Generated by# versioneer-0.7+ (https://github.com/warner/python-versioneer)# these strings will be replaced by git during git-archivegit_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s"git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s"import subprocessimport sysdef run_command(args, cwd=None, verbose=False):    try:        # remember shell=False, so use git.cmd on windows, not just git        p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd)    except EnvironmentError:        e = sys.exc_info()[1]        if verbose:            print("unable to run %%s" %% args[0])            print(e)        return None    stdout = p.communicate()[0].strip()    if sys.version >= '3':        stdout = stdout.decode()    if p.returncode != 0:        if verbose:            print("unable to run %%s (error)" %% args[0])        return None    return stdoutimport sysimport reimport os.pathdef get_expanded_variables(versionfile_source):    # the code embedded in _version.py can just fetch the value of these    # variables. When used from setup.py, we don't want to import    # _version.py, so we do it with a regexp instead. This function is not    # used from _version.py.    variables = {}    try:        for line in open(versionfile_source,"r").readlines():            if line.strip().startswith("git_refnames ="):                mo = re.search(r'=\s*"(.*)"', line)                if mo:                    variables["refnames"] = mo.group(1)            if line.strip().startswith("git_full ="):                mo = re.search(r'=\s*"(.*)"', line)                if mo:                    variables["full"] = mo.group(1)    except EnvironmentError:        pass    return variablesdef versions_from_expanded_variables(variables, tag_prefix, verbose=False):    refnames = variables["refnames"].strip()    if refnames.startswith("$Format"):        if verbose:            print("variables are unexpanded, not using")        return {} # unexpanded, so not in an unpacked git-archive tarball    refs = set([r.strip() for r in refnames.strip("()").split(",")])    for ref in list(refs):        if not re.search(r'\d', ref):            if verbose:                print("discarding '%%s', no digits" %% ref)            refs.discard(ref)            # Assume all version tags have a digit. git's %%d expansion            # behaves like git log --decorate=short and strips out the            # refs/heads/ and refs/tags/ prefixes that would let us            # distinguish between branches and tags. By ignoring refnames            # without digits, we filter out many common branch names like            # "release" and "stabilization", as well as "HEAD" and "master".    if verbose:        print("remaining refs: %%s" %% ",".join(sorted(refs)))    for ref in sorted(refs):        # sorting will prefer e.g. "2.0" over "2.0rc1"        if ref.startswith(tag_prefix):            r = ref[len(tag_prefix):]            if verbose:                print("picking %%s" %% r)            return { "version": r,                     "full": variables["full"].strip() }    # no suitable tags, so we use the full revision id    if verbose:        print("no suitable tags, using full revision id")    return { "version": variables["full"].strip(),             "full": variables["full"].strip() }def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):    # this runs 'git' from the root of the source tree. That either means    # someone ran a setup.py command (and this code is in versioneer.py, so    # IN_LONG_VERSION_PY=False, thus the containing directory is the root of    # the source tree), or someone ran a project-specific entry point (and    # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the    # containing directory is somewhere deeper in the source tree). This only    # gets called if the git-archive 'subst' variables were *not* expanded,    # and _version.py hasn't already been rewritten with a short version    # string, meaning we're inside a checked out source tree.    try:        here = os.path.abspath(__file__)    except NameError:        # some py2exe/bbfreeze/non-CPython implementations don't do __file__        return {} # not always correct    # versionfile_source is the relative path from the top of the source tree    # (where the .git directory might live) to this file. Invert this to find    # the root from __file__.    root = here    if IN_LONG_VERSION_PY:        for i in range(len(versionfile_source.split("/"))):            root = os.path.dirname(root)    else:        root = os.path.dirname(here)    if not os.path.exists(os.path.join(root, ".git")):        if verbose:            print("no .git in %%s" %% root)        return {}    GIT = "git"    if sys.platform == "win32":        GIT = "git.cmd"    stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"],                         cwd=root)    if stdout is None:        return {}    if not stdout.startswith(tag_prefix):        if verbose:            print("tag '%%s' doesn't start with prefix '%%s'" %% (stdout, tag_prefix))        return {}    tag = stdout[len(tag_prefix):]    stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root)    if stdout is None:        return {}    full = stdout.strip()    if tag.endswith("-dirty"):        full += "-dirty"    return {"version": tag, "full": full}def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False):    if IN_LONG_VERSION_PY:        # We're running from _version.py. If it's from a source tree        # (execute-in-place), we can work upwards to find the root of the        # tree, and then check the parent directory for a version string. If        # it's in an installed application, there's no hope.        try:            here = os.path.abspath(__file__)        except NameError:            # py2exe/bbfreeze/non-CPython don't have __file__            return {} # without __file__, we have no hope        # versionfile_source is the relative path from the top of the source        # tree to _version.py. Invert this to find the root from __file__.        root = here        for i in range(len(versionfile_source.split("/"))):            root = os.path.dirname(root)    else:        # we're running from versioneer.py, which means we're running from        # the setup.py in a source tree. sys.argv[0] is setup.py in the root.        here = os.path.abspath(sys.argv[0])        root = os.path.dirname(here)    # Source tarballs conventionally unpack into a directory that includes    # both the project name and a version string.    dirname = os.path.basename(root)    if not dirname.startswith(parentdir_prefix):        if verbose:            print("guessing rootdir is '%%s', but '%%s' doesn't start with prefix '%%s'" %%                  (root, dirname, parentdir_prefix))        return None    return {"version": dirname[len(parentdir_prefix):], "full": ""}tag_prefix = "%(TAG_PREFIX)s"parentdir_prefix = "%(PARENTDIR_PREFIX)s"versionfile_source = "%(VERSIONFILE_SOURCE)s"def get_versions(default={"version": "unknown", "full": ""}, verbose=False):    variables = { "refnames": git_refnames, "full": git_full }    ver = versions_from_expanded_variables(variables, tag_prefix, verbose)    if not ver:        ver = versions_from_vcs(tag_prefix, versionfile_source, verbose)    if not ver:        ver = versions_from_parentdir(parentdir_prefix, versionfile_source,                                      verbose)    if not ver:        ver = default    return ver'''import subprocessimport sysdef run_command(args, cwd=None, verbose=False):    try:        # remember shell=False, so use git.cmd on windows, not just git        p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd)    except EnvironmentError:        e = sys.exc_info()[1]        if verbose:            print("unable to run %s" % args[0])            print(e)        return None    stdout = p.communicate()[0].strip()    if sys.version >= '3':        stdout = stdout.decode()    if p.returncode != 0:        if verbose:            print("unable to run %s (error)" % args[0])        return None    return stdoutimport sysimport reimport os.pathdef get_expanded_variables(versionfile_source):    # the code embedded in _version.py can just fetch the value of these    # variables. When used from setup.py, we don't want to import    # _version.py, so we do it with a regexp instead. This function is not    # used from _version.py.    variables = {}    try:        for line in open(versionfile_source,"r").readlines():            if line.strip().startswith("git_refnames ="):                mo = re.search(r'=\s*"(.*)"', line)                if mo:                    variables["refnames"] = mo.group(1)            if line.strip().startswith("git_full ="):                mo = re.search(r'=\s*"(.*)"', line)                if mo:                    variables["full"] = mo.group(1)    except EnvironmentError:        pass    return variablesdef versions_from_expanded_variables(variables, tag_prefix, verbose=False):    refnames = variables["refnames"].strip()    if refnames.startswith("$Format"):        if verbose:            print("variables are unexpanded, not using")        return {} # unexpanded, so not in an unpacked git-archive tarball    refs = set([r.strip() for r in refnames.strip("()").split(",")])    for ref in list(refs):        if not re.search(r'\d', ref):            if verbose:                print("discarding '%s', no digits" % ref)            refs.discard(ref)            # Assume all version tags have a digit. git's %d expansion            # behaves like git log --decorate=short and strips out the            # refs/heads/ and refs/tags/ prefixes that would let us            # distinguish between branches and tags. By ignoring refnames            # without digits, we filter out many common branch names like            # "release" and "stabilization", as well as "HEAD" and "master".    if verbose:        print("remaining refs: %s" % ",".join(sorted(refs)))    for ref in sorted(refs):        # sorting will prefer e.g. "2.0" over "2.0rc1"        if ref.startswith(tag_prefix):            r = ref[len(tag_prefix):]            if verbose:                print("picking %s" % r)            return { "version": r,                     "full": variables["full"].strip() }    # no suitable tags, so we use the full revision id    if verbose:        print("no suitable tags, using full revision id")    return { "version": variables["full"].strip(),             "full": variables["full"].strip() }def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):    # this runs 'git' from the root of the source tree. That either means    # someone ran a setup.py command (and this code is in versioneer.py, so    # IN_LONG_VERSION_PY=False, thus the containing directory is the root of    # the source tree), or someone ran a project-specific entry point (and    # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the    # containing directory is somewhere deeper in the source tree). This only    # gets called if the git-archive 'subst' variables were *not* expanded,    # and _version.py hasn't already been rewritten with a short version    # string, meaning we're inside a checked out source tree.    try:        here = os.path.abspath(__file__)    except NameError:        # some py2exe/bbfreeze/non-CPython implementations don't do __file__        return {} # not always correct    # versionfile_source is the relative path from the top of the source tree    # (where the .git directory might live) to this file. Invert this to find    # the root from __file__.    root = here    if IN_LONG_VERSION_PY:        for i in range(len(versionfile_source.split("/"))):            root = os.path.dirname(root)    else:        root = os.path.dirname(here)    if not os.path.exists(os.path.join(root, ".git")):        if verbose:            print("no .git in %s" % root)        return {}    GIT = "git"    if sys.platform == "win32":        GIT = "git.cmd"    stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"],                         cwd=root)    if stdout is None:        return {}    if not stdout.startswith(tag_prefix):        if verbose:            print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix))        return {}    tag = stdout[len(tag_prefix):]    stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root)    if stdout is None:        return {}    full = stdout.strip()    if tag.endswith("-dirty"):        full += "-dirty"    return {"version": tag, "full": full}def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False):    if IN_LONG_VERSION_PY:        # We're running from _version.py. If it's from a source tree        # (execute-in-place), we can work upwards to find the root of the        # tree, and then check the parent directory for a version string. If        # it's in an installed application, there's no hope.        try:            here = os.path.abspath(__file__)        except NameError:            # py2exe/bbfreeze/non-CPython don't have __file__            return {} # without __file__, we have no hope        # versionfile_source is the relative path from the top of the source        # tree to _version.py. Invert this to find the root from __file__.        root = here        for i in range(len(versionfile_source.split("/"))):            root = os.path.dirname(root)    else:        # we're running from versioneer.py, which means we're running from        # the setup.py in a source tree. sys.argv[0] is setup.py in the root.        here = os.path.abspath(sys.argv[0])        root = os.path.dirname(here)    # Source tarballs conventionally unpack into a directory that includes    # both the project name and a version string.    dirname = os.path.basename(root)    if not dirname.startswith(parentdir_prefix):        if verbose:            print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" %                  (root, dirname, parentdir_prefix))        return None    return {"version": dirname[len(parentdir_prefix):], "full": ""}import sysdef do_vcs_install(versionfile_source, ipy):    GIT = "git"    if sys.platform == "win32":        GIT = "git.cmd"    run_command([GIT, "add", "versioneer.py"])    run_command([GIT, "add", versionfile_source])    run_command([GIT, "add", ipy])    present = False    try:        f = open(".gitattributes", "r")        for line in f.readlines():            if line.strip().startswith(versionfile_source):                if "export-subst" in line.strip().split()[1:]:                    present = True        f.close()    except EnvironmentError:        pass        if not present:        f = open(".gitattributes", "a+")        f.write("%s export-subst\n" % versionfile_source)        f.close()        run_command([GIT, "add", ".gitattributes"])    SHORT_VERSION_PY = """# This file was generated by 'versioneer.py' (0.7+) from# revision-control system data, or from the parent directory name of an# unpacked source archive. Distribution tarballs contain a pre-generated copy# of this file.version_version = '%(version)s'version_full = '%(full)s'def get_versions(default={}, verbose=False):    return {'version': version_version, 'full': version_full}"""DEFAULT = {"version": "unknown", "full": "unknown"}def versions_from_file(filename):    versions = {}    try:        f = open(filename)    except EnvironmentError:        return versions    for line in f.readlines():        mo = re.match("version_version = '([^']+)'", line)        if mo:            versions["version"] = mo.group(1)        mo = re.match("version_full = '([^']+)'", line)        if mo:            versions["full"] = mo.group(1)    return versionsdef write_to_version_file(filename, versions):    f = open(filename, "w")    f.write(SHORT_VERSION_PY % versions)    f.close()    print("set %s to '%s'" % (filename, versions["version"]))def get_best_versions(versionfile, tag_prefix, parentdir_prefix,                      default=DEFAULT, verbose=False):    # returns dict with two keys: 'version' and 'full'    #    # extract version from first of _version.py, 'git describe', parentdir.    # This is meant to work for developers using a source checkout, for users    # of a tarball created by 'setup.py sdist', and for users of a    # tarball/zipball created by 'git archive' or github's download-from-tag    # feature.    variables = get_expanded_variables(versionfile_source)    if variables:        ver = versions_from_expanded_variables(variables, tag_prefix)        if ver:            if verbose: print("got version from expanded variable %s" % ver)            return ver    ver = versions_from_file(versionfile)    if ver:        if verbose: print("got version from file %s %s" % (versionfile, ver))        return ver    ver = versions_from_vcs(tag_prefix, versionfile_source, verbose)    if ver:        if verbose: print("got version from git %s" % ver)        return ver    ver = versions_from_parentdir(parentdir_prefix, versionfile_source, verbose)    if ver:        if verbose: print("got version from parentdir %s" % ver)        return ver    if verbose: print("got version from default %s" % ver)    return defaultdef get_versions(default=DEFAULT, verbose=False):    assert versionfile_source is not None, "please set versioneer.versionfile_source"    assert tag_prefix is not None, "please set versioneer.tag_prefix"    assert parentdir_prefix is not None, "please set versioneer.parentdir_prefix"    return get_best_versions(versionfile_source, tag_prefix, parentdir_prefix,                             default=default, verbose=verbose)def get_version(verbose=False):    return get_versions(verbose=verbose)["version"]class cmd_version(Command):    description = "report generated version string"    user_options = []    boolean_options = []    def initialize_options(self):        pass    def finalize_options(self):        pass    def run(self):        ver = get_version(verbose=True)        print("Version is currently: %s" % ver)class cmd_build(_build):    def run2(self):        versions = get_versions(verbose=True)        _build.run(self)        # now locate _version.py in the new build/ directory and replace it        # with an updated value        target_versionfile = os.path.join(self.build_lib, versionfile_build)        print("UPDATING %s" % target_versionfile)        os.unlink(target_versionfile)        f = open(target_versionfile, "w")        f.write(SHORT_VERSION_PY % versions)        f.close()class cmd_sdist(_sdist):    def run(self):        versions = get_versions(verbose=True)        self._versioneer_generated_versions = versions        # unless we update this, the command will keep using the old version        self.distribution.metadata.version = versions["version"]        return _sdist.run(self)    def make_release_tree(self, base_dir, files):        _sdist.make_release_tree(self, base_dir, files)        # now locate _version.py in the new base_dir directory (remembering        # that it may be a hardlink) and replace it with an updated value        target_versionfile = os.path.join(base_dir, versionfile_source)        print("UPDATING %s" % target_versionfile)        os.unlink(target_versionfile)        f = open(target_versionfile, "w")        f.write(SHORT_VERSION_PY % self._versioneer_generated_versions)        f.close()INIT_PY_SNIPPET = """from ._version import get_versions__version__ = get_versions()['version']del get_versions"""class cmd_update_files(Command):    description = "modify __init__.py and create _version.py"    user_options = []    boolean_options = []    def initialize_options(self):        pass    def finalize_options(self):        pass    def run(self):        ipy = os.path.join(os.path.dirname(versionfile_source), "__init__.py")        print(" creating %s" % versionfile_source)        f = open(versionfile_source, "w")        f.write(LONG_VERSION_PY % {"DOLLAR": "$",                                   "TAG_PREFIX": tag_prefix,                                   "PARENTDIR_PREFIX": parentdir_prefix,                                   "VERSIONFILE_SOURCE": versionfile_source,                                   })        f.close()        try:            old = open(ipy, "r").read()        except EnvironmentError:            old = ""        if INIT_PY_SNIPPET not in old:            print(" appending to %s" % ipy)            f = open(ipy, "a")            f.write(INIT_PY_SNIPPET)            f.close()        else:            print(" %s unmodified" % ipy)        do_vcs_install(versionfile_source, ipy)def get_cmdclass():    return {'version': cmd_version,            'update_files': cmd_update_files,            'build': cmd_build,            'sdist': cmd_sdist,            }
 |