| Total Complexity | 98 |
| Total Lines | 521 |
| Duplicated Lines | 72.17 % |
| Changes | 0 | ||
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like build.rna_tools._version often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | |||
| 2 | # This file helps to compute a version number in source trees obtained from |
||
| 3 | # git-archive tarball (such as those provided by githubs download-from-tag |
||
| 4 | # feature). Distribution tarballs (built by setup.py sdist) and build |
||
| 5 | # directories (produced by setup.py build) will contain a much shorter file |
||
| 6 | # that just contains the computed version number. |
||
| 7 | |||
| 8 | # This file is released into the public domain. Generated by |
||
| 9 | # versioneer-0.18 (https://github.com/warner/python-versioneer) |
||
| 10 | |||
| 11 | """Git implementation of _version.py.""" |
||
| 12 | |||
| 13 | import errno |
||
| 14 | import os |
||
| 15 | import re |
||
| 16 | import subprocess |
||
| 17 | import sys |
||
| 18 | |||
| 19 | |||
| 20 | def get_keywords(): |
||
| 21 | """Get the keywords needed to look up the version information.""" |
||
| 22 | # these strings will be replaced by git during git-archive. |
||
| 23 | # setup.py/versioneer.py will grep for the variable names, so they must |
||
| 24 | # each be defined on a line of their own. _version.py will just call |
||
| 25 | # get_keywords(). |
||
| 26 | git_refnames = "$Format:%d$" |
||
| 27 | git_full = "$Format:%H$" |
||
| 28 | git_date = "$Format:%ci$" |
||
| 29 | keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} |
||
| 30 | return keywords |
||
| 31 | |||
| 32 | |||
| 33 | class VersioneerConfig: |
||
| 34 | """Container for Versioneer configuration parameters.""" |
||
| 35 | |||
| 36 | |||
| 37 | def get_config(): |
||
| 38 | """Create, populate and return the VersioneerConfig() object.""" |
||
| 39 | # these strings are filled in when 'setup.py versioneer' creates |
||
| 40 | # _version.py |
||
| 41 | cfg = VersioneerConfig() |
||
| 42 | cfg.VCS = "git" |
||
| 43 | cfg.style = "pep440" |
||
| 44 | cfg.tag_prefix = "" |
||
| 45 | cfg.parentdir_prefix = "rna_tools-" |
||
| 46 | cfg.versionfile_source = "rna_tools/_version.py" |
||
| 47 | cfg.verbose = False |
||
| 48 | return cfg |
||
| 49 | |||
| 50 | |||
| 51 | class NotThisMethod(Exception): |
||
| 52 | """Exception raised if a method is not valid for the current scenario.""" |
||
| 53 | |||
| 54 | |||
| 55 | LONG_VERSION_PY = {} |
||
| 56 | HANDLERS = {} |
||
| 57 | |||
| 58 | |||
| 59 | def register_vcs_handler(vcs, method): # decorator |
||
| 60 | """Decorator to mark a method as the handler for a particular VCS.""" |
||
| 61 | def decorate(f): |
||
| 62 | """Store f in HANDLERS[vcs][method].""" |
||
| 63 | if vcs not in HANDLERS: |
||
| 64 | HANDLERS[vcs] = {} |
||
| 65 | HANDLERS[vcs][method] = f |
||
| 66 | return f |
||
| 67 | return decorate |
||
| 68 | |||
| 69 | |||
| 70 | View Code Duplication | def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, |
|
| 71 | env=None): |
||
| 72 | """Call the given command(s).""" |
||
| 73 | assert isinstance(commands, list) |
||
| 74 | p = None |
||
| 75 | for c in commands: |
||
| 76 | try: |
||
| 77 | dispcmd = str([c] + args) |
||
| 78 | # remember shell=False, so use git.cmd on windows, not just git |
||
| 79 | p = subprocess.Popen([c] + args, cwd=cwd, env=env, |
||
| 80 | stdout=subprocess.PIPE, |
||
| 81 | stderr=(subprocess.PIPE if hide_stderr |
||
| 82 | else None)) |
||
| 83 | break |
||
| 84 | except EnvironmentError: |
||
| 85 | e = sys.exc_info()[1] |
||
| 86 | if e.errno == errno.ENOENT: |
||
| 87 | continue |
||
| 88 | if verbose: |
||
| 89 | print("unable to run %s" % dispcmd) |
||
| 90 | print(e) |
||
| 91 | return None, None |
||
| 92 | else: |
||
| 93 | if verbose: |
||
| 94 | print("unable to find command, tried %s" % (commands,)) |
||
| 95 | return None, None |
||
| 96 | stdout = p.communicate()[0].strip() |
||
| 97 | if sys.version_info[0] >= 3: |
||
| 98 | stdout = stdout.decode() |
||
| 99 | if p.returncode != 0: |
||
| 100 | if verbose: |
||
| 101 | print("unable to run %s (error)" % dispcmd) |
||
| 102 | print("stdout was %s" % stdout) |
||
| 103 | return None, p.returncode |
||
| 104 | return stdout, p.returncode |
||
| 105 | |||
| 106 | |||
| 107 | View Code Duplication | def versions_from_parentdir(parentdir_prefix, root, verbose): |
|
| 108 | """Try to determine the version from the parent directory name. |
||
| 109 | |||
| 110 | Source tarballs conventionally unpack into a directory that includes both |
||
| 111 | the project name and a version string. We will also support searching up |
||
| 112 | two directory levels for an appropriately named parent directory |
||
| 113 | """ |
||
| 114 | rootdirs = [] |
||
| 115 | |||
| 116 | for i in range(3): |
||
| 117 | dirname = os.path.basename(root) |
||
| 118 | if dirname.startswith(parentdir_prefix): |
||
| 119 | return {"version": dirname[len(parentdir_prefix):], |
||
| 120 | "full-revisionid": None, |
||
| 121 | "dirty": False, "error": None, "date": None} |
||
| 122 | else: |
||
| 123 | rootdirs.append(root) |
||
| 124 | root = os.path.dirname(root) # up a level |
||
| 125 | |||
| 126 | if verbose: |
||
| 127 | print("Tried directories %s but none started with prefix %s" % |
||
| 128 | (str(rootdirs), parentdir_prefix)) |
||
| 129 | raise NotThisMethod("rootdir doesn't start with parentdir_prefix") |
||
| 130 | |||
| 131 | |||
| 132 | View Code Duplication | @register_vcs_handler("git", "get_keywords") |
|
| 133 | def git_get_keywords(versionfile_abs): |
||
| 134 | """Extract version information from the given file.""" |
||
| 135 | # the code embedded in _version.py can just fetch the value of these |
||
| 136 | # keywords. When used from setup.py, we don't want to import _version.py, |
||
| 137 | # so we do it with a regexp instead. This function is not used from |
||
| 138 | # _version.py. |
||
| 139 | keywords = {} |
||
| 140 | try: |
||
| 141 | f = open(versionfile_abs, "r") |
||
| 142 | for line in f.readlines(): |
||
| 143 | if line.strip().startswith("git_refnames ="): |
||
| 144 | mo = re.search(r'=\s*"(.*)"', line) |
||
| 145 | if mo: |
||
| 146 | keywords["refnames"] = mo.group(1) |
||
| 147 | if line.strip().startswith("git_full ="): |
||
| 148 | mo = re.search(r'=\s*"(.*)"', line) |
||
| 149 | if mo: |
||
| 150 | keywords["full"] = mo.group(1) |
||
| 151 | if line.strip().startswith("git_date ="): |
||
| 152 | mo = re.search(r'=\s*"(.*)"', line) |
||
| 153 | if mo: |
||
| 154 | keywords["date"] = mo.group(1) |
||
| 155 | f.close() |
||
| 156 | except EnvironmentError: |
||
| 157 | pass |
||
| 158 | return keywords |
||
| 159 | |||
| 160 | |||
| 161 | View Code Duplication | @register_vcs_handler("git", "keywords") |
|
| 162 | def git_versions_from_keywords(keywords, tag_prefix, verbose): |
||
| 163 | """Get version information from git keywords.""" |
||
| 164 | if not keywords: |
||
| 165 | raise NotThisMethod("no keywords at all, weird") |
||
| 166 | date = keywords.get("date") |
||
| 167 | if date is not None: |
||
| 168 | # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant |
||
| 169 | # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 |
||
| 170 | # -like" string, which we must then edit to make compliant), because |
||
| 171 | # it's been around since git-1.5.3, and it's too difficult to |
||
| 172 | # discover which version we're using, or to work around using an |
||
| 173 | # older one. |
||
| 174 | date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) |
||
| 175 | refnames = keywords["refnames"].strip() |
||
| 176 | if refnames.startswith("$Format"): |
||
| 177 | if verbose: |
||
| 178 | print("keywords are unexpanded, not using") |
||
| 179 | raise NotThisMethod("unexpanded keywords, not a git-archive tarball") |
||
| 180 | refs = set([r.strip() for r in refnames.strip("()").split(",")]) |
||
| 181 | # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of |
||
| 182 | # just "foo-1.0". If we see a "tag: " prefix, prefer those. |
||
| 183 | TAG = "tag: " |
||
| 184 | tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) |
||
| 185 | if not tags: |
||
| 186 | # Either we're using git < 1.8.3, or there really are no tags. We use |
||
| 187 | # a heuristic: assume all version tags have a digit. The old git %d |
||
| 188 | # expansion behaves like git log --decorate=short and strips out the |
||
| 189 | # refs/heads/ and refs/tags/ prefixes that would let us distinguish |
||
| 190 | # between branches and tags. By ignoring refnames without digits, we |
||
| 191 | # filter out many common branch names like "release" and |
||
| 192 | # "stabilization", as well as "HEAD" and "master". |
||
| 193 | tags = set([r for r in refs if re.search(r'\d', r)]) |
||
| 194 | if verbose: |
||
| 195 | print("discarding '%s', no digits" % ",".join(refs - tags)) |
||
| 196 | if verbose: |
||
| 197 | print("likely tags: %s" % ",".join(sorted(tags))) |
||
| 198 | for ref in sorted(tags): |
||
| 199 | # sorting will prefer e.g. "2.0" over "2.0rc1" |
||
| 200 | if ref.startswith(tag_prefix): |
||
| 201 | r = ref[len(tag_prefix):] |
||
| 202 | if verbose: |
||
| 203 | print("picking %s" % r) |
||
| 204 | return {"version": r, |
||
| 205 | "full-revisionid": keywords["full"].strip(), |
||
| 206 | "dirty": False, "error": None, |
||
| 207 | "date": date} |
||
| 208 | # no suitable tags, so version is "0+unknown", but full hex is still there |
||
| 209 | if verbose: |
||
| 210 | print("no suitable tags, using unknown + full revision id") |
||
| 211 | return {"version": "0+unknown", |
||
| 212 | "full-revisionid": keywords["full"].strip(), |
||
| 213 | "dirty": False, "error": "no suitable tags", "date": None} |
||
| 214 | |||
| 215 | |||
| 216 | View Code Duplication | @register_vcs_handler("git", "pieces_from_vcs") |
|
| 217 | def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): |
||
| 218 | """Get version from 'git describe' in the root of the source tree. |
||
| 219 | |||
| 220 | This only gets called if the git-archive 'subst' keywords were *not* |
||
| 221 | expanded, and _version.py hasn't already been rewritten with a short |
||
| 222 | version string, meaning we're inside a checked out source tree. |
||
| 223 | """ |
||
| 224 | GITS = ["git"] |
||
| 225 | if sys.platform == "win32": |
||
| 226 | GITS = ["git.cmd", "git.exe"] |
||
| 227 | |||
| 228 | out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, |
||
| 229 | hide_stderr=True) |
||
| 230 | if rc != 0: |
||
| 231 | if verbose: |
||
| 232 | print("Directory %s not under git control" % root) |
||
| 233 | raise NotThisMethod("'git rev-parse --git-dir' returned error") |
||
| 234 | |||
| 235 | # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] |
||
| 236 | # if there isn't one, this yields HEX[-dirty] (no NUM) |
||
| 237 | describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", |
||
| 238 | "--always", "--long", |
||
| 239 | "--match", "%s*" % tag_prefix], |
||
| 240 | cwd=root) |
||
| 241 | # --long was added in git-1.5.5 |
||
| 242 | if describe_out is None: |
||
| 243 | raise NotThisMethod("'git describe' failed") |
||
| 244 | describe_out = describe_out.strip() |
||
| 245 | full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) |
||
| 246 | if full_out is None: |
||
| 247 | raise NotThisMethod("'git rev-parse' failed") |
||
| 248 | full_out = full_out.strip() |
||
| 249 | |||
| 250 | pieces = {} |
||
| 251 | pieces["long"] = full_out |
||
| 252 | pieces["short"] = full_out[:7] # maybe improved later |
||
| 253 | pieces["error"] = None |
||
| 254 | |||
| 255 | # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] |
||
| 256 | # TAG might have hyphens. |
||
| 257 | git_describe = describe_out |
||
| 258 | |||
| 259 | # look for -dirty suffix |
||
| 260 | dirty = git_describe.endswith("-dirty") |
||
| 261 | pieces["dirty"] = dirty |
||
| 262 | if dirty: |
||
| 263 | git_describe = git_describe[:git_describe.rindex("-dirty")] |
||
| 264 | |||
| 265 | # now we have TAG-NUM-gHEX or HEX |
||
| 266 | |||
| 267 | if "-" in git_describe: |
||
| 268 | # TAG-NUM-gHEX |
||
| 269 | mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) |
||
| 270 | if not mo: |
||
| 271 | # unparseable. Maybe git-describe is misbehaving? |
||
| 272 | pieces["error"] = ("unable to parse git-describe output: '%s'" |
||
| 273 | % describe_out) |
||
| 274 | return pieces |
||
| 275 | |||
| 276 | # tag |
||
| 277 | full_tag = mo.group(1) |
||
| 278 | if not full_tag.startswith(tag_prefix): |
||
| 279 | if verbose: |
||
| 280 | fmt = "tag '%s' doesn't start with prefix '%s'" |
||
| 281 | print(fmt % (full_tag, tag_prefix)) |
||
| 282 | pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" |
||
| 283 | % (full_tag, tag_prefix)) |
||
| 284 | return pieces |
||
| 285 | pieces["closest-tag"] = full_tag[len(tag_prefix):] |
||
| 286 | |||
| 287 | # distance: number of commits since tag |
||
| 288 | pieces["distance"] = int(mo.group(2)) |
||
| 289 | |||
| 290 | # commit: short hex revision ID |
||
| 291 | pieces["short"] = mo.group(3) |
||
| 292 | |||
| 293 | else: |
||
| 294 | # HEX: no tags |
||
| 295 | pieces["closest-tag"] = None |
||
| 296 | count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], |
||
| 297 | cwd=root) |
||
| 298 | pieces["distance"] = int(count_out) # total number of commits |
||
| 299 | |||
| 300 | # commit date: see ISO-8601 comment in git_versions_from_keywords() |
||
| 301 | date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], |
||
| 302 | cwd=root)[0].strip() |
||
| 303 | pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) |
||
| 304 | |||
| 305 | return pieces |
||
| 306 | |||
| 307 | |||
| 308 | def plus_or_dot(pieces): |
||
| 309 | """Return a + if we don't already have one, else return a .""" |
||
| 310 | if "+" in pieces.get("closest-tag", ""): |
||
| 311 | return "." |
||
| 312 | return "+" |
||
| 313 | |||
| 314 | |||
| 315 | View Code Duplication | def render_pep440(pieces): |
|
| 316 | """Build up version string, with post-release "local version identifier". |
||
| 317 | |||
| 318 | Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you |
||
| 319 | get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty |
||
| 320 | |||
| 321 | Exceptions: |
||
| 322 | 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] |
||
| 323 | """ |
||
| 324 | if pieces["closest-tag"]: |
||
| 325 | rendered = pieces["closest-tag"] |
||
| 326 | if pieces["distance"] or pieces["dirty"]: |
||
| 327 | rendered += plus_or_dot(pieces) |
||
| 328 | rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) |
||
| 329 | if pieces["dirty"]: |
||
| 330 | rendered += ".dirty" |
||
| 331 | else: |
||
| 332 | # exception #1 |
||
| 333 | rendered = "0+untagged.%d.g%s" % (pieces["distance"], |
||
| 334 | pieces["short"]) |
||
| 335 | if pieces["dirty"]: |
||
| 336 | rendered += ".dirty" |
||
| 337 | return rendered |
||
| 338 | |||
| 339 | |||
| 340 | View Code Duplication | def render_pep440_pre(pieces): |
|
| 341 | """TAG[.post.devDISTANCE] -- No -dirty. |
||
| 342 | |||
| 343 | Exceptions: |
||
| 344 | 1: no tags. 0.post.devDISTANCE |
||
| 345 | """ |
||
| 346 | if pieces["closest-tag"]: |
||
| 347 | rendered = pieces["closest-tag"] |
||
| 348 | if pieces["distance"]: |
||
| 349 | rendered += ".post.dev%d" % pieces["distance"] |
||
| 350 | else: |
||
| 351 | # exception #1 |
||
| 352 | rendered = "0.post.dev%d" % pieces["distance"] |
||
| 353 | return rendered |
||
| 354 | |||
| 355 | |||
| 356 | View Code Duplication | def render_pep440_post(pieces): |
|
| 357 | """TAG[.postDISTANCE[.dev0]+gHEX] . |
||
| 358 | |||
| 359 | The ".dev0" means dirty. Note that .dev0 sorts backwards |
||
| 360 | (a dirty tree will appear "older" than the corresponding clean one), |
||
| 361 | but you shouldn't be releasing software with -dirty anyways. |
||
| 362 | |||
| 363 | Exceptions: |
||
| 364 | 1: no tags. 0.postDISTANCE[.dev0] |
||
| 365 | """ |
||
| 366 | if pieces["closest-tag"]: |
||
| 367 | rendered = pieces["closest-tag"] |
||
| 368 | if pieces["distance"] or pieces["dirty"]: |
||
| 369 | rendered += ".post%d" % pieces["distance"] |
||
| 370 | if pieces["dirty"]: |
||
| 371 | rendered += ".dev0" |
||
| 372 | rendered += plus_or_dot(pieces) |
||
| 373 | rendered += "g%s" % pieces["short"] |
||
| 374 | else: |
||
| 375 | # exception #1 |
||
| 376 | rendered = "0.post%d" % pieces["distance"] |
||
| 377 | if pieces["dirty"]: |
||
| 378 | rendered += ".dev0" |
||
| 379 | rendered += "+g%s" % pieces["short"] |
||
| 380 | return rendered |
||
| 381 | |||
| 382 | |||
| 383 | View Code Duplication | def render_pep440_old(pieces): |
|
| 384 | """TAG[.postDISTANCE[.dev0]] . |
||
| 385 | |||
| 386 | The ".dev0" means dirty. |
||
| 387 | |||
| 388 | Eexceptions: |
||
| 389 | 1: no tags. 0.postDISTANCE[.dev0] |
||
| 390 | """ |
||
| 391 | if pieces["closest-tag"]: |
||
| 392 | rendered = pieces["closest-tag"] |
||
| 393 | if pieces["distance"] or pieces["dirty"]: |
||
| 394 | rendered += ".post%d" % pieces["distance"] |
||
| 395 | if pieces["dirty"]: |
||
| 396 | rendered += ".dev0" |
||
| 397 | else: |
||
| 398 | # exception #1 |
||
| 399 | rendered = "0.post%d" % pieces["distance"] |
||
| 400 | if pieces["dirty"]: |
||
| 401 | rendered += ".dev0" |
||
| 402 | return rendered |
||
| 403 | |||
| 404 | |||
| 405 | View Code Duplication | def render_git_describe(pieces): |
|
| 406 | """TAG[-DISTANCE-gHEX][-dirty]. |
||
| 407 | |||
| 408 | Like 'git describe --tags --dirty --always'. |
||
| 409 | |||
| 410 | Exceptions: |
||
| 411 | 1: no tags. HEX[-dirty] (note: no 'g' prefix) |
||
| 412 | """ |
||
| 413 | if pieces["closest-tag"]: |
||
| 414 | rendered = pieces["closest-tag"] |
||
| 415 | if pieces["distance"]: |
||
| 416 | rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) |
||
| 417 | else: |
||
| 418 | # exception #1 |
||
| 419 | rendered = pieces["short"] |
||
| 420 | if pieces["dirty"]: |
||
| 421 | rendered += "-dirty" |
||
| 422 | return rendered |
||
| 423 | |||
| 424 | |||
| 425 | View Code Duplication | def render_git_describe_long(pieces): |
|
| 426 | """TAG-DISTANCE-gHEX[-dirty]. |
||
| 427 | |||
| 428 | Like 'git describe --tags --dirty --always -long'. |
||
| 429 | The distance/hash is unconditional. |
||
| 430 | |||
| 431 | Exceptions: |
||
| 432 | 1: no tags. HEX[-dirty] (note: no 'g' prefix) |
||
| 433 | """ |
||
| 434 | if pieces["closest-tag"]: |
||
| 435 | rendered = pieces["closest-tag"] |
||
| 436 | rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) |
||
| 437 | else: |
||
| 438 | # exception #1 |
||
| 439 | rendered = pieces["short"] |
||
| 440 | if pieces["dirty"]: |
||
| 441 | rendered += "-dirty" |
||
| 442 | return rendered |
||
| 443 | |||
| 444 | |||
| 445 | View Code Duplication | def render(pieces, style): |
|
| 446 | """Render the given version pieces into the requested style.""" |
||
| 447 | if pieces["error"]: |
||
| 448 | return {"version": "unknown", |
||
| 449 | "full-revisionid": pieces.get("long"), |
||
| 450 | "dirty": None, |
||
| 451 | "error": pieces["error"], |
||
| 452 | "date": None} |
||
| 453 | |||
| 454 | if not style or style == "default": |
||
| 455 | style = "pep440" # the default |
||
| 456 | |||
| 457 | if style == "pep440": |
||
| 458 | rendered = render_pep440(pieces) |
||
| 459 | elif style == "pep440-pre": |
||
| 460 | rendered = render_pep440_pre(pieces) |
||
| 461 | elif style == "pep440-post": |
||
| 462 | rendered = render_pep440_post(pieces) |
||
| 463 | elif style == "pep440-old": |
||
| 464 | rendered = render_pep440_old(pieces) |
||
| 465 | elif style == "git-describe": |
||
| 466 | rendered = render_git_describe(pieces) |
||
| 467 | elif style == "git-describe-long": |
||
| 468 | rendered = render_git_describe_long(pieces) |
||
| 469 | else: |
||
| 470 | raise ValueError("unknown style '%s'" % style) |
||
| 471 | |||
| 472 | return {"version": rendered, "full-revisionid": pieces["long"], |
||
| 473 | "dirty": pieces["dirty"], "error": None, |
||
| 474 | "date": pieces.get("date")} |
||
| 475 | |||
| 476 | |||
| 477 | def get_versions(): |
||
| 478 | """Get version information or return default if unable to do so.""" |
||
| 479 | # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have |
||
| 480 | # __file__, we can work backwards from there to the root. Some |
||
| 481 | # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which |
||
| 482 | # case we can only use expanded keywords. |
||
| 483 | |||
| 484 | cfg = get_config() |
||
| 485 | verbose = cfg.verbose |
||
| 486 | |||
| 487 | try: |
||
| 488 | return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, |
||
| 489 | verbose) |
||
| 490 | except NotThisMethod: |
||
| 491 | pass |
||
| 492 | |||
| 493 | try: |
||
| 494 | root = os.path.realpath(__file__) |
||
| 495 | # versionfile_source is the relative path from the top of the source |
||
| 496 | # tree (where the .git directory might live) to this file. Invert |
||
| 497 | # this to find the root from __file__. |
||
| 498 | for i in cfg.versionfile_source.split('/'): |
||
| 499 | root = os.path.dirname(root) |
||
| 500 | except NameError: |
||
| 501 | return {"version": "0+unknown", "full-revisionid": None, |
||
| 502 | "dirty": None, |
||
| 503 | "error": "unable to find root of source tree", |
||
| 504 | "date": None} |
||
| 505 | |||
| 506 | try: |
||
| 507 | pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) |
||
| 508 | return render(pieces, cfg.style) |
||
| 509 | except NotThisMethod: |
||
| 510 | pass |
||
| 511 | |||
| 512 | try: |
||
| 513 | if cfg.parentdir_prefix: |
||
| 514 | return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) |
||
| 515 | except NotThisMethod: |
||
| 516 | pass |
||
| 517 | |||
| 518 | return {"version": "0+unknown", "full-revisionid": None, |
||
| 519 | "dirty": None, |
||
| 520 | "error": "unable to compute version", "date": None} |
||
| 521 |