versioneer.py 25 KB

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