1 | #! /usr/bin/python |
---|
2 | |
---|
3 | """versioneer.py |
---|
4 | |
---|
5 | (like a rocketeer, but for versions) |
---|
6 | |
---|
7 | * https://github.com/warner/python-versioneer |
---|
8 | * Brian Warner |
---|
9 | * License: Public Domain |
---|
10 | * Version: 0.7 |
---|
11 | |
---|
12 | This file helps distutils-based projects manage their version number by just |
---|
13 | creating version-control tags. |
---|
14 | |
---|
15 | For developers who work from a VCS-generated tree (e.g. 'git clone' etc), |
---|
16 | each 'setup.py version', 'setup.py build', 'setup.py sdist' will compute a |
---|
17 | version number by asking your version-control tool about the current |
---|
18 | checkout. The version number will be written into a generated _version.py |
---|
19 | file of your choosing, where it can be included by your __init__.py |
---|
20 | |
---|
21 | For users who work from a VCS-generated tarball (e.g. 'git archive'), it will |
---|
22 | compute a version number by looking at the name of the directory created when |
---|
23 | te tarball is unpacked. This conventionally includes both the name of the |
---|
24 | project and a version number. |
---|
25 | |
---|
26 | For users who work from a tarball built by 'setup.py sdist', it will get a |
---|
27 | version number from a previously-generated _version.py file. |
---|
28 | |
---|
29 | As a result, loading code directly from the source tree will not result in a |
---|
30 | real version. If you want real versions from VCS trees (where you frequently |
---|
31 | update from the upstream repository, or do new development), you will need to |
---|
32 | do a 'setup.py version' after each update, and load code from the build/ |
---|
33 | directory. |
---|
34 | |
---|
35 | You need to provide this code with a few configuration values: |
---|
36 | |
---|
37 | versionfile_source: |
---|
38 | A project-relative pathname into which the generated version strings |
---|
39 | should be written. This is usually a _version.py next to your project's |
---|
40 | main __init__.py file. If your project uses src/myproject/__init__.py, |
---|
41 | this should be 'src/myproject/_version.py'. This file should be checked |
---|
42 | in to your VCS as usual: the copy created below by 'setup.py |
---|
43 | update_files' will include code that parses expanded VCS keywords in |
---|
44 | generated tarballs. The 'build' and 'sdist' commands will replace it with |
---|
45 | a copy that has just the calculated version string. |
---|
46 | |
---|
47 | versionfile_build: |
---|
48 | Like versionfile_source, but relative to the build directory instead of |
---|
49 | the source directory. These will differ when your setup.py uses |
---|
50 | 'package_dir='. If you have package_dir={'myproject': 'src/myproject'}, |
---|
51 | then you will probably have versionfile_build='myproject/_version.py' and |
---|
52 | versionfile_source='src/myproject/_version.py'. |
---|
53 | |
---|
54 | tag_prefix: a string, like 'PROJECTNAME-', which appears at the start of all |
---|
55 | VCS tags. If your tags look like 'myproject-1.2.0', then you |
---|
56 | should use tag_prefix='myproject-'. If you use unprefixed tags |
---|
57 | like '1.2.0', this should be an empty string. |
---|
58 | |
---|
59 | parentdir_prefix: a string, frequently the same as tag_prefix, which |
---|
60 | appears at the start of all unpacked tarball filenames. If |
---|
61 | your tarball unpacks into 'myproject-1.2.0', this should |
---|
62 | be 'myproject-'. |
---|
63 | |
---|
64 | To use it: |
---|
65 | |
---|
66 | 1: include this file in the top level of your project |
---|
67 | 2: make the following changes to the top of your setup.py: |
---|
68 | import versioneer |
---|
69 | versioneer.versionfile_source = 'src/myproject/_version.py' |
---|
70 | versioneer.versionfile_build = 'myproject/_version.py' |
---|
71 | versioneer.tag_prefix = '' # tags are like 1.2.0 |
---|
72 | versioneer.parentdir_prefix = 'myproject-' # dirname like 'myproject-1.2.0' |
---|
73 | 3: add the following arguments to the setup() call in your setup.py: |
---|
74 | version=versioneer.get_version(), |
---|
75 | cmdclass=versioneer.get_cmdclass(), |
---|
76 | 4: run 'setup.py update_files', which will create _version.py, and will |
---|
77 | append the following to your __init__.py: |
---|
78 | from _version import __version__ |
---|
79 | 5: modify your MANIFEST.in to include versioneer.py |
---|
80 | 6: add both versioneer.py and the generated _version.py to your VCS |
---|
81 | """ |
---|
82 | |
---|
83 | import os, sys, re |
---|
84 | from distutils.core import Command |
---|
85 | from distutils.command.sdist import sdist as _sdist |
---|
86 | from distutils.command.build import build as _build |
---|
87 | |
---|
88 | versionfile_source = None |
---|
89 | versionfile_build = None |
---|
90 | tag_prefix = None |
---|
91 | parentdir_prefix = None |
---|
92 | |
---|
93 | VCS = "git" |
---|
94 | IN_LONG_VERSION_PY = False |
---|
95 | |
---|
96 | |
---|
97 | LONG_VERSION_PY = ''' |
---|
98 | IN_LONG_VERSION_PY = True |
---|
99 | # This file helps to compute a version number in source trees obtained from |
---|
100 | # git-archive tarball (such as those provided by githubs download-from-tag |
---|
101 | # feature). Distribution tarballs (build by setup.py sdist) and build |
---|
102 | # directories (produced by setup.py build) will contain a much shorter file |
---|
103 | # that just contains the computed version number. |
---|
104 | |
---|
105 | # This file is released into the public domain. Generated by |
---|
106 | # versioneer-0.7 (https://github.com/warner/python-versioneer) |
---|
107 | |
---|
108 | # these strings will be replaced by git during git-archive |
---|
109 | git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" |
---|
110 | git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" |
---|
111 | |
---|
112 | |
---|
113 | import subprocess |
---|
114 | |
---|
115 | def run_command(args, cwd=None, verbose=False): |
---|
116 | try: |
---|
117 | # remember shell=False, so use git.cmd on windows, not just git |
---|
118 | p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) |
---|
119 | except EnvironmentError, e: |
---|
120 | if verbose: |
---|
121 | print "unable to run %%s" %% args[0] |
---|
122 | print e |
---|
123 | return None |
---|
124 | stdout = p.communicate()[0].strip() |
---|
125 | if p.returncode != 0: |
---|
126 | if verbose: |
---|
127 | print "unable to run %%s (error)" %% args[0] |
---|
128 | return None |
---|
129 | return stdout |
---|
130 | |
---|
131 | |
---|
132 | import sys |
---|
133 | import re |
---|
134 | import os.path |
---|
135 | |
---|
136 | def get_expanded_variables(versionfile_source): |
---|
137 | # the code embedded in _version.py can just fetch the value of these |
---|
138 | # variables. When used from setup.py, we don't want to import |
---|
139 | # _version.py, so we do it with a regexp instead. This function is not |
---|
140 | # used from _version.py. |
---|
141 | variables = {} |
---|
142 | try: |
---|
143 | for line in open(versionfile_source,"r").readlines(): |
---|
144 | if line.strip().startswith("git_refnames ="): |
---|
145 | mo = re.search(r'=\s*"(.*)"', line) |
---|
146 | if mo: |
---|
147 | variables["refnames"] = mo.group(1) |
---|
148 | if line.strip().startswith("git_full ="): |
---|
149 | mo = re.search(r'=\s*"(.*)"', line) |
---|
150 | if mo: |
---|
151 | variables["full"] = mo.group(1) |
---|
152 | except EnvironmentError: |
---|
153 | pass |
---|
154 | return variables |
---|
155 | |
---|
156 | def versions_from_expanded_variables(variables, tag_prefix, verbose=False): |
---|
157 | refnames = variables["refnames"].strip() |
---|
158 | if refnames.startswith("$Format"): |
---|
159 | if verbose: |
---|
160 | print "variables are unexpanded, not using" |
---|
161 | return {} # unexpanded, so not in an unpacked git-archive tarball |
---|
162 | refs = set([r.strip() for r in refnames.strip("()").split(",")]) |
---|
163 | for ref in list(refs): |
---|
164 | if not re.search(r'\d', ref): |
---|
165 | if verbose: |
---|
166 | print "discarding '%%s', no digits" %% ref |
---|
167 | refs.discard(ref) |
---|
168 | # Assume all version tags have a digit. git's %%d expansion |
---|
169 | # behaves like git log --decorate=short and strips out the |
---|
170 | # refs/heads/ and refs/tags/ prefixes that would let us |
---|
171 | # distinguish between branches and tags. By ignoring refnames |
---|
172 | # without digits, we filter out many common branch names like |
---|
173 | # "release" and "stabilization", as well as "HEAD" and "master". |
---|
174 | if verbose: |
---|
175 | print "remaining refs:", ",".join(sorted(refs)) |
---|
176 | for ref in sorted(refs): |
---|
177 | # sorting will prefer e.g. "2.0" over "2.0rc1" |
---|
178 | if ref.startswith(tag_prefix): |
---|
179 | r = ref[len(tag_prefix):] |
---|
180 | if verbose: |
---|
181 | print "picking %%s" %% r |
---|
182 | return { "version": r, |
---|
183 | "full": variables["full"].strip() } |
---|
184 | # no suitable tags, so we use the full revision id |
---|
185 | if verbose: |
---|
186 | print "no suitable tags, using full revision id" |
---|
187 | return { "version": variables["full"].strip(), |
---|
188 | "full": variables["full"].strip() } |
---|
189 | |
---|
190 | def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): |
---|
191 | # this runs 'git' from the root of the source tree. That either means |
---|
192 | # someone ran a setup.py command (and this code is in versioneer.py, so |
---|
193 | # IN_LONG_VERSION_PY=False, thus the containing directory is the root of |
---|
194 | # the source tree), or someone ran a project-specific entry point (and |
---|
195 | # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the |
---|
196 | # containing directory is somewhere deeper in the source tree). This only |
---|
197 | # gets called if the git-archive 'subst' variables were *not* expanded, |
---|
198 | # and _version.py hasn't already been rewritten with a short version |
---|
199 | # string, meaning we're inside a checked out source tree. |
---|
200 | |
---|
201 | try: |
---|
202 | here = os.path.abspath(__file__) |
---|
203 | except NameError: |
---|
204 | # some py2exe/bbfreeze/non-CPython implementations don't do __file__ |
---|
205 | return {} # not always correct |
---|
206 | |
---|
207 | # versionfile_source is the relative path from the top of the source tree |
---|
208 | # (where the .git directory might live) to this file. Invert this to find |
---|
209 | # the root from __file__. |
---|
210 | root = here |
---|
211 | if IN_LONG_VERSION_PY: |
---|
212 | for i in range(len(versionfile_source.split("/"))): |
---|
213 | root = os.path.dirname(root) |
---|
214 | else: |
---|
215 | root = os.path.dirname(here) |
---|
216 | if not os.path.exists(os.path.join(root, ".git")): |
---|
217 | if verbose: |
---|
218 | print "no .git in", root |
---|
219 | return {} |
---|
220 | |
---|
221 | GIT = "git" |
---|
222 | if sys.platform == "win32": |
---|
223 | GIT = "git.cmd" |
---|
224 | stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], |
---|
225 | cwd=root) |
---|
226 | if stdout is None: |
---|
227 | return {} |
---|
228 | if not stdout.startswith(tag_prefix): |
---|
229 | if verbose: |
---|
230 | print "tag '%%s' doesn't start with prefix '%%s'" %% (stdout, tag_prefix) |
---|
231 | return {} |
---|
232 | tag = stdout[len(tag_prefix):] |
---|
233 | stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) |
---|
234 | if stdout is None: |
---|
235 | return {} |
---|
236 | full = stdout.strip() |
---|
237 | if tag.endswith("-dirty"): |
---|
238 | full += "-dirty" |
---|
239 | return {"version": tag, "full": full} |
---|
240 | |
---|
241 | |
---|
242 | def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): |
---|
243 | if IN_LONG_VERSION_PY: |
---|
244 | # We're running from _version.py. If it's from a source tree |
---|
245 | # (execute-in-place), we can work upwards to find the root of the |
---|
246 | # tree, and then check the parent directory for a version string. If |
---|
247 | # it's in an installed application, there's no hope. |
---|
248 | try: |
---|
249 | here = os.path.abspath(__file__) |
---|
250 | except NameError: |
---|
251 | # py2exe/bbfreeze/non-CPython don't have __file__ |
---|
252 | return {} # without __file__, we have no hope |
---|
253 | # versionfile_source is the relative path from the top of the source |
---|
254 | # tree to _version.py. Invert this to find the root from __file__. |
---|
255 | root = here |
---|
256 | for i in range(len(versionfile_source.split("/"))): |
---|
257 | root = os.path.dirname(root) |
---|
258 | else: |
---|
259 | # we're running from versioneer.py, which means we're running from |
---|
260 | # the setup.py in a source tree. sys.argv[0] is setup.py in the root. |
---|
261 | here = os.path.abspath(sys.argv[0]) |
---|
262 | root = os.path.dirname(here) |
---|
263 | |
---|
264 | # Source tarballs conventionally unpack into a directory that includes |
---|
265 | # both the project name and a version string. |
---|
266 | dirname = os.path.basename(root) |
---|
267 | if not dirname.startswith(parentdir_prefix): |
---|
268 | if verbose: |
---|
269 | print "guessing rootdir is '%%s', but '%%s' doesn't start with prefix '%%s'" %% \ |
---|
270 | (root, dirname, parentdir_prefix) |
---|
271 | return None |
---|
272 | return {"version": dirname[len(parentdir_prefix):], "full": ""} |
---|
273 | |
---|
274 | tag_prefix = "%(TAG_PREFIX)s" |
---|
275 | parentdir_prefix = "%(PARENTDIR_PREFIX)s" |
---|
276 | versionfile_source = "%(VERSIONFILE_SOURCE)s" |
---|
277 | |
---|
278 | def get_versions(default={"version": "unknown", "full": ""}, verbose=False): |
---|
279 | variables = { "refnames": git_refnames, "full": git_full } |
---|
280 | ver = versions_from_expanded_variables(variables, tag_prefix, verbose) |
---|
281 | if not ver: |
---|
282 | ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) |
---|
283 | if not ver: |
---|
284 | ver = versions_from_parentdir(parentdir_prefix, versionfile_source, |
---|
285 | verbose) |
---|
286 | if not ver: |
---|
287 | ver = default |
---|
288 | return ver |
---|
289 | |
---|
290 | ''' |
---|
291 | |
---|
292 | |
---|
293 | import subprocess |
---|
294 | |
---|
295 | def run_command(args, cwd=None, verbose=False): |
---|
296 | try: |
---|
297 | # remember shell=False, so use git.cmd on windows, not just git |
---|
298 | p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) |
---|
299 | except EnvironmentError, e: |
---|
300 | if verbose: |
---|
301 | print "unable to run %s" % args[0] |
---|
302 | print e |
---|
303 | return None |
---|
304 | stdout = p.communicate()[0].strip() |
---|
305 | if p.returncode != 0: |
---|
306 | if verbose: |
---|
307 | print "unable to run %s (error)" % args[0] |
---|
308 | return None |
---|
309 | return stdout |
---|
310 | |
---|
311 | |
---|
312 | import sys |
---|
313 | import re |
---|
314 | import os.path |
---|
315 | |
---|
316 | def get_expanded_variables(versionfile_source): |
---|
317 | # the code embedded in _version.py can just fetch the value of these |
---|
318 | # variables. When used from setup.py, we don't want to import |
---|
319 | # _version.py, so we do it with a regexp instead. This function is not |
---|
320 | # used from _version.py. |
---|
321 | variables = {} |
---|
322 | try: |
---|
323 | for line in open(versionfile_source,"r").readlines(): |
---|
324 | if line.strip().startswith("git_refnames ="): |
---|
325 | mo = re.search(r'=\s*"(.*)"', line) |
---|
326 | if mo: |
---|
327 | variables["refnames"] = mo.group(1) |
---|
328 | if line.strip().startswith("git_full ="): |
---|
329 | mo = re.search(r'=\s*"(.*)"', line) |
---|
330 | if mo: |
---|
331 | variables["full"] = mo.group(1) |
---|
332 | except EnvironmentError: |
---|
333 | pass |
---|
334 | return variables |
---|
335 | |
---|
336 | def versions_from_expanded_variables(variables, tag_prefix, verbose=False): |
---|
337 | refnames = variables["refnames"].strip() |
---|
338 | if refnames.startswith("$Format"): |
---|
339 | if verbose: |
---|
340 | print "variables are unexpanded, not using" |
---|
341 | return {} # unexpanded, so not in an unpacked git-archive tarball |
---|
342 | refs = set([r.strip() for r in refnames.strip("()").split(",")]) |
---|
343 | for ref in list(refs): |
---|
344 | if not re.search(r'\d', ref): |
---|
345 | if verbose: |
---|
346 | print "discarding '%s', no digits" % ref |
---|
347 | refs.discard(ref) |
---|
348 | # Assume all version tags have a digit. git's %d expansion |
---|
349 | # behaves like git log --decorate=short and strips out the |
---|
350 | # refs/heads/ and refs/tags/ prefixes that would let us |
---|
351 | # distinguish between branches and tags. By ignoring refnames |
---|
352 | # without digits, we filter out many common branch names like |
---|
353 | # "release" and "stabilization", as well as "HEAD" and "master". |
---|
354 | if verbose: |
---|
355 | print "remaining refs:", ",".join(sorted(refs)) |
---|
356 | for ref in sorted(refs): |
---|
357 | # sorting will prefer e.g. "2.0" over "2.0rc1" |
---|
358 | if ref.startswith(tag_prefix): |
---|
359 | r = ref[len(tag_prefix):] |
---|
360 | if verbose: |
---|
361 | print "picking %s" % r |
---|
362 | return { "version": r, |
---|
363 | "full": variables["full"].strip() } |
---|
364 | # no suitable tags, so we use the full revision id |
---|
365 | if verbose: |
---|
366 | print "no suitable tags, using full revision id" |
---|
367 | return { "version": variables["full"].strip(), |
---|
368 | "full": variables["full"].strip() } |
---|
369 | |
---|
370 | def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): |
---|
371 | # this runs 'git' from the root of the source tree. That either means |
---|
372 | # someone ran a setup.py command (and this code is in versioneer.py, so |
---|
373 | # IN_LONG_VERSION_PY=False, thus the containing directory is the root of |
---|
374 | # the source tree), or someone ran a project-specific entry point (and |
---|
375 | # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the |
---|
376 | # containing directory is somewhere deeper in the source tree). This only |
---|
377 | # gets called if the git-archive 'subst' variables were *not* expanded, |
---|
378 | # and _version.py hasn't already been rewritten with a short version |
---|
379 | # string, meaning we're inside a checked out source tree. |
---|
380 | |
---|
381 | try: |
---|
382 | here = os.path.abspath(__file__) |
---|
383 | except NameError: |
---|
384 | # some py2exe/bbfreeze/non-CPython implementations don't do __file__ |
---|
385 | return {} # not always correct |
---|
386 | |
---|
387 | # versionfile_source is the relative path from the top of the source tree |
---|
388 | # (where the .git directory might live) to this file. Invert this to find |
---|
389 | # the root from __file__. |
---|
390 | root = here |
---|
391 | if IN_LONG_VERSION_PY: |
---|
392 | for i in range(len(versionfile_source.split("/"))): |
---|
393 | root = os.path.dirname(root) |
---|
394 | else: |
---|
395 | root = os.path.dirname(here) |
---|
396 | if not os.path.exists(os.path.join(root, ".git")): |
---|
397 | if verbose: |
---|
398 | print "no .git in", root |
---|
399 | return {} |
---|
400 | |
---|
401 | GIT = "git" |
---|
402 | if sys.platform == "win32": |
---|
403 | GIT = "git.cmd" |
---|
404 | stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], |
---|
405 | cwd=root) |
---|
406 | if stdout is None: |
---|
407 | return {} |
---|
408 | if not stdout.startswith(tag_prefix): |
---|
409 | if verbose: |
---|
410 | print "tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix) |
---|
411 | return {} |
---|
412 | tag = stdout[len(tag_prefix):] |
---|
413 | stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) |
---|
414 | if stdout is None: |
---|
415 | return {} |
---|
416 | full = stdout.strip() |
---|
417 | if tag.endswith("-dirty"): |
---|
418 | full += "-dirty" |
---|
419 | return {"version": tag, "full": full} |
---|
420 | |
---|
421 | |
---|
422 | def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): |
---|
423 | if IN_LONG_VERSION_PY: |
---|
424 | # We're running from _version.py. If it's from a source tree |
---|
425 | # (execute-in-place), we can work upwards to find the root of the |
---|
426 | # tree, and then check the parent directory for a version string. If |
---|
427 | # it's in an installed application, there's no hope. |
---|
428 | try: |
---|
429 | here = os.path.abspath(__file__) |
---|
430 | except NameError: |
---|
431 | # py2exe/bbfreeze/non-CPython don't have __file__ |
---|
432 | return {} # without __file__, we have no hope |
---|
433 | # versionfile_source is the relative path from the top of the source |
---|
434 | # tree to _version.py. Invert this to find the root from __file__. |
---|
435 | root = here |
---|
436 | for i in range(len(versionfile_source.split("/"))): |
---|
437 | root = os.path.dirname(root) |
---|
438 | else: |
---|
439 | # we're running from versioneer.py, which means we're running from |
---|
440 | # the setup.py in a source tree. sys.argv[0] is setup.py in the root. |
---|
441 | here = os.path.abspath(sys.argv[0]) |
---|
442 | root = os.path.dirname(here) |
---|
443 | |
---|
444 | # Source tarballs conventionally unpack into a directory that includes |
---|
445 | # both the project name and a version string. |
---|
446 | dirname = os.path.basename(root) |
---|
447 | if not dirname.startswith(parentdir_prefix): |
---|
448 | if verbose: |
---|
449 | print "guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % \ |
---|
450 | (root, dirname, parentdir_prefix) |
---|
451 | return None |
---|
452 | return {"version": dirname[len(parentdir_prefix):], "full": ""} |
---|
453 | |
---|
454 | import sys |
---|
455 | |
---|
456 | def do_vcs_install(versionfile_source, ipy): |
---|
457 | GIT = "git" |
---|
458 | if sys.platform == "win32": |
---|
459 | GIT = "git.cmd" |
---|
460 | run_command([GIT, "add", "versioneer.py"]) |
---|
461 | run_command([GIT, "add", versionfile_source]) |
---|
462 | run_command([GIT, "add", ipy]) |
---|
463 | present = False |
---|
464 | try: |
---|
465 | f = open(".gitattributes", "r") |
---|
466 | for line in f.readlines(): |
---|
467 | if line.strip().startswith(versionfile_source): |
---|
468 | if "export-subst" in line.strip().split()[1:]: |
---|
469 | present = True |
---|
470 | f.close() |
---|
471 | except EnvironmentError: |
---|
472 | pass |
---|
473 | if not present: |
---|
474 | f = open(".gitattributes", "a+") |
---|
475 | f.write("%s export-subst\n" % versionfile_source) |
---|
476 | f.close() |
---|
477 | run_command([GIT, "add", ".gitattributes"]) |
---|
478 | |
---|
479 | |
---|
480 | SHORT_VERSION_PY = """ |
---|
481 | # This file was generated by 'versioneer.py' (0.7) from |
---|
482 | # revision-control system data, or from the parent directory name of an |
---|
483 | # unpacked source archive. Distribution tarballs contain a pre-generated copy |
---|
484 | # of this file. |
---|
485 | |
---|
486 | version_version = '%(version)s' |
---|
487 | version_full = '%(full)s' |
---|
488 | def get_versions(default={}, verbose=False): |
---|
489 | return {'version': version_version, 'full': version_full} |
---|
490 | |
---|
491 | """ |
---|
492 | |
---|
493 | DEFAULT = {"version": "unknown", "full": "unknown"} |
---|
494 | |
---|
495 | def versions_from_file(filename): |
---|
496 | versions = {} |
---|
497 | try: |
---|
498 | f = open(filename) |
---|
499 | except EnvironmentError: |
---|
500 | return versions |
---|
501 | for line in f.readlines(): |
---|
502 | mo = re.match("version_version = '([^']+)'", line) |
---|
503 | if mo: |
---|
504 | versions["version"] = mo.group(1) |
---|
505 | mo = re.match("version_full = '([^']+)'", line) |
---|
506 | if mo: |
---|
507 | versions["full"] = mo.group(1) |
---|
508 | return versions |
---|
509 | |
---|
510 | def write_to_version_file(filename, versions): |
---|
511 | f = open(filename, "w") |
---|
512 | f.write(SHORT_VERSION_PY % versions) |
---|
513 | f.close() |
---|
514 | print "set %s to '%s'" % (filename, versions["version"]) |
---|
515 | |
---|
516 | |
---|
517 | def get_best_versions(versionfile, tag_prefix, parentdir_prefix, |
---|
518 | default=DEFAULT, verbose=False): |
---|
519 | # returns dict with two keys: 'version' and 'full' |
---|
520 | # |
---|
521 | # extract version from first of _version.py, 'git describe', parentdir. |
---|
522 | # This is meant to work for developers using a source checkout, for users |
---|
523 | # of a tarball created by 'setup.py sdist', and for users of a |
---|
524 | # tarball/zipball created by 'git archive' or github's download-from-tag |
---|
525 | # feature. |
---|
526 | |
---|
527 | variables = get_expanded_variables(versionfile_source) |
---|
528 | if variables: |
---|
529 | ver = versions_from_expanded_variables(variables, tag_prefix) |
---|
530 | if ver: |
---|
531 | if verbose: print "got version from expanded variable", ver |
---|
532 | return ver |
---|
533 | |
---|
534 | ver = versions_from_file(versionfile) |
---|
535 | if ver: |
---|
536 | if verbose: print "got version from file %s" % versionfile, ver |
---|
537 | return ver |
---|
538 | |
---|
539 | ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) |
---|
540 | if ver: |
---|
541 | if verbose: print "got version from git", ver |
---|
542 | return ver |
---|
543 | |
---|
544 | ver = versions_from_parentdir(parentdir_prefix, versionfile_source, verbose) |
---|
545 | if ver: |
---|
546 | if verbose: print "got version from parentdir", ver |
---|
547 | return ver |
---|
548 | |
---|
549 | if verbose: print "got version from default", ver |
---|
550 | return default |
---|
551 | |
---|
552 | def get_versions(default=DEFAULT, verbose=False): |
---|
553 | assert versionfile_source is not None, "please set versioneer.versionfile_source" |
---|
554 | assert tag_prefix is not None, "please set versioneer.tag_prefix" |
---|
555 | assert parentdir_prefix is not None, "please set versioneer.parentdir_prefix" |
---|
556 | return get_best_versions(versionfile_source, tag_prefix, parentdir_prefix, |
---|
557 | default=default, verbose=verbose) |
---|
558 | def get_version(verbose=False): |
---|
559 | return get_versions(verbose=verbose)["version"] |
---|
560 | |
---|
561 | class cmd_version(Command): |
---|
562 | description = "report generated version string" |
---|
563 | user_options = [] |
---|
564 | boolean_options = [] |
---|
565 | def initialize_options(self): |
---|
566 | pass |
---|
567 | def finalize_options(self): |
---|
568 | pass |
---|
569 | def run(self): |
---|
570 | ver = get_version(verbose=True) |
---|
571 | print "Version is currently:", ver |
---|
572 | |
---|
573 | |
---|
574 | class cmd_build(_build): |
---|
575 | def run(self): |
---|
576 | versions = get_versions(verbose=True) |
---|
577 | _build.run(self) |
---|
578 | # now locate _version.py in the new build/ directory and replace it |
---|
579 | # with an updated value |
---|
580 | target_versionfile = os.path.join(self.build_lib, versionfile_build) |
---|
581 | print "UPDATING", target_versionfile |
---|
582 | os.unlink(target_versionfile) |
---|
583 | f = open(target_versionfile, "w") |
---|
584 | f.write(SHORT_VERSION_PY % versions) |
---|
585 | f.close() |
---|
586 | |
---|
587 | class cmd_sdist(_sdist): |
---|
588 | def run(self): |
---|
589 | versions = get_versions(verbose=True) |
---|
590 | self._versioneer_generated_versions = versions |
---|
591 | # unless we update this, the command will keep using the old version |
---|
592 | self.distribution.metadata.version = versions["version"] |
---|
593 | return _sdist.run(self) |
---|
594 | |
---|
595 | def make_release_tree(self, base_dir, files): |
---|
596 | _sdist.make_release_tree(self, base_dir, files) |
---|
597 | # now locate _version.py in the new base_dir directory (remembering |
---|
598 | # that it may be a hardlink) and replace it with an updated value |
---|
599 | target_versionfile = os.path.join(base_dir, versionfile_source) |
---|
600 | print "UPDATING", target_versionfile |
---|
601 | os.unlink(target_versionfile) |
---|
602 | f = open(target_versionfile, "w") |
---|
603 | f.write(SHORT_VERSION_PY % self._versioneer_generated_versions) |
---|
604 | f.close() |
---|
605 | |
---|
606 | INIT_PY_SNIPPET = """ |
---|
607 | from ._version import get_versions |
---|
608 | __version__ = get_versions()['version'] |
---|
609 | del get_versions |
---|
610 | """ |
---|
611 | |
---|
612 | class cmd_update_files(Command): |
---|
613 | description = "modify __init__.py and create _version.py" |
---|
614 | user_options = [] |
---|
615 | boolean_options = [] |
---|
616 | def initialize_options(self): |
---|
617 | pass |
---|
618 | def finalize_options(self): |
---|
619 | pass |
---|
620 | def run(self): |
---|
621 | ipy = os.path.join(os.path.dirname(versionfile_source), "__init__.py") |
---|
622 | print " creating %s" % versionfile_source |
---|
623 | f = open(versionfile_source, "w") |
---|
624 | f.write(LONG_VERSION_PY % {"DOLLAR": "$", |
---|
625 | "TAG_PREFIX": tag_prefix, |
---|
626 | "PARENTDIR_PREFIX": parentdir_prefix, |
---|
627 | "VERSIONFILE_SOURCE": versionfile_source, |
---|
628 | }) |
---|
629 | f.close() |
---|
630 | try: |
---|
631 | old = open(ipy, "r").read() |
---|
632 | except EnvironmentError: |
---|
633 | old = "" |
---|
634 | if INIT_PY_SNIPPET not in old: |
---|
635 | print " appending to %s" % ipy |
---|
636 | f = open(ipy, "a") |
---|
637 | f.write(INIT_PY_SNIPPET) |
---|
638 | f.close() |
---|
639 | else: |
---|
640 | print " %s unmodified" % ipy |
---|
641 | do_vcs_install(versionfile_source, ipy) |
---|
642 | |
---|
643 | def get_cmdclass(): |
---|
644 | return {'version': cmd_version, |
---|
645 | 'update_files': cmd_update_files, |
---|
646 | 'build': cmd_build, |
---|
647 | 'sdist': cmd_sdist, |
---|
648 | } |
---|