Fanwang Meng commited on
Commit
3de13eb
·
1 Parent(s): 4bbf21d

Remove versioneer.py

Browse files
Files changed (1) hide show
  1. versioneer.py +0 -1882
versioneer.py DELETED
@@ -1,1882 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # The Selector library provides a set of tools for selecting a
3
- # subset of the dataset and computing diversity.
4
- #
5
- # Copyright (C) 2023 The QC-Devs Community
6
- #
7
- # This file is part of Selector.
8
- #
9
- # Selector is free software; you can redistribute it and/or
10
- # modify it under the terms of the GNU General Public License
11
- # as published by the Free Software Foundation; either version 3
12
- # of the License, or (at your option) any later version.
13
- #
14
- # Selector is distributed in the hope that it will be useful,
15
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
- # GNU General Public License for more details.
18
- #
19
- # You should have received a copy of the GNU General Public License
20
- # along with this program; if not, see <http://www.gnu.org/licenses/>
21
- #
22
- # --
23
-
24
- # Version: 0.18
25
-
26
- """The Versioneer - like a rocketeer, but for versions.
27
-
28
- The Versioneer
29
- ==============
30
-
31
- * like a rocketeer, but for versions!
32
- * https://github.com/warner/python-versioneer
33
- * Brian Warner
34
- * License: Public Domain
35
- * Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy
36
- * [![Latest Version]
37
- (https://pypip.in/version/versioneer/badge.svg?style=flat)
38
- ](https://pypi.python.org/pypi/versioneer/)
39
- * [![Build Status]
40
- (https://travis-ci.org/warner/python-versioneer.png?branch=master)
41
- ](https://travis-ci.org/warner/python-versioneer)
42
-
43
- This is a tool for managing a recorded version number in distutils-based
44
- python projects. The goal is to remove the tedious and error-prone "update
45
- the embedded version string" step from your release process. Making a new
46
- release should be as easy as recording a new tag in your version-control
47
- system, and maybe making new tarballs.
48
-
49
-
50
- ## Quick Install
51
-
52
- * `pip install versioneer` to somewhere to your $PATH
53
- * add a `[versioneer]` section to your setup.cfg (see below)
54
- * run `versioneer install` in your source tree, commit the results
55
-
56
- ## Version Identifiers
57
-
58
- Source trees come from a variety of places:
59
-
60
- * a version-control system checkout (mostly used by developers)
61
- * a nightly tarball, produced by build automation
62
- * a snapshot tarball, produced by a web-based VCS browser, like github's
63
- "tarball from tag" feature
64
- * a release tarball, produced by "setup.py sdist", distributed through PyPI
65
-
66
- Within each source tree, the version identifier (either a string or a number,
67
- this tool is format-agnostic) can come from a variety of places:
68
-
69
- * ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows
70
- about recent "tags" and an absolute revision-id
71
- * the name of the directory into which the tarball was unpacked
72
- * an expanded VCS keyword ($Id$, etc)
73
- * a `_version.py` created by some earlier build step
74
-
75
- For released software, the version identifier is closely related to a VCS
76
- tag. Some projects use tag names that include more than just the version
77
- string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool
78
- needs to strip the tag prefix to extract the version identifier. For
79
- unreleased software (between tags), the version identifier should provide
80
- enough information to help developers recreate the same tree, while also
81
- giving them an idea of roughly how old the tree is (after version 1.2, before
82
- version 1.3). Many VCS systems can report a description that captures this,
83
- for example `git describe --tags --dirty --always` reports things like
84
- "0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the
85
- 0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has
86
- uncommitted changes.
87
-
88
- The version identifier is used for multiple purposes:
89
-
90
- * to allow the module to self-identify its version: `myproject.__version__`
91
- * to choose a name and prefix for a 'setup.py sdist' tarball
92
-
93
- ## Theory of Operation
94
-
95
- Versioneer works by adding a special `_version.py` file into your source
96
- tree, where your `__init__.py` can import it. This `_version.py` knows how to
97
- dynamically ask the VCS tool for version information at import time.
98
-
99
- `_version.py` also contains `$Revision$` markers, and the installation
100
- process marks `_version.py` to have this marker rewritten with a tag name
101
- during the `git archive` command. As a result, generated tarballs will
102
- contain enough information to get the proper version.
103
-
104
- To allow `setup.py` to compute a version too, a `versioneer.py` is added to
105
- the top level of your source tree, next to `setup.py` and the `setup.cfg`
106
- that configures it. This overrides several distutils/setuptools commands to
107
- compute the version when invoked, and changes `setup.py build` and `setup.py
108
- sdist` to replace `_version.py` with a small static file that contains just
109
- the generated version data.
110
-
111
- ## Installation
112
-
113
- See [INSTALL.md](./INSTALL.md) for detailed installation instructions.
114
-
115
- ## Version-String Flavors
116
-
117
- Code which uses Versioneer can learn about its version string at runtime by
118
- importing `_version` from your main `__init__.py` file and running the
119
- `get_versions()` function. From the "outside" (e.g. in `setup.py`), you can
120
- import the top-level `versioneer.py` and run `get_versions()`.
121
-
122
- Both functions return a dictionary with different flavors of version
123
- information:
124
-
125
- * `['version']`: A condensed version string, rendered using the selected
126
- style. This is the most commonly used value for the project's version
127
- string. The default "pep440" style yields strings like `0.11`,
128
- `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section
129
- below for alternative styles.
130
-
131
- * `['full-revisionid']`: detailed revision identifier. For Git, this is the
132
- full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac".
133
-
134
- * `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the
135
- commit date in ISO 8601 format. This will be None if the date is not
136
- available.
137
-
138
- * `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that
139
- this is only accurate if run in a VCS checkout, otherwise it is likely to
140
- be False or None
141
-
142
- * `['error']`: if the version string could not be computed, this will be set
143
- to a string describing the problem, otherwise it will be None. It may be
144
- useful to throw an exception in setup.py if this is set, to avoid e.g.
145
- creating tarballs with a version string of "unknown".
146
-
147
- Some variants are more useful than others. Including `full-revisionid` in a
148
- bug report should allow developers to reconstruct the exact code being tested
149
- (or indicate the presence of local changes that should be shared with the
150
- developers). `version` is suitable for display in an "about" box or a CLI
151
- `--version` output: it can be easily compared against release notes and lists
152
- of bugs fixed in various releases.
153
-
154
- The installer adds the following text to your `__init__.py` to place a basic
155
- version in `YOURPROJECT.__version__`:
156
-
157
- from ._version import get_versions
158
- __version__ = get_versions()['version']
159
- del get_versions
160
-
161
- ## Styles
162
-
163
- The setup.cfg `style=` configuration controls how the VCS information is
164
- rendered into a version string.
165
-
166
- The default style, "pep440", produces a PEP440-compliant string, equal to the
167
- un-prefixed tag name for actual releases, and containing an additional "local
168
- version" section with more detail for in-between builds. For Git, this is
169
- TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags
170
- --dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the
171
- tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and
172
- that this commit is two revisions ("+2") beyond the "0.11" tag. For released
173
- software (exactly equal to a known tag), the identifier will only contain the
174
- stripped tag, e.g. "0.11".
175
-
176
- Other styles are available. See [details.md](details.md) in the Versioneer
177
- source tree for descriptions.
178
-
179
- ## Debugging
180
-
181
- Versioneer tries to avoid fatal errors: if something goes wrong, it will tend
182
- to return a version of "0+unknown". To investigate the problem, run `setup.py
183
- version`, which will run the version-lookup code in a verbose mode, and will
184
- display the full contents of `get_versions()` (including the `error` string,
185
- which may help identify what went wrong).
186
-
187
- ## Known Limitations
188
-
189
- Some situations are known to cause problems for Versioneer. This details the
190
- most significant ones. More can be found on Github
191
- [issues page](https://github.com/warner/python-versioneer/issues).
192
-
193
- ### Subprojects
194
-
195
- Versioneer has limited support for source trees in which `setup.py` is not in
196
- the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are
197
- two common reasons why `setup.py` might not be in the root:
198
-
199
- * Source trees which contain multiple subprojects, such as
200
- [Buildbot](https://github.com/buildbot/buildbot), which contains both
201
- "master" and "slave" subprojects, each with their own `setup.py`,
202
- `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI
203
- distributions (and upload multiple independently-installable tarballs).
204
- * Source trees whose main purpose is to contain a C library, but which also
205
- provide bindings to Python (and perhaps other langauges) in subdirectories.
206
-
207
- Versioneer will look for `.git` in parent directories, and most operations
208
- should get the right version string. However `pip` and `setuptools` have bugs
209
- and implementation details which frequently cause `pip install .` from a
210
- subproject directory to fail to find a correct version string (so it usually
211
- defaults to `0+unknown`).
212
-
213
- `pip install --editable .` should work correctly. `setup.py install` might
214
- work too.
215
-
216
- Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in
217
- some later version.
218
-
219
- [Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking
220
- this issue. The discussion in
221
- [PR #61](https://github.com/warner/python-versioneer/pull/61) describes the
222
- issue from the Versioneer side in more detail.
223
- [pip PR#3176](https://github.com/pypa/pip/pull/3176) and
224
- [pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve
225
- pip to let Versioneer work correctly.
226
-
227
- Versioneer-0.16 and earlier only looked for a `.git` directory next to the
228
- `setup.cfg`, so subprojects were completely unsupported with those releases.
229
-
230
- ### Editable installs with setuptools <= 18.5
231
-
232
- `setup.py develop` and `pip install --editable .` allow you to install a
233
- project into a virtualenv once, then continue editing the source code (and
234
- test) without re-installing after every change.
235
-
236
- "Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a
237
- convenient way to specify executable scripts that should be installed along
238
- with the python package.
239
-
240
- These both work as expected when using modern setuptools. When using
241
- setuptools-18.5 or earlier, however, certain operations will cause
242
- `pkg_resources.DistributionNotFound` errors when running the entrypoint
243
- script, which must be resolved by re-installing the package. This happens
244
- when the install happens with one version, then the egg_info data is
245
- regenerated while a different version is checked out. Many setup.py commands
246
- cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into
247
- a different virtualenv), so this can be surprising.
248
-
249
- [Bug #83](https://github.com/warner/python-versioneer/issues/83) describes
250
- this one, but upgrading to a newer version of setuptools should probably
251
- resolve it.
252
-
253
- ### Unicode version strings
254
-
255
- While Versioneer works (and is continually tested) with both Python 2 and
256
- Python 3, it is not entirely consistent with bytes-vs-unicode distinctions.
257
- Newer releases probably generate unicode version strings on py2. It's not
258
- clear that this is wrong, but it may be surprising for applications when then
259
- write these strings to a network connection or include them in bytes-oriented
260
- APIs like cryptographic checksums.
261
-
262
- [Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates
263
- this question.
264
-
265
-
266
- ## Updating Versioneer
267
-
268
- To upgrade your project to a new release of Versioneer, do the following:
269
-
270
- * install the new Versioneer (`pip install -U versioneer` or equivalent)
271
- * edit `setup.cfg`, if necessary, to include any new configuration settings
272
- indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details.
273
- * re-run `versioneer install` in your source tree, to replace
274
- `SRC/_version.py`
275
- * commit any changed files
276
-
277
- ## Future Directions
278
-
279
- This tool is designed to make it easily extended to other version-control
280
- systems: all VCS-specific components are in separate directories like
281
- src/git/ . The top-level `versioneer.py` script is assembled from these
282
- components by running make-versioneer.py . In the future, make-versioneer.py
283
- will take a VCS name as an argument, and will construct a version of
284
- `versioneer.py` that is specific to the given VCS. It might also take the
285
- configuration arguments that are currently provided manually during
286
- installation by editing setup.py . Alternatively, it might go the other
287
- direction and include code from all supported VCS systems, reducing the
288
- number of intermediate scripts.
289
-
290
-
291
- ## License
292
-
293
- To make Versioneer easier to embed, all its code is dedicated to the public
294
- domain. The `_version.py` that it creates is also in the public domain.
295
- Specifically, both are released under the Creative Commons "Public Domain
296
- Dedication" license (CC0-1.0), as described in
297
- https://creativecommons.org/publicdomain/zero/1.0/ .
298
-
299
- """
300
-
301
- from __future__ import print_function
302
-
303
- try:
304
- import configparser
305
- except ImportError:
306
- import ConfigParser as configparser
307
- import errno
308
- import json
309
- import os
310
- import re
311
- import subprocess
312
- import sys
313
-
314
- # pylint: skip-file
315
-
316
-
317
- class VersioneerConfig:
318
- """Container for Versioneer configuration parameters."""
319
-
320
-
321
- def get_root():
322
- """Get the project root directory.
323
-
324
- We require that all commands are run from the project root, i.e. the
325
- directory that contains setup.py, setup.cfg, and versioneer.py .
326
- """
327
- root = os.path.realpath(os.path.abspath(os.getcwd()))
328
- setup_py = os.path.join(root, "setup.py")
329
- versioneer_py = os.path.join(root, "versioneer.py")
330
- if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)):
331
- # allow 'python path/to/setup.py COMMAND'
332
- root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0])))
333
- setup_py = os.path.join(root, "setup.py")
334
- versioneer_py = os.path.join(root, "versioneer.py")
335
- if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)):
336
- err = (
337
- "Versioneer was unable to run the project root directory. "
338
- "Versioneer requires setup.py to be executed from "
339
- "its immediate directory (like 'python setup.py COMMAND'), "
340
- "or in a way that lets it use sys.argv[0] to find the root "
341
- "(like 'python path/to/setup.py COMMAND')."
342
- )
343
- raise VersioneerBadRootError(err)
344
- try:
345
- # Certain runtime workflows (setup.py install/develop in a setuptools
346
- # tree) execute all dependencies in a single python process, so
347
- # "versioneer" may be imported multiple times, and python's shared
348
- # module-import table will cache the first one. So we can't use
349
- # os.path.dirname(__file__), as that will find whichever
350
- # versioneer.py was first imported, even in later projects.
351
- me = os.path.realpath(os.path.abspath(__file__))
352
- me_dir = os.path.normcase(os.path.splitext(me)[0])
353
- vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0])
354
- if me_dir != vsr_dir:
355
- print(
356
- "Warning: build in %s is using versioneer.py from %s"
357
- % (os.path.dirname(me), versioneer_py)
358
- )
359
- except NameError:
360
- pass
361
- return root
362
-
363
-
364
- def get_config_from_root(root):
365
- """Read the project setup.cfg file to determine Versioneer config."""
366
- # This might raise EnvironmentError (if setup.cfg is missing), or
367
- # configparser.NoSectionError (if it lacks a [versioneer] section), or
368
- # configparser.NoOptionError (if it lacks "VCS="). See the docstring at
369
- # the top of versioneer.py for instructions on writing your setup.cfg .
370
- setup_cfg = os.path.join(root, "setup.cfg")
371
- parser = configparser.SafeConfigParser()
372
- with open(setup_cfg, "r") as f:
373
- parser.readfp(f)
374
- VCS = parser.get("versioneer", "VCS") # mandatory
375
-
376
- def get(parser, name):
377
- if parser.has_option("versioneer", name):
378
- return parser.get("versioneer", name)
379
- return None
380
-
381
- cfg = VersioneerConfig()
382
- cfg.VCS = VCS
383
- cfg.style = get(parser, "style") or ""
384
- cfg.versionfile_source = get(parser, "versionfile_source")
385
- cfg.versionfile_build = get(parser, "versionfile_build")
386
- cfg.tag_prefix = get(parser, "tag_prefix")
387
- if cfg.tag_prefix in ("''", '""'):
388
- cfg.tag_prefix = ""
389
- cfg.parentdir_prefix = get(parser, "parentdir_prefix")
390
- cfg.verbose = get(parser, "verbose")
391
- return cfg
392
-
393
-
394
- class NotThisMethod(Exception):
395
- """Exception raised if a method is not valid for the current scenario."""
396
-
397
-
398
- # these dictionaries contain VCS-specific tools
399
- LONG_VERSION_PY = {}
400
- HANDLERS = {}
401
-
402
-
403
- def register_vcs_handler(vcs, method): # decorator
404
- """Decorator to mark a method as the handler for a particular VCS."""
405
-
406
- def decorate(f):
407
- """Store f in HANDLERS[vcs][method]."""
408
- if vcs not in HANDLERS:
409
- HANDLERS[vcs] = {}
410
- HANDLERS[vcs][method] = f
411
- return f
412
-
413
- return decorate
414
-
415
-
416
- def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None):
417
- """Call the given command(s)."""
418
- assert isinstance(commands, list)
419
- p = None
420
- for c in commands:
421
- try:
422
- dispcmd = str([c] + args)
423
- # remember shell=False, so use git.cmd on windows, not just git
424
- p = subprocess.Popen(
425
- [c] + args,
426
- cwd=cwd,
427
- env=env,
428
- stdout=subprocess.PIPE,
429
- stderr=(subprocess.PIPE if hide_stderr else None),
430
- )
431
- break
432
- except EnvironmentError:
433
- e = sys.exc_info()[1]
434
- if e.errno == errno.ENOENT:
435
- continue
436
- if verbose:
437
- print("unable to run %s" % dispcmd)
438
- print(e)
439
- return None, None
440
- else:
441
- if verbose:
442
- print("unable to find command, tried %s" % (commands,))
443
- return None, None
444
- stdout = p.communicate()[0].strip()
445
- if sys.version_info[0] >= 3:
446
- stdout = stdout.decode()
447
- if p.returncode != 0:
448
- if verbose:
449
- print("unable to run %s (error)" % dispcmd)
450
- print("stdout was %s" % stdout)
451
- return None, p.returncode
452
- return stdout, p.returncode
453
-
454
-
455
- LONG_VERSION_PY[
456
- "git"
457
- ] = '''
458
- # This file helps to compute a version number in source trees obtained from
459
- # git-archive tarball (such as those provided by githubs download-from-tag
460
- # feature). Distribution tarballs (built by setup.py sdist) and build
461
- # directories (produced by setup.py build) will contain a much shorter file
462
- # that just contains the computed version number.
463
-
464
- # This file is released into the public domain. Generated by
465
- # versioneer-0.18 (https://github.com/warner/python-versioneer)
466
-
467
- """Git implementation of _version.py."""
468
-
469
- import errno
470
- import os
471
- import re
472
- import subprocess
473
- import sys
474
-
475
-
476
- def get_keywords():
477
- """Get the keywords needed to look up the version information."""
478
- # these strings will be replaced by git during git-archive.
479
- # setup.py/versioneer.py will grep for the variable names, so they must
480
- # each be defined on a line of their own. _version.py will just call
481
- # get_keywords().
482
- git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s"
483
- git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s"
484
- git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s"
485
- keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
486
- return keywords
487
-
488
-
489
- class VersioneerConfig:
490
- """Container for Versioneer configuration parameters."""
491
-
492
-
493
- def get_config():
494
- """Create, populate and return the VersioneerConfig() object."""
495
- # these strings are filled in when 'setup.py versioneer' creates
496
- # _version.py
497
- cfg = VersioneerConfig()
498
- cfg.VCS = "git"
499
- cfg.style = "%(STYLE)s"
500
- cfg.tag_prefix = "%(TAG_PREFIX)s"
501
- cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s"
502
- cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s"
503
- cfg.verbose = False
504
- return cfg
505
-
506
-
507
- class NotThisMethod(Exception):
508
- """Exception raised if a method is not valid for the current scenario."""
509
-
510
-
511
- LONG_VERSION_PY = {}
512
- HANDLERS = {}
513
-
514
-
515
- def register_vcs_handler(vcs, method): # decorator
516
- """Decorator to mark a method as the handler for a particular VCS."""
517
- def decorate(f):
518
- """Store f in HANDLERS[vcs][method]."""
519
- if vcs not in HANDLERS:
520
- HANDLERS[vcs] = {}
521
- HANDLERS[vcs][method] = f
522
- return f
523
- return decorate
524
-
525
-
526
- def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
527
- env=None):
528
- """Call the given command(s)."""
529
- assert isinstance(commands, list)
530
- p = None
531
- for c in commands:
532
- try:
533
- dispcmd = str([c] + args)
534
- # remember shell=False, so use git.cmd on windows, not just git
535
- p = subprocess.Popen([c] + args, cwd=cwd, env=env,
536
- stdout=subprocess.PIPE,
537
- stderr=(subprocess.PIPE if hide_stderr
538
- else None))
539
- break
540
- except EnvironmentError:
541
- e = sys.exc_info()[1]
542
- if e.errno == errno.ENOENT:
543
- continue
544
- if verbose:
545
- print("unable to run %%s" %% dispcmd)
546
- print(e)
547
- return None, None
548
- else:
549
- if verbose:
550
- print("unable to find command, tried %%s" %% (commands,))
551
- return None, None
552
- stdout = p.communicate()[0].strip()
553
- if sys.version_info[0] >= 3:
554
- stdout = stdout.decode()
555
- if p.returncode != 0:
556
- if verbose:
557
- print("unable to run %%s (error)" %% dispcmd)
558
- print("stdout was %%s" %% stdout)
559
- return None, p.returncode
560
- return stdout, p.returncode
561
-
562
-
563
- def versions_from_parentdir(parentdir_prefix, root, verbose):
564
- """Try to determine the version from the parent directory name.
565
-
566
- Source tarballs conventionally unpack into a directory that includes both
567
- the project name and a version string. We will also support searching up
568
- two directory levels for an appropriately named parent directory
569
- """
570
- rootdirs = []
571
-
572
- for i in range(3):
573
- dirname = os.path.basename(root)
574
- if dirname.startswith(parentdir_prefix):
575
- return {"version": dirname[len(parentdir_prefix):],
576
- "full-revisionid": None,
577
- "dirty": False, "error": None, "date": None}
578
- else:
579
- rootdirs.append(root)
580
- root = os.path.dirname(root) # up a level
581
-
582
- if verbose:
583
- print("Tried directories %%s but none started with prefix %%s" %%
584
- (str(rootdirs), parentdir_prefix))
585
- raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
586
-
587
-
588
- @register_vcs_handler("git", "get_keywords")
589
- def git_get_keywords(versionfile_abs):
590
- """Extract version information from the given file."""
591
- # the code embedded in _version.py can just fetch the value of these
592
- # keywords. When used from setup.py, we don't want to import _version.py,
593
- # so we do it with a regexp instead. This function is not used from
594
- # _version.py.
595
- keywords = {}
596
- try:
597
- f = open(versionfile_abs, "r")
598
- for line in f.readlines():
599
- if line.strip().startswith("git_refnames ="):
600
- mo = re.search(r'=\s*"(.*)"', line)
601
- if mo:
602
- keywords["refnames"] = mo.group(1)
603
- if line.strip().startswith("git_full ="):
604
- mo = re.search(r'=\s*"(.*)"', line)
605
- if mo:
606
- keywords["full"] = mo.group(1)
607
- if line.strip().startswith("git_date ="):
608
- mo = re.search(r'=\s*"(.*)"', line)
609
- if mo:
610
- keywords["date"] = mo.group(1)
611
- f.close()
612
- except EnvironmentError:
613
- pass
614
- return keywords
615
-
616
-
617
- @register_vcs_handler("git", "keywords")
618
- def git_versions_from_keywords(keywords, tag_prefix, verbose):
619
- """Get version information from git keywords."""
620
- if not keywords:
621
- raise NotThisMethod("no keywords at all, weird")
622
- date = keywords.get("date")
623
- if date is not None:
624
- # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant
625
- # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601
626
- # -like" string, which we must then edit to make compliant), because
627
- # it's been around since git-1.5.3, and it's too difficult to
628
- # discover which version we're using, or to work around using an
629
- # older one.
630
- date = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
631
- refnames = keywords["refnames"].strip()
632
- if refnames.startswith("$Format"):
633
- if verbose:
634
- print("keywords are unexpanded, not using")
635
- raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
636
- refs = set([r.strip() for r in refnames.strip("()").split(",")])
637
- # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
638
- # just "foo-1.0". If we see a "tag: " prefix, prefer those.
639
- TAG = "tag: "
640
- tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
641
- if not tags:
642
- # Either we're using git < 1.8.3, or there really are no tags. We use
643
- # a heuristic: assume all version tags have a digit. The old git %%d
644
- # expansion behaves like git log --decorate=short and strips out the
645
- # refs/heads/ and refs/tags/ prefixes that would let us distinguish
646
- # between branches and tags. By ignoring refnames without digits, we
647
- # filter out many common branch names like "release" and
648
- # "stabilization", as well as "HEAD" and "master".
649
- tags = set([r for r in refs if re.search(r'\d', r)])
650
- if verbose:
651
- print("discarding '%%s', no digits" %% ",".join(refs - tags))
652
- if verbose:
653
- print("likely tags: %%s" %% ",".join(sorted(tags)))
654
- for ref in sorted(tags):
655
- # sorting will prefer e.g. "2.0" over "2.0rc1"
656
- if ref.startswith(tag_prefix):
657
- r = ref[len(tag_prefix):]
658
- if verbose:
659
- print("picking %%s" %% r)
660
- return {"version": r,
661
- "full-revisionid": keywords["full"].strip(),
662
- "dirty": False, "error": None,
663
- "date": date}
664
- # no suitable tags, so version is "0+unknown", but full hex is still there
665
- if verbose:
666
- print("no suitable tags, using unknown + full revision id")
667
- return {"version": "0+unknown",
668
- "full-revisionid": keywords["full"].strip(),
669
- "dirty": False, "error": "no suitable tags", "date": None}
670
-
671
-
672
- @register_vcs_handler("git", "pieces_from_vcs")
673
- def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
674
- """Get version from 'git describe' in the root of the source tree.
675
-
676
- This only gets called if the git-archive 'subst' keywords were *not*
677
- expanded, and _version.py hasn't already been rewritten with a short
678
- version string, meaning we're inside a checked out source tree.
679
- """
680
- GITS = ["git"]
681
- if sys.platform == "win32":
682
- GITS = ["git.cmd", "git.exe"]
683
-
684
- out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root,
685
- hide_stderr=True)
686
- if rc != 0:
687
- if verbose:
688
- print("Directory %%s not under git control" %% root)
689
- raise NotThisMethod("'git rev-parse --git-dir' returned error")
690
-
691
- # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
692
- # if there isn't one, this yields HEX[-dirty] (no NUM)
693
- describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty",
694
- "--always", "--long",
695
- "--match", "%%s*" %% tag_prefix],
696
- cwd=root)
697
- # --long was added in git-1.5.5
698
- if describe_out is None:
699
- raise NotThisMethod("'git describe' failed")
700
- describe_out = describe_out.strip()
701
- full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
702
- if full_out is None:
703
- raise NotThisMethod("'git rev-parse' failed")
704
- full_out = full_out.strip()
705
-
706
- pieces = {}
707
- pieces["long"] = full_out
708
- pieces["short"] = full_out[:7] # maybe improved later
709
- pieces["error"] = None
710
-
711
- # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
712
- # TAG might have hyphens.
713
- git_describe = describe_out
714
-
715
- # look for -dirty suffix
716
- dirty = git_describe.endswith("-dirty")
717
- pieces["dirty"] = dirty
718
- if dirty:
719
- git_describe = git_describe[:git_describe.rindex("-dirty")]
720
-
721
- # now we have TAG-NUM-gHEX or HEX
722
-
723
- if "-" in git_describe:
724
- # TAG-NUM-gHEX
725
- mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
726
- if not mo:
727
- # unparseable. Maybe git-describe is misbehaving?
728
- pieces["error"] = ("unable to parse git-describe output: '%%s'"
729
- %% describe_out)
730
- return pieces
731
-
732
- # tag
733
- full_tag = mo.group(1)
734
- if not full_tag.startswith(tag_prefix):
735
- if verbose:
736
- fmt = "tag '%%s' doesn't start with prefix '%%s'"
737
- print(fmt %% (full_tag, tag_prefix))
738
- pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'"
739
- %% (full_tag, tag_prefix))
740
- return pieces
741
- pieces["closest-tag"] = full_tag[len(tag_prefix):]
742
-
743
- # distance: number of commits since tag
744
- pieces["distance"] = int(mo.group(2))
745
-
746
- # commit: short hex revision ID
747
- pieces["short"] = mo.group(3)
748
-
749
- else:
750
- # HEX: no tags
751
- pieces["closest-tag"] = None
752
- count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"],
753
- cwd=root)
754
- pieces["distance"] = int(count_out) # total number of commits
755
-
756
- # commit date: see ISO-8601 comment in git_versions_from_keywords()
757
- date = run_command(GITS, ["show", "-s", "--format=%%ci", "HEAD"],
758
- cwd=root)[0].strip()
759
- pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
760
-
761
- return pieces
762
-
763
-
764
- def plus_or_dot(pieces):
765
- """Return a + if we don't already have one, else return a ."""
766
- if "+" in pieces.get("closest-tag", ""):
767
- return "."
768
- return "+"
769
-
770
-
771
- def render_pep440(pieces):
772
- """Build up version string, with post-release "local version identifier".
773
-
774
- Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
775
- get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
776
-
777
- Exceptions:
778
- 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
779
- """
780
- if pieces["closest-tag"]:
781
- rendered = pieces["closest-tag"]
782
- if pieces["distance"] or pieces["dirty"]:
783
- rendered += plus_or_dot(pieces)
784
- rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"])
785
- if pieces["dirty"]:
786
- rendered += ".dirty"
787
- else:
788
- # exception #1
789
- rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"],
790
- pieces["short"])
791
- if pieces["dirty"]:
792
- rendered += ".dirty"
793
- return rendered
794
-
795
-
796
- def render_pep440_pre(pieces):
797
- """TAG[.post.devDISTANCE] -- No -dirty.
798
-
799
- Exceptions:
800
- 1: no tags. 0.post.devDISTANCE
801
- """
802
- if pieces["closest-tag"]:
803
- rendered = pieces["closest-tag"]
804
- if pieces["distance"]:
805
- rendered += ".post.dev%%d" %% pieces["distance"]
806
- else:
807
- # exception #1
808
- rendered = "0.post.dev%%d" %% pieces["distance"]
809
- return rendered
810
-
811
-
812
- def render_pep440_post(pieces):
813
- """TAG[.postDISTANCE[.dev0]+gHEX] .
814
-
815
- The ".dev0" means dirty. Note that .dev0 sorts backwards
816
- (a dirty tree will appear "older" than the corresponding clean one),
817
- but you shouldn't be releasing software with -dirty anyways.
818
-
819
- Exceptions:
820
- 1: no tags. 0.postDISTANCE[.dev0]
821
- """
822
- if pieces["closest-tag"]:
823
- rendered = pieces["closest-tag"]
824
- if pieces["distance"] or pieces["dirty"]:
825
- rendered += ".post%%d" %% pieces["distance"]
826
- if pieces["dirty"]:
827
- rendered += ".dev0"
828
- rendered += plus_or_dot(pieces)
829
- rendered += "g%%s" %% pieces["short"]
830
- else:
831
- # exception #1
832
- rendered = "0.post%%d" %% pieces["distance"]
833
- if pieces["dirty"]:
834
- rendered += ".dev0"
835
- rendered += "+g%%s" %% pieces["short"]
836
- return rendered
837
-
838
-
839
- def render_pep440_old(pieces):
840
- """TAG[.postDISTANCE[.dev0]] .
841
-
842
- The ".dev0" means dirty.
843
-
844
- Eexceptions:
845
- 1: no tags. 0.postDISTANCE[.dev0]
846
- """
847
- if pieces["closest-tag"]:
848
- rendered = pieces["closest-tag"]
849
- if pieces["distance"] or pieces["dirty"]:
850
- rendered += ".post%%d" %% pieces["distance"]
851
- if pieces["dirty"]:
852
- rendered += ".dev0"
853
- else:
854
- # exception #1
855
- rendered = "0.post%%d" %% pieces["distance"]
856
- if pieces["dirty"]:
857
- rendered += ".dev0"
858
- return rendered
859
-
860
-
861
- def render_git_describe(pieces):
862
- """TAG[-DISTANCE-gHEX][-dirty].
863
-
864
- Like 'git describe --tags --dirty --always'.
865
-
866
- Exceptions:
867
- 1: no tags. HEX[-dirty] (note: no 'g' prefix)
868
- """
869
- if pieces["closest-tag"]:
870
- rendered = pieces["closest-tag"]
871
- if pieces["distance"]:
872
- rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"])
873
- else:
874
- # exception #1
875
- rendered = pieces["short"]
876
- if pieces["dirty"]:
877
- rendered += "-dirty"
878
- return rendered
879
-
880
-
881
- def render_git_describe_long(pieces):
882
- """TAG-DISTANCE-gHEX[-dirty].
883
-
884
- Like 'git describe --tags --dirty --always -long'.
885
- The distance/hash is unconditional.
886
-
887
- Exceptions:
888
- 1: no tags. HEX[-dirty] (note: no 'g' prefix)
889
- """
890
- if pieces["closest-tag"]:
891
- rendered = pieces["closest-tag"]
892
- rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"])
893
- else:
894
- # exception #1
895
- rendered = pieces["short"]
896
- if pieces["dirty"]:
897
- rendered += "-dirty"
898
- return rendered
899
-
900
-
901
- def render(pieces, style):
902
- """Render the given version pieces into the requested style."""
903
- if pieces["error"]:
904
- return {"version": "unknown",
905
- "full-revisionid": pieces.get("long"),
906
- "dirty": None,
907
- "error": pieces["error"],
908
- "date": None}
909
-
910
- if not style or style == "default":
911
- style = "pep440" # the default
912
-
913
- if style == "pep440":
914
- rendered = render_pep440(pieces)
915
- elif style == "pep440-pre":
916
- rendered = render_pep440_pre(pieces)
917
- elif style == "pep440-post":
918
- rendered = render_pep440_post(pieces)
919
- elif style == "pep440-old":
920
- rendered = render_pep440_old(pieces)
921
- elif style == "git-describe":
922
- rendered = render_git_describe(pieces)
923
- elif style == "git-describe-long":
924
- rendered = render_git_describe_long(pieces)
925
- else:
926
- raise ValueError("unknown style '%%s'" %% style)
927
-
928
- return {"version": rendered, "full-revisionid": pieces["long"],
929
- "dirty": pieces["dirty"], "error": None,
930
- "date": pieces.get("date")}
931
-
932
-
933
- def get_versions():
934
- """Get version information or return default if unable to do so."""
935
- # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
936
- # __file__, we can work backwards from there to the root. Some
937
- # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
938
- # case we can only use expanded keywords.
939
-
940
- cfg = get_config()
941
- verbose = cfg.verbose
942
-
943
- try:
944
- return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
945
- verbose)
946
- except NotThisMethod:
947
- pass
948
-
949
- try:
950
- root = os.path.realpath(__file__)
951
- # versionfile_source is the relative path from the top of the source
952
- # tree (where the .git directory might live) to this file. Invert
953
- # this to find the root from __file__.
954
- for i in cfg.versionfile_source.split('/'):
955
- root = os.path.dirname(root)
956
- except NameError:
957
- return {"version": "0+unknown", "full-revisionid": None,
958
- "dirty": None,
959
- "error": "unable to find root of source tree",
960
- "date": None}
961
-
962
- try:
963
- pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
964
- return render(pieces, cfg.style)
965
- except NotThisMethod:
966
- pass
967
-
968
- try:
969
- if cfg.parentdir_prefix:
970
- return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
971
- except NotThisMethod:
972
- pass
973
-
974
- return {"version": "0+unknown", "full-revisionid": None,
975
- "dirty": None,
976
- "error": "unable to compute version", "date": None}
977
- '''
978
-
979
-
980
- @register_vcs_handler("git", "get_keywords")
981
- def git_get_keywords(versionfile_abs):
982
- """Extract version information from the given file."""
983
- # the code embedded in _version.py can just fetch the value of these
984
- # keywords. When used from setup.py, we don't want to import _version.py,
985
- # so we do it with a regexp instead. This function is not used from
986
- # _version.py.
987
- keywords = {}
988
- try:
989
- f = open(versionfile_abs, "r")
990
- for line in f.readlines():
991
- if line.strip().startswith("git_refnames ="):
992
- mo = re.search(r'=\s*"(.*)"', line)
993
- if mo:
994
- keywords["refnames"] = mo.group(1)
995
- if line.strip().startswith("git_full ="):
996
- mo = re.search(r'=\s*"(.*)"', line)
997
- if mo:
998
- keywords["full"] = mo.group(1)
999
- if line.strip().startswith("git_date ="):
1000
- mo = re.search(r'=\s*"(.*)"', line)
1001
- if mo:
1002
- keywords["date"] = mo.group(1)
1003
- f.close()
1004
- except EnvironmentError:
1005
- pass
1006
- return keywords
1007
-
1008
-
1009
- @register_vcs_handler("git", "keywords")
1010
- def git_versions_from_keywords(keywords, tag_prefix, verbose):
1011
- """Get version information from git keywords."""
1012
- if not keywords:
1013
- raise NotThisMethod("no keywords at all, weird")
1014
- date = keywords.get("date")
1015
- if date is not None:
1016
- # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant
1017
- # datestamp. However we prefer "%ci" (which expands to an "ISO-8601
1018
- # -like" string, which we must then edit to make compliant), because
1019
- # it's been around since git-1.5.3, and it's too difficult to
1020
- # discover which version we're using, or to work around using an
1021
- # older one.
1022
- date = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
1023
- refnames = keywords["refnames"].strip()
1024
- if refnames.startswith("$Format"):
1025
- if verbose:
1026
- print("keywords are unexpanded, not using")
1027
- raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
1028
- refs = set([r.strip() for r in refnames.strip("()").split(",")])
1029
- # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
1030
- # just "foo-1.0". If we see a "tag: " prefix, prefer those.
1031
- TAG = "tag: "
1032
- tags = set([r[len(TAG) :] for r in refs if r.startswith(TAG)])
1033
- if not tags:
1034
- # Either we're using git < 1.8.3, or there really are no tags. We use
1035
- # a heuristic: assume all version tags have a digit. The old git %d
1036
- # expansion behaves like git log --decorate=short and strips out the
1037
- # refs/heads/ and refs/tags/ prefixes that would let us distinguish
1038
- # between branches and tags. By ignoring refnames without digits, we
1039
- # filter out many common branch names like "release" and
1040
- # "stabilization", as well as "HEAD" and "master".
1041
- tags = set([r for r in refs if re.search(r"\d", r)])
1042
- if verbose:
1043
- print("discarding '%s', no digits" % ",".join(refs - tags))
1044
- if verbose:
1045
- print("likely tags: %s" % ",".join(sorted(tags)))
1046
- for ref in sorted(tags):
1047
- # sorting will prefer e.g. "2.0" over "2.0rc1"
1048
- if ref.startswith(tag_prefix):
1049
- r = ref[len(tag_prefix) :]
1050
- if verbose:
1051
- print("picking %s" % r)
1052
- return {
1053
- "version": r,
1054
- "full-revisionid": keywords["full"].strip(),
1055
- "dirty": False,
1056
- "error": None,
1057
- "date": date,
1058
- }
1059
- # no suitable tags, so version is "0+unknown", but full hex is still there
1060
- if verbose:
1061
- print("no suitable tags, using unknown + full revision id")
1062
- return {
1063
- "version": "0+unknown",
1064
- "full-revisionid": keywords["full"].strip(),
1065
- "dirty": False,
1066
- "error": "no suitable tags",
1067
- "date": None,
1068
- }
1069
-
1070
-
1071
- @register_vcs_handler("git", "pieces_from_vcs")
1072
- def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
1073
- """Get version from 'git describe' in the root of the source tree.
1074
-
1075
- This only gets called if the git-archive 'subst' keywords were *not*
1076
- expanded, and _version.py hasn't already been rewritten with a short
1077
- version string, meaning we're inside a checked out source tree.
1078
- """
1079
- GITS = ["git"]
1080
- if sys.platform == "win32":
1081
- GITS = ["git.cmd", "git.exe"]
1082
-
1083
- out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True)
1084
- if rc != 0:
1085
- if verbose:
1086
- print("Directory %s not under git control" % root)
1087
- raise NotThisMethod("'git rev-parse --git-dir' returned error")
1088
-
1089
- # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
1090
- # if there isn't one, this yields HEX[-dirty] (no NUM)
1091
- describe_out, rc = run_command(
1092
- GITS,
1093
- ["describe", "--tags", "--dirty", "--always", "--long", "--match", "%s*" % tag_prefix],
1094
- cwd=root,
1095
- )
1096
- # --long was added in git-1.5.5
1097
- if describe_out is None:
1098
- raise NotThisMethod("'git describe' failed")
1099
- describe_out = describe_out.strip()
1100
- full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
1101
- if full_out is None:
1102
- raise NotThisMethod("'git rev-parse' failed")
1103
- full_out = full_out.strip()
1104
-
1105
- pieces = {}
1106
- pieces["long"] = full_out
1107
- pieces["short"] = full_out[:7] # maybe improved later
1108
- pieces["error"] = None
1109
-
1110
- # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
1111
- # TAG might have hyphens.
1112
- git_describe = describe_out
1113
-
1114
- # look for -dirty suffix
1115
- dirty = git_describe.endswith("-dirty")
1116
- pieces["dirty"] = dirty
1117
- if dirty:
1118
- git_describe = git_describe[: git_describe.rindex("-dirty")]
1119
-
1120
- # now we have TAG-NUM-gHEX or HEX
1121
-
1122
- if "-" in git_describe:
1123
- # TAG-NUM-gHEX
1124
- mo = re.search(r"^(.+)-(\d+)-g([0-9a-f]+)$", git_describe)
1125
- if not mo:
1126
- # unparseable. Maybe git-describe is misbehaving?
1127
- pieces["error"] = "unable to parse git-describe output: '%s'" % describe_out
1128
- return pieces
1129
-
1130
- # tag
1131
- full_tag = mo.group(1)
1132
- if not full_tag.startswith(tag_prefix):
1133
- if verbose:
1134
- fmt = "tag '%s' doesn't start with prefix '%s'"
1135
- print(fmt % (full_tag, tag_prefix))
1136
- pieces["error"] = "tag '%s' doesn't start with prefix '%s'" % (full_tag, tag_prefix)
1137
- return pieces
1138
- pieces["closest-tag"] = full_tag[len(tag_prefix) :]
1139
-
1140
- # distance: number of commits since tag
1141
- pieces["distance"] = int(mo.group(2))
1142
-
1143
- # commit: short hex revision ID
1144
- pieces["short"] = mo.group(3)
1145
-
1146
- else:
1147
- # HEX: no tags
1148
- pieces["closest-tag"] = None
1149
- count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root)
1150
- pieces["distance"] = int(count_out) # total number of commits
1151
-
1152
- # commit date: see ISO-8601 comment in git_versions_from_keywords()
1153
- date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip()
1154
- pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
1155
-
1156
- return pieces
1157
-
1158
-
1159
- def do_vcs_install(manifest_in, versionfile_source, ipy):
1160
- """Git-specific installation logic for Versioneer.
1161
-
1162
- For Git, this means creating/changing .gitattributes to mark _version.py
1163
- for export-subst keyword substitution.
1164
- """
1165
- GITS = ["git"]
1166
- if sys.platform == "win32":
1167
- GITS = ["git.cmd", "git.exe"]
1168
- files = [manifest_in, versionfile_source]
1169
- if ipy:
1170
- files.append(ipy)
1171
- try:
1172
- me = __file__
1173
- if me.endswith(".pyc") or me.endswith(".pyo"):
1174
- me = os.path.splitext(me)[0] + ".py"
1175
- versioneer_file = os.path.relpath(me)
1176
- except NameError:
1177
- versioneer_file = "versioneer.py"
1178
- files.append(versioneer_file)
1179
- present = False
1180
- try:
1181
- f = open(".gitattributes", "r")
1182
- for line in f.readlines():
1183
- if line.strip().startswith(versionfile_source):
1184
- if "export-subst" in line.strip().split()[1:]:
1185
- present = True
1186
- f.close()
1187
- except EnvironmentError:
1188
- pass
1189
- if not present:
1190
- f = open(".gitattributes", "a+")
1191
- f.write("%s export-subst\n" % versionfile_source)
1192
- f.close()
1193
- files.append(".gitattributes")
1194
- run_command(GITS, ["add", "--"] + files)
1195
-
1196
-
1197
- def versions_from_parentdir(parentdir_prefix, root, verbose):
1198
- """Try to determine the version from the parent directory name.
1199
-
1200
- Source tarballs conventionally unpack into a directory that includes both
1201
- the project name and a version string. We will also support searching up
1202
- two directory levels for an appropriately named parent directory
1203
- """
1204
- rootdirs = []
1205
-
1206
- for i in range(3):
1207
- dirname = os.path.basename(root)
1208
- if dirname.startswith(parentdir_prefix):
1209
- return {
1210
- "version": dirname[len(parentdir_prefix) :],
1211
- "full-revisionid": None,
1212
- "dirty": False,
1213
- "error": None,
1214
- "date": None,
1215
- }
1216
- else:
1217
- rootdirs.append(root)
1218
- root = os.path.dirname(root) # up a level
1219
-
1220
- if verbose:
1221
- print(
1222
- "Tried directories %s but none started with prefix %s"
1223
- % (str(rootdirs), parentdir_prefix)
1224
- )
1225
- raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
1226
-
1227
-
1228
- SHORT_VERSION_PY = """
1229
- # This file was generated by 'versioneer.py' (0.18) from
1230
- # revision-control system data, or from the parent directory name of an
1231
- # unpacked source archive. Distribution tarballs contain a pre-generated copy
1232
- # of this file.
1233
-
1234
- import json
1235
-
1236
- version_json = '''
1237
- %s
1238
- ''' # END VERSION_JSON
1239
-
1240
-
1241
- def get_versions():
1242
- return json.loads(version_json)
1243
- """
1244
-
1245
-
1246
- def versions_from_file(filename):
1247
- """Try to determine the version from _version.py if present."""
1248
- try:
1249
- with open(filename) as f:
1250
- contents = f.read()
1251
- except EnvironmentError:
1252
- raise NotThisMethod("unable to read _version.py")
1253
- mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", contents, re.M | re.S)
1254
- if not mo:
1255
- mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", contents, re.M | re.S)
1256
- if not mo:
1257
- raise NotThisMethod("no version_json in _version.py")
1258
- return json.loads(mo.group(1))
1259
-
1260
-
1261
- def write_to_version_file(filename, versions):
1262
- """Write the given version number to the given _version.py file."""
1263
- os.unlink(filename)
1264
- contents = json.dumps(versions, sort_keys=True, indent=1, separators=(",", ": "))
1265
- with open(filename, "w") as f:
1266
- f.write(SHORT_VERSION_PY % contents)
1267
-
1268
- print("set %s to '%s'" % (filename, versions["version"]))
1269
-
1270
-
1271
- def plus_or_dot(pieces):
1272
- """Return a + if we don't already have one, else return a ."""
1273
- if "+" in pieces.get("closest-tag", ""):
1274
- return "."
1275
- return "+"
1276
-
1277
-
1278
- def render_pep440(pieces):
1279
- """Build up version string, with post-release "local version identifier".
1280
-
1281
- Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
1282
- get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
1283
-
1284
- Exceptions:
1285
- 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
1286
- """
1287
- if pieces["closest-tag"]:
1288
- rendered = pieces["closest-tag"]
1289
- if pieces["distance"] or pieces["dirty"]:
1290
- rendered += plus_or_dot(pieces)
1291
- rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
1292
- if pieces["dirty"]:
1293
- rendered += ".dirty"
1294
- else:
1295
- # exception #1
1296
- rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"])
1297
- if pieces["dirty"]:
1298
- rendered += ".dirty"
1299
- return rendered
1300
-
1301
-
1302
- def render_pep440_pre(pieces):
1303
- """TAG[.post.devDISTANCE] -- No -dirty.
1304
-
1305
- Exceptions:
1306
- 1: no tags. 0.post.devDISTANCE
1307
- """
1308
- if pieces["closest-tag"]:
1309
- rendered = pieces["closest-tag"]
1310
- if pieces["distance"]:
1311
- rendered += ".post.dev%d" % pieces["distance"]
1312
- else:
1313
- # exception #1
1314
- rendered = "0.post.dev%d" % pieces["distance"]
1315
- return rendered
1316
-
1317
-
1318
- def render_pep440_post(pieces):
1319
- """TAG[.postDISTANCE[.dev0]+gHEX] .
1320
-
1321
- The ".dev0" means dirty. Note that .dev0 sorts backwards
1322
- (a dirty tree will appear "older" than the corresponding clean one),
1323
- but you shouldn't be releasing software with -dirty anyways.
1324
-
1325
- Exceptions:
1326
- 1: no tags. 0.postDISTANCE[.dev0]
1327
- """
1328
- if pieces["closest-tag"]:
1329
- rendered = pieces["closest-tag"]
1330
- if pieces["distance"] or pieces["dirty"]:
1331
- rendered += ".post%d" % pieces["distance"]
1332
- if pieces["dirty"]:
1333
- rendered += ".dev0"
1334
- rendered += plus_or_dot(pieces)
1335
- rendered += "g%s" % pieces["short"]
1336
- else:
1337
- # exception #1
1338
- rendered = "0.post%d" % pieces["distance"]
1339
- if pieces["dirty"]:
1340
- rendered += ".dev0"
1341
- rendered += "+g%s" % pieces["short"]
1342
- return rendered
1343
-
1344
-
1345
- def render_pep440_old(pieces):
1346
- """TAG[.postDISTANCE[.dev0]] .
1347
-
1348
- The ".dev0" means dirty.
1349
-
1350
- Eexceptions:
1351
- 1: no tags. 0.postDISTANCE[.dev0]
1352
- """
1353
- if pieces["closest-tag"]:
1354
- rendered = pieces["closest-tag"]
1355
- if pieces["distance"] or pieces["dirty"]:
1356
- rendered += ".post%d" % pieces["distance"]
1357
- if pieces["dirty"]:
1358
- rendered += ".dev0"
1359
- else:
1360
- # exception #1
1361
- rendered = "0.post%d" % pieces["distance"]
1362
- if pieces["dirty"]:
1363
- rendered += ".dev0"
1364
- return rendered
1365
-
1366
-
1367
- def render_git_describe(pieces):
1368
- """TAG[-DISTANCE-gHEX][-dirty].
1369
-
1370
- Like 'git describe --tags --dirty --always'.
1371
-
1372
- Exceptions:
1373
- 1: no tags. HEX[-dirty] (note: no 'g' prefix)
1374
- """
1375
- if pieces["closest-tag"]:
1376
- rendered = pieces["closest-tag"]
1377
- if pieces["distance"]:
1378
- rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
1379
- else:
1380
- # exception #1
1381
- rendered = pieces["short"]
1382
- if pieces["dirty"]:
1383
- rendered += "-dirty"
1384
- return rendered
1385
-
1386
-
1387
- def render_git_describe_long(pieces):
1388
- """TAG-DISTANCE-gHEX[-dirty].
1389
-
1390
- Like 'git describe --tags --dirty --always -long'.
1391
- The distance/hash is unconditional.
1392
-
1393
- Exceptions:
1394
- 1: no tags. HEX[-dirty] (note: no 'g' prefix)
1395
- """
1396
- if pieces["closest-tag"]:
1397
- rendered = pieces["closest-tag"]
1398
- rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
1399
- else:
1400
- # exception #1
1401
- rendered = pieces["short"]
1402
- if pieces["dirty"]:
1403
- rendered += "-dirty"
1404
- return rendered
1405
-
1406
-
1407
- def render(pieces, style):
1408
- """Render the given version pieces into the requested style."""
1409
- if pieces["error"]:
1410
- return {
1411
- "version": "unknown",
1412
- "full-revisionid": pieces.get("long"),
1413
- "dirty": None,
1414
- "error": pieces["error"],
1415
- "date": None,
1416
- }
1417
-
1418
- if not style or style == "default":
1419
- style = "pep440" # the default
1420
-
1421
- if style == "pep440":
1422
- rendered = render_pep440(pieces)
1423
- elif style == "pep440-pre":
1424
- rendered = render_pep440_pre(pieces)
1425
- elif style == "pep440-post":
1426
- rendered = render_pep440_post(pieces)
1427
- elif style == "pep440-old":
1428
- rendered = render_pep440_old(pieces)
1429
- elif style == "git-describe":
1430
- rendered = render_git_describe(pieces)
1431
- elif style == "git-describe-long":
1432
- rendered = render_git_describe_long(pieces)
1433
- else:
1434
- raise ValueError("unknown style '%s'" % style)
1435
-
1436
- return {
1437
- "version": rendered,
1438
- "full-revisionid": pieces["long"],
1439
- "dirty": pieces["dirty"],
1440
- "error": None,
1441
- "date": pieces.get("date"),
1442
- }
1443
-
1444
-
1445
- class VersioneerBadRootError(Exception):
1446
- """The project root directory is unknown or missing key files."""
1447
-
1448
-
1449
- def get_versions(verbose=False):
1450
- """Get the project version from whatever source is available.
1451
-
1452
- Returns dict with two keys: 'version' and 'full'.
1453
- """
1454
- if "versioneer" in sys.modules:
1455
- # see the discussion in cmdclass.py:get_cmdclass()
1456
- del sys.modules["versioneer"]
1457
-
1458
- root = get_root()
1459
- cfg = get_config_from_root(root)
1460
-
1461
- assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg"
1462
- handlers = HANDLERS.get(cfg.VCS)
1463
- assert handlers, "unrecognized VCS '%s'" % cfg.VCS
1464
- verbose = verbose or cfg.verbose
1465
- assert cfg.versionfile_source is not None, "please set versioneer.versionfile_source"
1466
- assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix"
1467
-
1468
- versionfile_abs = os.path.join(root, cfg.versionfile_source)
1469
-
1470
- # extract version from first of: _version.py, VCS command (e.g. 'git
1471
- # describe'), parentdir. This is meant to work for developers using a
1472
- # source checkout, for users of a tarball created by 'setup.py sdist',
1473
- # and for users of a tarball/zipball created by 'git archive' or github's
1474
- # download-from-tag feature or the equivalent in other VCSes.
1475
-
1476
- get_keywords_f = handlers.get("get_keywords")
1477
- from_keywords_f = handlers.get("keywords")
1478
- if get_keywords_f and from_keywords_f:
1479
- try:
1480
- keywords = get_keywords_f(versionfile_abs)
1481
- ver = from_keywords_f(keywords, cfg.tag_prefix, verbose)
1482
- if verbose:
1483
- print("got version from expanded keyword %s" % ver)
1484
- return ver
1485
- except NotThisMethod:
1486
- pass
1487
-
1488
- try:
1489
- ver = versions_from_file(versionfile_abs)
1490
- if verbose:
1491
- print("got version from file %s %s" % (versionfile_abs, ver))
1492
- return ver
1493
- except NotThisMethod:
1494
- pass
1495
-
1496
- from_vcs_f = handlers.get("pieces_from_vcs")
1497
- if from_vcs_f:
1498
- try:
1499
- pieces = from_vcs_f(cfg.tag_prefix, root, verbose)
1500
- ver = render(pieces, cfg.style)
1501
- if verbose:
1502
- print("got version from VCS %s" % ver)
1503
- return ver
1504
- except NotThisMethod:
1505
- pass
1506
-
1507
- try:
1508
- if cfg.parentdir_prefix:
1509
- ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
1510
- if verbose:
1511
- print("got version from parentdir %s" % ver)
1512
- return ver
1513
- except NotThisMethod:
1514
- pass
1515
-
1516
- if verbose:
1517
- print("unable to compute version")
1518
-
1519
- return {
1520
- "version": "0+unknown",
1521
- "full-revisionid": None,
1522
- "dirty": None,
1523
- "error": "unable to compute version",
1524
- "date": None,
1525
- }
1526
-
1527
-
1528
- def get_version():
1529
- """Get the short version string for this project."""
1530
- return get_versions()["version"]
1531
-
1532
-
1533
- def get_cmdclass():
1534
- """Get the custom setuptools/distutils subclasses used by Versioneer."""
1535
- if "versioneer" in sys.modules:
1536
- del sys.modules["versioneer"]
1537
- # this fixes the "python setup.py develop" case (also 'install' and
1538
- # 'easy_install .'), in which subdependencies of the main project are
1539
- # built (using setup.py bdist_egg) in the same python process. Assume
1540
- # a main project A and a dependency B, which use different versions
1541
- # of Versioneer. A's setup.py imports A's Versioneer, leaving it in
1542
- # sys.modules by the time B's setup.py is executed, causing B to run
1543
- # with the wrong versioneer. Setuptools wraps the sub-dep builds in a
1544
- # sandbox that restores sys.modules to it's pre-build state, so the
1545
- # parent is protected against the child's "import versioneer". By
1546
- # removing ourselves from sys.modules here, before the child build
1547
- # happens, we protect the child from the parent's versioneer too.
1548
- # Also see https://github.com/warner/python-versioneer/issues/52
1549
-
1550
- cmds = {}
1551
-
1552
- # we add "version" to both distutils and setuptools
1553
- from distutils.core import Command
1554
-
1555
- class cmd_version(Command):
1556
- description = "report generated version string"
1557
- user_options = []
1558
- boolean_options = []
1559
-
1560
- def initialize_options(self):
1561
- pass
1562
-
1563
- def finalize_options(self):
1564
- pass
1565
-
1566
- def run(self):
1567
- vers = get_versions(verbose=True)
1568
- print("Version: %s" % vers["version"])
1569
- print(" full-revisionid: %s" % vers.get("full-revisionid"))
1570
- print(" dirty: %s" % vers.get("dirty"))
1571
- print(" date: %s" % vers.get("date"))
1572
- if vers["error"]:
1573
- print(" error: %s" % vers["error"])
1574
-
1575
- cmds["version"] = cmd_version
1576
-
1577
- # we override "build_py" in both distutils and setuptools
1578
- #
1579
- # most invocation pathways end up running build_py:
1580
- # distutils/build -> build_py
1581
- # distutils/install -> distutils/build ->..
1582
- # setuptools/bdist_wheel -> distutils/install ->..
1583
- # setuptools/bdist_egg -> distutils/install_lib -> build_py
1584
- # setuptools/install -> bdist_egg ->..
1585
- # setuptools/develop -> ?
1586
- # pip install:
1587
- # copies source tree to a tempdir before running egg_info/etc
1588
- # if .git isn't copied too, 'git describe' will fail
1589
- # then does setup.py bdist_wheel, or sometimes setup.py install
1590
- # setup.py egg_info -> ?
1591
-
1592
- # we override different "build_py" commands for both environments
1593
- if "setuptools" in sys.modules:
1594
- from setuptools.command.build_py import build_py as _build_py
1595
- else:
1596
- from distutils.command.build_py import build_py as _build_py
1597
-
1598
- class cmd_build_py(_build_py):
1599
- def run(self):
1600
- root = get_root()
1601
- cfg = get_config_from_root(root)
1602
- versions = get_versions()
1603
- _build_py.run(self)
1604
- # now locate _version.py in the new build/ directory and replace
1605
- # it with an updated value
1606
- if cfg.versionfile_build:
1607
- target_versionfile = os.path.join(self.build_lib, cfg.versionfile_build)
1608
- print("UPDATING %s" % target_versionfile)
1609
- write_to_version_file(target_versionfile, versions)
1610
-
1611
- cmds["build_py"] = cmd_build_py
1612
-
1613
- if "cx_Freeze" in sys.modules: # cx_freeze enabled?
1614
- from cx_Freeze.dist import build_exe as _build_exe
1615
-
1616
- # nczeczulin reports that py2exe won't like the pep440-style string
1617
- # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g.
1618
- # setup(console=[{
1619
- # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION
1620
- # "product_version": versioneer.get_version(),
1621
- # ...
1622
-
1623
- class cmd_build_exe(_build_exe):
1624
- def run(self):
1625
- root = get_root()
1626
- cfg = get_config_from_root(root)
1627
- versions = get_versions()
1628
- target_versionfile = cfg.versionfile_source
1629
- print("UPDATING %s" % target_versionfile)
1630
- write_to_version_file(target_versionfile, versions)
1631
-
1632
- _build_exe.run(self)
1633
- os.unlink(target_versionfile)
1634
- with open(cfg.versionfile_source, "w") as f:
1635
- LONG = LONG_VERSION_PY[cfg.VCS]
1636
- f.write(
1637
- LONG
1638
- % {
1639
- "DOLLAR": "$",
1640
- "STYLE": cfg.style,
1641
- "TAG_PREFIX": cfg.tag_prefix,
1642
- "PARENTDIR_PREFIX": cfg.parentdir_prefix,
1643
- "VERSIONFILE_SOURCE": cfg.versionfile_source,
1644
- }
1645
- )
1646
-
1647
- cmds["build_exe"] = cmd_build_exe
1648
- del cmds["build_py"]
1649
-
1650
- if "py2exe" in sys.modules: # py2exe enabled?
1651
- try:
1652
- from py2exe.distutils_buildexe import py2exe as _py2exe # py3
1653
- except ImportError:
1654
- from py2exe.build_exe import py2exe as _py2exe # py2
1655
-
1656
- class cmd_py2exe(_py2exe):
1657
- def run(self):
1658
- root = get_root()
1659
- cfg = get_config_from_root(root)
1660
- versions = get_versions()
1661
- target_versionfile = cfg.versionfile_source
1662
- print("UPDATING %s" % target_versionfile)
1663
- write_to_version_file(target_versionfile, versions)
1664
-
1665
- _py2exe.run(self)
1666
- os.unlink(target_versionfile)
1667
- with open(cfg.versionfile_source, "w") as f:
1668
- LONG = LONG_VERSION_PY[cfg.VCS]
1669
- f.write(
1670
- LONG
1671
- % {
1672
- "DOLLAR": "$",
1673
- "STYLE": cfg.style,
1674
- "TAG_PREFIX": cfg.tag_prefix,
1675
- "PARENTDIR_PREFIX": cfg.parentdir_prefix,
1676
- "VERSIONFILE_SOURCE": cfg.versionfile_source,
1677
- }
1678
- )
1679
-
1680
- cmds["py2exe"] = cmd_py2exe
1681
-
1682
- # we override different "sdist" commands for both environments
1683
- if "setuptools" in sys.modules:
1684
- from setuptools.command.sdist import sdist as _sdist
1685
- else:
1686
- from distutils.command.sdist import sdist as _sdist
1687
-
1688
- class cmd_sdist(_sdist):
1689
- def run(self):
1690
- versions = get_versions()
1691
- self._versioneer_generated_versions = versions
1692
- # unless we update this, the command will keep using the old
1693
- # version
1694
- self.distribution.metadata.version = versions["version"]
1695
- return _sdist.run(self)
1696
-
1697
- def make_release_tree(self, base_dir, files):
1698
- root = get_root()
1699
- cfg = get_config_from_root(root)
1700
- _sdist.make_release_tree(self, base_dir, files)
1701
- # now locate _version.py in the new base_dir directory
1702
- # (remembering that it may be a hardlink) and replace it with an
1703
- # updated value
1704
- target_versionfile = os.path.join(base_dir, cfg.versionfile_source)
1705
- print("UPDATING %s" % target_versionfile)
1706
- write_to_version_file(target_versionfile, self._versioneer_generated_versions)
1707
-
1708
- cmds["sdist"] = cmd_sdist
1709
-
1710
- return cmds
1711
-
1712
-
1713
- CONFIG_ERROR = """
1714
- setup.cfg is missing the necessary Versioneer configuration. You need
1715
- a section like:
1716
-
1717
- [versioneer]
1718
- VCS = git
1719
- style = pep440
1720
- versionfile_source = src/myproject/_version.py
1721
- versionfile_build = myproject/_version.py
1722
- tag_prefix =
1723
- parentdir_prefix = myproject-
1724
-
1725
- You will also need to edit your setup.py to use the results:
1726
-
1727
- import versioneer
1728
- setup(version=versioneer.get_version(),
1729
- cmdclass=versioneer.get_cmdclass(), ...)
1730
-
1731
- Please read the docstring in ./versioneer.py for configuration instructions,
1732
- edit setup.cfg, and re-run the installer or 'python versioneer.py setup'.
1733
- """
1734
-
1735
- SAMPLE_CONFIG = """
1736
- # See the docstring in versioneer.py for instructions. Note that you must
1737
- # re-run 'versioneer.py setup' after changing this section, and commit the
1738
- # resulting files.
1739
-
1740
- [versioneer]
1741
- #VCS = git
1742
- #style = pep440
1743
- #versionfile_source =
1744
- #versionfile_build =
1745
- #tag_prefix =
1746
- #parentdir_prefix =
1747
-
1748
- """
1749
-
1750
- INIT_PY_SNIPPET = """
1751
- from ._version import get_versions
1752
- __version__ = get_versions()['version']
1753
- del get_versions
1754
- """
1755
-
1756
-
1757
- def do_setup():
1758
- """Main VCS-independent setup function for installing Versioneer."""
1759
- root = get_root()
1760
- try:
1761
- cfg = get_config_from_root(root)
1762
- except (EnvironmentError, configparser.NoSectionError, configparser.NoOptionError) as e:
1763
- if isinstance(e, (EnvironmentError, configparser.NoSectionError)):
1764
- print("Adding sample versioneer config to setup.cfg", file=sys.stderr)
1765
- with open(os.path.join(root, "setup.cfg"), "a") as f:
1766
- f.write(SAMPLE_CONFIG)
1767
- print(CONFIG_ERROR, file=sys.stderr)
1768
- return 1
1769
-
1770
- print(" creating %s" % cfg.versionfile_source)
1771
- with open(cfg.versionfile_source, "w") as f:
1772
- LONG = LONG_VERSION_PY[cfg.VCS]
1773
- f.write(
1774
- LONG
1775
- % {
1776
- "DOLLAR": "$",
1777
- "STYLE": cfg.style,
1778
- "TAG_PREFIX": cfg.tag_prefix,
1779
- "PARENTDIR_PREFIX": cfg.parentdir_prefix,
1780
- "VERSIONFILE_SOURCE": cfg.versionfile_source,
1781
- }
1782
- )
1783
-
1784
- ipy = os.path.join(os.path.dirname(cfg.versionfile_source), "__init__.py")
1785
- if os.path.exists(ipy):
1786
- try:
1787
- with open(ipy, "r") as f:
1788
- old = f.read()
1789
- except EnvironmentError:
1790
- old = ""
1791
- if INIT_PY_SNIPPET not in old:
1792
- print(" appending to %s" % ipy)
1793
- with open(ipy, "a") as f:
1794
- f.write(INIT_PY_SNIPPET)
1795
- else:
1796
- print(" %s unmodified" % ipy)
1797
- else:
1798
- print(" %s doesn't exist, ok" % ipy)
1799
- ipy = None
1800
-
1801
- # Make sure both the top-level "versioneer.py" and versionfile_source
1802
- # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so
1803
- # they'll be copied into source distributions. Pip won't be able to
1804
- # install the package without this.
1805
- manifest_in = os.path.join(root, "MANIFEST.in")
1806
- simple_includes = set()
1807
- try:
1808
- with open(manifest_in, "r") as f:
1809
- for line in f:
1810
- if line.startswith("include "):
1811
- for include in line.split()[1:]:
1812
- simple_includes.add(include)
1813
- except EnvironmentError:
1814
- pass
1815
- # That doesn't cover everything MANIFEST.in can do
1816
- # (http://docs.python.org/2/distutils/sourcedist.html#commands), so
1817
- # it might give some false negatives. Appending redundant 'include'
1818
- # lines is safe, though.
1819
- if "versioneer.py" not in simple_includes:
1820
- print(" appending 'versioneer.py' to MANIFEST.in")
1821
- with open(manifest_in, "a") as f:
1822
- f.write("include versioneer.py\n")
1823
- else:
1824
- print(" 'versioneer.py' already in MANIFEST.in")
1825
- if cfg.versionfile_source not in simple_includes:
1826
- print(" appending versionfile_source ('%s') to MANIFEST.in" % cfg.versionfile_source)
1827
- with open(manifest_in, "a") as f:
1828
- f.write("include %s\n" % cfg.versionfile_source)
1829
- else:
1830
- print(" versionfile_source already in MANIFEST.in")
1831
-
1832
- # Make VCS-specific changes. For git, this means creating/changing
1833
- # .gitattributes to mark _version.py for export-subst keyword
1834
- # substitution.
1835
- do_vcs_install(manifest_in, cfg.versionfile_source, ipy)
1836
- return 0
1837
-
1838
-
1839
- def scan_setup_py():
1840
- """Validate the contents of setup.py against Versioneer's expectations."""
1841
- found = set()
1842
- setters = False
1843
- errors = 0
1844
- with open("setup.py", "r") as f:
1845
- for line in f.readlines():
1846
- if "import versioneer" in line:
1847
- found.add("import")
1848
- if "versioneer.get_cmdclass()" in line:
1849
- found.add("cmdclass")
1850
- if "versioneer.get_version()" in line:
1851
- found.add("get_version")
1852
- if "versioneer.VCS" in line:
1853
- setters = True
1854
- if "versioneer.versionfile_source" in line:
1855
- setters = True
1856
- if len(found) != 3:
1857
- print("")
1858
- print("Your setup.py appears to be missing some important items")
1859
- print("(but I might be wrong). Please make sure it has something")
1860
- print("roughly like the following:")
1861
- print("")
1862
- print(" import versioneer")
1863
- print(" setup( version=versioneer.get_version(),")
1864
- print(" cmdclass=versioneer.get_cmdclass(), ...)")
1865
- print("")
1866
- errors += 1
1867
- if setters:
1868
- print("You should remove lines like 'versioneer.VCS = ' and")
1869
- print("'versioneer.versionfile_source = ' . This configuration")
1870
- print("now lives in setup.cfg, and should be removed from setup.py")
1871
- print("")
1872
- errors += 1
1873
- return errors
1874
-
1875
-
1876
- if __name__ == "__main__":
1877
- cmd = sys.argv[1]
1878
- if cmd == "setup":
1879
- errors = do_setup()
1880
- errors += scan_setup_py()
1881
- if errors:
1882
- sys.exit(1)