Commit 1773491b authored by Wei Shoulin's avatar Wei Shoulin
Browse files

rename and api defined

parent d5fcbad0
This directory contains eggs that were downloaded by setuptools to build, test, and run plug-ins.
This directory caches those eggs to prevent repeated downloads.
However, it is safe to delete this directory.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
This diff is collapsed.
setuptools_scm/__init__.py,sha256=0NWHUiWlSYqA7whMYsVAVrmnujn_NPFt-AP-9EOAIIA,5578
setuptools_scm/__main__.py,sha256=r2weno4bqNJ3pFJCrArU2ryJOKNWZ_pg1Fz6wiEe6t0,423
setuptools_scm/config.py,sha256=nlMUfZhtzCz40iYXOq6adW9UB8PS8TS6jPDaGECOdHs,4282
setuptools_scm/discover.py,sha256=LqX0raq94k3llpxXmjNnDbkqECIGqEm1UcU3g2Rn2NI,416
setuptools_scm/file_finder.py,sha256=PTYcZXz6yZAhmsCaRcVd3EPe2p_f5T6Su4RYvqpWjhU,2548
setuptools_scm/file_finder_git.py,sha256=9KPibz5-qJG0170WpEgIhTD6NP1XkXjZyDTZaaTmL6M,2316
setuptools_scm/file_finder_hg.py,sha256=G5-sPQjHU3Kg7LGPtAtbvsFIVmPLgSc4-9ak5Mf3E1k,1487
setuptools_scm/git.py,sha256=p0El7RQOs3Tg68yzr-lOmm2DQNcdlW64DtaLfrdbWlk,4205
setuptools_scm/hacks.py,sha256=KEhSSGKLaTCfQVdqAZ8JUcdL5KIZBg0K_AHiyPpCJOY,1277
setuptools_scm/hg.py,sha256=F9gqx3S5u0m4tpOcZhGLbWBtt0qCoLdyAVQkXIIrnqE,3387
setuptools_scm/integration.py,sha256=tJK_iTyQj-haKjohnpa5RIcxUAdQvRXgiP5vwGeNCOI,1690
setuptools_scm/utils.py,sha256=JrpjpyzBaNP5-7uuANHJW0c7H2AJ26OLpCpkjLGcr88,3772
setuptools_scm/version.py,sha256=RKSwD0drbqE2Fc8VF9ltGhI76M28RrtaWRPZ3EjPE10,10814
setuptools_scm/win_py31_compat.py,sha256=w-TAp2Z21O_shi3gPvlcbxz1JZ8cGOLFd9HguCTYB6E,5098
setuptools_scm-5.0.1.dist-info/LICENSE,sha256=iYB6zyMJvShfAzQE7nhYFgLzzZuBmhasLw5fYP9KRz4,1023
setuptools_scm-5.0.1.dist-info/METADATA,sha256=QoFZ61ieCfZIxA_g5mJAtHKh2yHnIGaZoajm2pb9lvE,21762
setuptools_scm-5.0.1.dist-info/WHEEL,sha256=Z-nyYpwrcSqxfdux5Mbn_DQ525iP7J2DG3JgGvOYyTQ,110
setuptools_scm-5.0.1.dist-info/entry_points.txt,sha256=-ltXW9C7w2CaE7aerUXpZClGXQCCsm67Os_PA5oQjx4,1385
setuptools_scm-5.0.1.dist-info/top_level.txt,sha256=kiu-91q3_rJLUoc2wl8_lC4cIlpgtgdD_4NaChF4hOA,15
setuptools_scm-5.0.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
setuptools_scm-5.0.1.dist-info/RECORD,,
Wheel-Version: 1.0
Generator: bdist_wheel (0.36.2)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any
[distutils.setup_keywords]
use_scm_version = setuptools_scm.integration:version_keyword
[setuptools.file_finders]
setuptools_scm = setuptools_scm.integration:find_files
[setuptools.finalize_distribution_options]
setuptools_scm = setuptools_scm.integration:infer_version
[setuptools_scm.files_command]
.git = setuptools_scm.file_finder_git:git_find_files
.hg = setuptools_scm.file_finder_hg:hg_find_files
[setuptools_scm.local_scheme]
dirty-tag = setuptools_scm.version:get_local_dirty_tag
no-local-version = setuptools_scm.version:get_no_local_node
node-and-date = setuptools_scm.version:get_local_node_and_date
node-and-timestamp = setuptools_scm.version:get_local_node_and_timestamp
[setuptools_scm.parse_scm]
.git = setuptools_scm.git:parse
.hg = setuptools_scm.hg:parse
[setuptools_scm.parse_scm_fallback]
.hg_archival.txt = setuptools_scm.hg:parse_archival
PKG-INFO = setuptools_scm.hacks:parse_pkginfo
pip-egg-info = setuptools_scm.hacks:parse_pip_egg_info
setup.py = setuptools_scm.hacks:fallback_version
[setuptools_scm.version_scheme]
guess-next-dev = setuptools_scm.version:guess_next_dev_version
no-guess-dev = setuptools_scm.version:no_guess_dev_version
post-release = setuptools_scm.version:postrelease_version
python-simplified-semver = setuptools_scm.version:simplified_semver_version
release-branch-semver = setuptools_scm.version:release_branch_semver_version
"""
:copyright: 2010-2015 by Ronny Pfannschmidt
:license: MIT
"""
import os
import warnings
from .config import (
Configuration,
DEFAULT_VERSION_SCHEME,
DEFAULT_LOCAL_SCHEME,
DEFAULT_TAG_REGEX,
)
from .utils import function_has_arg, string_types, trace
from .version import format_version, meta
from .discover import iter_matching_entrypoints
PRETEND_KEY = "SETUPTOOLS_SCM_PRETEND_VERSION"
PRETEND_KEY_NAMED = PRETEND_KEY + "_FOR_{name}"
TEMPLATES = {
".py": """\
# coding: utf-8
# file generated by setuptools_scm
# don't change, don't track in version control
version = {version!r}
version_tuple = {version_tuple!r}
""",
".txt": "{version}",
}
def version_from_scm(root):
warnings.warn(
"version_from_scm is deprecated please use get_version",
category=DeprecationWarning,
)
config = Configuration()
config.root = root
# TODO: Is it API?
return _version_from_entrypoints(config)
def _call_entrypoint_fn(root, config, fn):
if function_has_arg(fn, "config"):
return fn(root, config=config)
else:
warnings.warn(
"parse functions are required to provide a named argument"
" 'config' in the future.",
category=PendingDeprecationWarning,
stacklevel=2,
)
return fn(root)
def _version_from_entrypoints(config, fallback=False):
if fallback:
entrypoint = "setuptools_scm.parse_scm_fallback"
root = config.fallback_root
else:
entrypoint = "setuptools_scm.parse_scm"
root = config.absolute_root
for ep in iter_matching_entrypoints(root, entrypoint):
version = _call_entrypoint_fn(root, config, ep.load())
if version:
return version
def dump_version(root, version, write_to, template=None):
assert isinstance(version, string_types)
if not write_to:
return
target = os.path.normpath(os.path.join(root, write_to))
ext = os.path.splitext(target)[1]
template = template or TEMPLATES.get(ext)
if template is None:
raise ValueError(
"bad file format: '{}' (of {}) \nonly *.txt and *.py are supported".format(
os.path.splitext(target)[1], target
)
)
# version_tuple: each field is converted to an int if possible or kept as string
fields = tuple(version.split("."))
version_fields = []
for field in fields:
try:
v = int(field)
except ValueError:
v = field
version_fields.append(v)
with open(target, "w") as fp:
fp.write(template.format(version=version, version_tuple=tuple(version_fields)))
def _do_parse(config):
trace("dist name:", config.dist_name)
if config.dist_name is not None:
pretended = os.environ.get(
PRETEND_KEY_NAMED.format(name=config.dist_name.upper())
)
else:
pretended = None
if pretended is None:
pretended = os.environ.get(PRETEND_KEY)
if pretended:
# we use meta here since the pretended version
# must adhere to the pep to begin with
return meta(tag=pretended, preformatted=True, config=config)
if config.parse:
parse_result = _call_entrypoint_fn(config.absolute_root, config, config.parse)
if isinstance(parse_result, string_types):
raise TypeError(
"version parse result was a string\nplease return a parsed version"
)
version = parse_result or _version_from_entrypoints(config, fallback=True)
else:
# include fallbacks after dropping them from the main entrypoint
version = _version_from_entrypoints(config) or _version_from_entrypoints(
config, fallback=True
)
if version:
return version
raise LookupError(
"setuptools-scm was unable to detect version for %r.\n\n"
"Make sure you're either building from a fully intact git repository "
"or PyPI tarballs. Most other sources (such as GitHub's tarballs, a "
"git checkout without the .git folder) don't contain the necessary "
"metadata and will not work.\n\n"
"For example, if you're using pip, instead of "
"https://github.com/user/proj/archive/master.zip "
"use git+https://github.com/user/proj.git#egg=proj" % config.absolute_root
)
def get_version(
root=".",
version_scheme=DEFAULT_VERSION_SCHEME,
local_scheme=DEFAULT_LOCAL_SCHEME,
write_to=None,
write_to_template=None,
relative_to=None,
tag_regex=DEFAULT_TAG_REGEX,
parentdir_prefix_version=None,
fallback_version=None,
fallback_root=".",
parse=None,
git_describe_command=None,
dist_name=None,
):
"""
If supplied, relative_to should be a file from which root may
be resolved. Typically called by a script or module that is not
in the root of the repository to direct setuptools_scm to the
root of the repository by supplying ``__file__``.
"""
config = Configuration(**locals())
return _get_version(config)
def _get_version(config):
parsed_version = _do_parse(config)
if parsed_version:
version_string = format_version(
parsed_version,
version_scheme=config.version_scheme,
local_scheme=config.local_scheme,
)
dump_version(
root=config.root,
version=version_string,
write_to=config.write_to,
template=config.write_to_template,
)
return version_string
from __future__ import print_function
import sys
from setuptools_scm import get_version
from setuptools_scm.integration import find_files
from setuptools_scm.version import _warn_if_setuptools_outdated
def main():
_warn_if_setuptools_outdated()
print("Guessed Version", get_version())
if "ls" in sys.argv:
for fname in find_files("."):
print(fname)
if __name__ == "__main__":
main()
""" configuration """
from __future__ import print_function, unicode_literals
import os
import re
import warnings
from .utils import trace
DEFAULT_TAG_REGEX = r"^(?:[\w-]+-)?(?P<version>[vV]?\d+(?:\.\d+){0,2}[^\+]*)(?:\+.*)?$"
DEFAULT_VERSION_SCHEME = "guess-next-dev"
DEFAULT_LOCAL_SCHEME = "node-and-date"
def _check_tag_regex(value):
if not value:
value = DEFAULT_TAG_REGEX
regex = re.compile(value)
group_names = regex.groupindex.keys()
if regex.groups == 0 or (regex.groups > 1 and "version" not in group_names):
warnings.warn(
"Expected tag_regex to contain a single match group or a group named"
" 'version' to identify the version part of any tag."
)
return regex
def _check_absolute_root(root, relative_to):
trace("l", repr(locals()))
if relative_to:
if os.path.isabs(root) and not root.startswith(relative_to):
warnings.warn(
"absolute root path '%s' overrides relative_to '%s'"
% (root, relative_to)
)
if os.path.isdir(relative_to):
warnings.warn(
"relative_to is expected to be a file,"
" its the directory %r\n"
"assuming the parent directory was passed" % (relative_to,)
)
trace("dir", relative_to)
root = os.path.join(relative_to, root)
else:
trace("file", relative_to)
root = os.path.join(os.path.dirname(relative_to), root)
return os.path.abspath(root)
class Configuration(object):
""" Global configuration model """
def __init__(
self,
relative_to=None,
root=".",
version_scheme=DEFAULT_VERSION_SCHEME,
local_scheme=DEFAULT_LOCAL_SCHEME,
write_to=None,
write_to_template=None,
tag_regex=DEFAULT_TAG_REGEX,
parentdir_prefix_version=None,
fallback_version=None,
fallback_root=".",
parse=None,
git_describe_command=None,
dist_name=None,
):
# TODO:
self._relative_to = relative_to
self._root = "."
self.root = root
self.version_scheme = version_scheme
self.local_scheme = local_scheme
self.write_to = write_to
self.write_to_template = write_to_template
self.parentdir_prefix_version = parentdir_prefix_version
self.fallback_version = fallback_version
self.fallback_root = fallback_root
self.parse = parse
self.tag_regex = tag_regex
self.git_describe_command = git_describe_command
self.dist_name = dist_name
@property
def fallback_root(self):
return self._fallback_root
@fallback_root.setter
def fallback_root(self, value):
self._fallback_root = os.path.abspath(value)
@property
def absolute_root(self):
return self._absolute_root
@property
def relative_to(self):
return self._relative_to
@relative_to.setter
def relative_to(self, value):
self._absolute_root = _check_absolute_root(self._root, value)
self._relative_to = value
trace("root", repr(self._absolute_root))
trace("relative_to", repr(value))
@property
def root(self):
return self._root
@root.setter
def root(self, value):
self._absolute_root = _check_absolute_root(value, self._relative_to)
self._root = value
trace("root", repr(self._absolute_root))
trace("relative_to", repr(self._relative_to))
@property
def tag_regex(self):
return self._tag_regex
@tag_regex.setter
def tag_regex(self, value):
self._tag_regex = _check_tag_regex(value)
@classmethod
def from_file(cls, name="pyproject.toml", dist_name=None):
"""
Read Configuration from pyproject.toml (or similar).
Raises exceptions when file is not found or toml is
not installed or the file has invalid format or does
not contain the [tool.setuptools_scm] section.
"""
with open(name) as strm:
defn = __import__("toml").load(strm)
section = defn.get("tool", {})["setuptools_scm"]
return cls(dist_name=dist_name, **section)
import os
from pkg_resources import iter_entry_points
from .utils import trace
def iter_matching_entrypoints(path, entrypoint):
trace("looking for ep", entrypoint, path)
for ep in iter_entry_points(entrypoint):
if os.path.exists(os.path.join(path, ep.name)):
if os.path.isabs(ep.name):
trace("ignoring bad ep", ep)
trace("found ep", ep)
yield ep
import os
from .utils import trace
def scm_find_files(path, scm_files, scm_dirs):
""" setuptools compatible file finder that follows symlinks
- path: the root directory from which to search
- scm_files: set of scm controlled files and symlinks
(including symlinks to directories)
- scm_dirs: set of scm controlled directories
(including directories containing no scm controlled files)
scm_files and scm_dirs must be absolute with symlinks resolved (realpath),
with normalized case (normcase)
Spec here: http://setuptools.readthedocs.io/en/latest/setuptools.html#\
adding-support-for-revision-control-systems
"""
realpath = os.path.normcase(os.path.realpath(path))
seen = set()
res = []
for dirpath, dirnames, filenames in os.walk(realpath, followlinks=True):
# dirpath with symlinks resolved
realdirpath = os.path.normcase(os.path.realpath(dirpath))
def _link_not_in_scm(n):
fn = os.path.join(realdirpath, os.path.normcase(n))
return os.path.islink(fn) and fn not in scm_files
if realdirpath not in scm_dirs:
# directory not in scm, don't walk it's content
dirnames[:] = []
continue
if os.path.islink(dirpath) and not os.path.relpath(
realdirpath, realpath
).startswith(os.pardir):
# a symlink to a directory not outside path:
# we keep it in the result and don't walk its content
res.append(os.path.join(path, os.path.relpath(dirpath, path)))
dirnames[:] = []
continue
if realdirpath in seen:
# symlink loop protection
dirnames[:] = []
continue
dirnames[:] = [dn for dn in dirnames if not _link_not_in_scm(dn)]
for filename in filenames:
if _link_not_in_scm(filename):
continue
# dirpath + filename with symlinks preserved
fullfilename = os.path.join(dirpath, filename)
if os.path.normcase(os.path.realpath(fullfilename)) in scm_files:
res.append(os.path.join(path, os.path.relpath(fullfilename, realpath)))
seen.add(realdirpath)
return res
def is_toplevel_acceptable(toplevel):
""
if toplevel is None:
return False
ignored = os.environ.get("SETUPTOOLS_SCM_IGNORE_VCS_ROOTS", "").split(os.pathsep)
ignored = [os.path.normcase(p) for p in ignored]
trace(toplevel, ignored)
return toplevel not in ignored
import os
import subprocess
import tarfile
import logging
from .file_finder import scm_find_files
from .file_finder import is_toplevel_acceptable
from .utils import trace
log = logging.getLogger(__name__)
def _git_toplevel(path):
try:
with open(os.devnull, "wb") as devnull:
out = subprocess.check_output(
["git", "rev-parse", "--show-toplevel"],
cwd=(path or "."),
universal_newlines=True,
stderr=devnull,
)
trace("find files toplevel", out)
return os.path.normcase(os.path.realpath(out.strip()))
except subprocess.CalledProcessError:
# git returned error, we are not in a git repo
return None
except OSError:
# git command not found, probably
return None
def _git_interpret_archive(fd, toplevel):
with tarfile.open(fileobj=fd, mode="r|*") as tf:
git_files = set()
git_dirs = {toplevel}
for member in tf.getmembers():
name = os.path.normcase(member.name).replace("/", os.path.sep)
if member.type == tarfile.DIRTYPE:
git_dirs.add(name)
else:
git_files.add(name)
return git_files, git_dirs
def _git_ls_files_and_dirs(toplevel):
# use git archive instead of git ls-file to honor
# export-ignore git attribute
cmd = ["git", "archive", "--prefix", toplevel + os.path.sep, "HEAD"]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, cwd=toplevel)
try:
try:
return _git_interpret_archive(proc.stdout, toplevel)
finally:
# ensure we avoid resource warnings by cleaning up the process
proc.stdout.close()
proc.terminate()
except Exception:
if proc.wait() != 0:
log.exception("listing git files failed - pretending there aren't any")
return (), ()
def git_find_files(path=""):
toplevel = _git_toplevel(path)
if not is_toplevel_acceptable(toplevel):
return []
fullpath = os.path.abspath(os.path.normpath(path))
if not fullpath.startswith(toplevel):
trace("toplevel mismatch", toplevel, fullpath)
git_files, git_dirs = _git_ls_files_and_dirs(toplevel)
return scm_find_files(path, git_files, git_dirs)
import os
import subprocess
from .file_finder import scm_find_files
from .file_finder import is_toplevel_acceptable
def _hg_toplevel(path):
try:
with open(os.devnull, "wb") as devnull:
out = subprocess.check_output(
["hg", "root"],
cwd=(path or "."),
universal_newlines=True,
stderr=devnull,
)
return os.path.normcase(os.path.realpath(out.strip()))
except subprocess.CalledProcessError:
# hg returned error, we are not in a mercurial repo
return None
except OSError:
# hg command not found, probably
return None
def _hg_ls_files_and_dirs(toplevel):
hg_files = set()
hg_dirs = {toplevel}
out = subprocess.check_output(
["hg", "files"], cwd=toplevel, universal_newlines=True
)
for name in out.splitlines():
name = os.path.normcase(name).replace("/", os.path.sep)
fullname = os.path.join(toplevel, name)
hg_files.add(fullname)
dirname = os.path.dirname(fullname)
while len(dirname) > len(toplevel) and dirname not in hg_dirs:
hg_dirs.add(dirname)
dirname = os.path.dirname(dirname)
return hg_files, hg_dirs
def hg_find_files(path=""):
toplevel = _hg_toplevel(path)
if not is_toplevel_acceptable(toplevel):
return []
hg_files, hg_dirs = _hg_ls_files_and_dirs(toplevel)
return scm_find_files(path, hg_files, hg_dirs)
from .config import Configuration
from .utils import do_ex, trace, require_command
from .version import meta
from os.path import isfile, join
import warnings
try:
from os.path import samefile
except ImportError:
from .win_py31_compat import samefile
DEFAULT_DESCRIBE = "git describe --dirty --tags --long --match *[0-9]*"
class GitWorkdir(object):
"""experimental, may change at any time"""
def __init__(self, path):
self.path = path
def do_ex(self, cmd):
return do_ex(cmd, cwd=self.path)
@classmethod
def from_potential_worktree(cls, wd):
real_wd, _, ret = do_ex("git rev-parse --show-toplevel", wd)
if ret:
return
trace("real root", real_wd)
if not samefile(real_wd, wd):
return
return cls(real_wd)
def is_dirty(self):
out, _, _ = self.do_ex("git status --porcelain --untracked-files=no")
return bool(out)
def get_branch(self):
branch, err, ret = self.do_ex("git rev-parse --abbrev-ref HEAD")
if ret:
trace("branch err", branch, err, ret)
return
return branch
def is_shallow(self):
return isfile(join(self.path, ".git/shallow"))
def fetch_shallow(self):
self.do_ex("git fetch --unshallow")
def node(self):
rev_node, _, ret = self.do_ex("git rev-parse --verify --quiet HEAD")
if not ret:
return rev_node[:7]
def count_all_nodes(self):
revs, _, _ = self.do_ex("git rev-list HEAD")
return revs.count("\n") + 1
def warn_on_shallow(wd):
"""experimental, may change at any time"""
if wd.is_shallow():
warnings.warn('"{}" is shallow and may cause errors'.format(wd.path))
def fetch_on_shallow(wd):
"""experimental, may change at any time"""
if wd.is_shallow():
warnings.warn('"%s" was shallow, git fetch was used to rectify')
wd.fetch_shallow()
def fail_on_shallow(wd):
"""experimental, may change at any time"""
if wd.is_shallow():
raise ValueError(
"%r is shallow, please correct with " '"git fetch --unshallow"' % wd.path
)
def parse(
root, describe_command=DEFAULT_DESCRIBE, pre_parse=warn_on_shallow, config=None
):
"""
:param pre_parse: experimental pre_parse action, may change at any time
"""
if not config:
config = Configuration(root=root)
require_command("git")
wd = GitWorkdir.from_potential_worktree(config.absolute_root)
if wd is None:
return
if pre_parse:
pre_parse(wd)
if config.git_describe_command:
describe_command = config.git_describe_command
out, unused_err, ret = wd.do_ex(describe_command)
if ret:
# If 'git git_describe_command' failed, try to get the information otherwise.
branch, branch_err, branch_ret = wd.do_ex("git symbolic-ref --short HEAD")
if branch_ret:
branch = None
rev_node = wd.node()
dirty = wd.is_dirty()
if rev_node is None:
return meta("0.0", distance=0, dirty=dirty, branch=branch, config=config)
return meta(
"0.0",
distance=wd.count_all_nodes(),
node="g" + rev_node,
dirty=dirty,
branch=wd.get_branch(),
config=config,
)
else:
tag, number, node, dirty = _git_parse_describe(out)
branch = wd.get_branch()
if number:
return meta(
tag,
config=config,
distance=number,
node=node,
dirty=dirty,
branch=branch,
)
else:
return meta(tag, config=config, node=node, dirty=dirty, branch=branch)
def _git_parse_describe(describe_output):
# 'describe_output' looks e.g. like 'v1.5.0-0-g4060507' or
# 'v1.15.1rc1-37-g9bd1298-dirty'.
if describe_output.endswith("-dirty"):
dirty = True
describe_output = describe_output[:-6]
else:
dirty = False
tag, number, node = describe_output.rsplit("-", 2)
number = int(number)
return tag, number, node, dirty
import os
from .utils import data_from_mime, trace
from .version import tag_to_version, meta
def parse_pkginfo(root, config=None):
pkginfo = os.path.join(root, "PKG-INFO")
trace("pkginfo", pkginfo)
data = data_from_mime(pkginfo)
version = data.get("Version")
if version != "UNKNOWN":
return meta(version, preformatted=True, config=config)
def parse_pip_egg_info(root, config=None):
pipdir = os.path.join(root, "pip-egg-info")
if not os.path.isdir(pipdir):
return
items = os.listdir(pipdir)
trace("pip-egg-info", pipdir, items)
if not items:
return
return parse_pkginfo(os.path.join(pipdir, items[0]), config=config)
def fallback_version(root, config=None):
if config.parentdir_prefix_version is not None:
_, parent_name = os.path.split(os.path.abspath(root))
if parent_name.startswith(config.parentdir_prefix_version):
version = tag_to_version(
parent_name[len(config.parentdir_prefix_version) :], config
)
if version is not None:
return meta(str(version), preformatted=True, config=config)
if config.fallback_version is not None:
return meta(config.fallback_version, preformatted=True, config=config)
import os
from .config import Configuration
from .utils import do, trace, data_from_mime, require_command
from .version import meta, tags_to_versions
def _hg_tagdist_normalize_tagcommit(config, tag, dist, node, branch):
dirty = node.endswith("+")
node = "h" + node.strip("+")
# Detect changes since the specified tag
revset = (
"(branch(.)" # look for revisions in this branch only
" and tag({tag!r})::." # after the last tag
# ignore commits that only modify .hgtags and nothing else:
" and (merge() or file('re:^(?!\\.hgtags).*$'))"
" and not tag({tag!r}))" # ignore the tagged commit itself
).format(tag=tag)
if tag != "0.0":
commits = do(
["hg", "log", "-r", revset, "--template", "{node|short}"],
config.absolute_root,
)
else:
commits = True
trace("normalize", locals())
if commits or dirty:
return meta(
tag, distance=dist, node=node, dirty=dirty, branch=branch, config=config
)
else:
return meta(tag, config=config)
def parse(root, config=None):
if not config:
config = Configuration(root=root)
require_command("hg")
identity_data = do("hg id -i -b -t", config.absolute_root).split()
if not identity_data:
return
node = identity_data.pop(0)
branch = identity_data.pop(0)
if "tip" in identity_data:
# tip is not a real tag
identity_data.remove("tip")
tags = tags_to_versions(identity_data)
dirty = node[-1] == "+"
if tags:
return meta(tags[0], dirty=dirty, branch=branch, config=config)
if node.strip("+") == "0" * 12:
trace("initial node", config.absolute_root)
return meta("0.0", config=config, dirty=dirty, branch=branch)
try:
tag = get_latest_normalizable_tag(config.absolute_root)
dist = get_graph_distance(config.absolute_root, tag)
if tag == "null":
tag = "0.0"
dist = int(dist) + 1
return _hg_tagdist_normalize_tagcommit(config, tag, dist, node, branch)
except ValueError:
pass # unpacking failed, old hg
def get_latest_normalizable_tag(root):
# Gets all tags containing a '.' (see #229) from oldest to newest
cmd = [
"hg",
"log",
"-r",
"ancestors(.) and tag('re:\\.')",
"--template",
"{tags}\n",
]
outlines = do(cmd, root).split()
if not outlines:
return "null"
tag = outlines[-1].split()[-1]
return tag
def get_graph_distance(root, rev1, rev2="."):
cmd = ["hg", "log", "-q", "-r", "{}::{}".format(rev1, rev2)]
out = do(cmd, root)
return len(out.strip().splitlines()) - 1
def archival_to_version(data, config=None):
trace("data", data)
node = data.get("node", "")[:12]
if node:
node = "h" + node
if "tag" in data:
return meta(data["tag"], config=config)
elif "latesttag" in data:
return meta(
data["latesttag"],
distance=data["latesttagdistance"],
node=node,
config=config,
)
else:
return meta("0.0", node=node, config=config)
def parse_archival(root, config=None):
archival = os.path.join(root, ".hg_archival.txt")
data = data_from_mime(archival)
return archival_to_version(data, config=config)
from pkg_resources import iter_entry_points
from .version import _warn_if_setuptools_outdated
from .utils import do, trace_exception, trace
from . import _get_version, Configuration
def version_keyword(dist, keyword, value):
_warn_if_setuptools_outdated()
if not value:
return
if value is True:
value = {}
if getattr(value, "__call__", None):
value = value()
assert (
"dist_name" not in value
), "dist_name may not be specified in the setup keyword "
trace(
"version keyword",
vars(dist.metadata),
)
dist_name = dist.metadata.name
config = Configuration(dist_name=dist_name, **value)
dist.metadata.version = _get_version(config)
def find_files(path=""):
for ep in iter_entry_points("setuptools_scm.files_command"):
command = ep.load()
if isinstance(command, str):
# this technique is deprecated
res = do(ep.load(), path or ".").splitlines()
else:
res = command(path)
if res:
return res
return []
def _args_from_toml(name="pyproject.toml"):
# todo: more sensible config initialization
# move this helper back to config and unify it with the code from get_config
with open(name) as strm:
defn = __import__("toml").load(strm)
return defn.get("tool", {})["setuptools_scm"]
def infer_version(dist):
trace(
"finalize hook",
vars(dist.metadata),
)
dist_name = dist.metadata.name
try:
config = Configuration.from_file(dist_name=dist_name)
except Exception:
return trace_exception()
dist.metadata.version = _get_version(config)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment