5
5
# that just contains the computed version number.
6
6
7
7
# This file is released into the public domain. Generated by
8
- # versioneer-0.17 (https://github.com/warner /python-versioneer)
8
+ # versioneer-0.21 (https://github.com/python-versioneer /python-versioneer)
9
9
10
10
"""Git implementation of _version.py."""
11
11
@@ -56,7 +56,7 @@ class NotThisMethod(Exception):
56
56
57
57
58
58
def register_vcs_handler (vcs , method ): # decorator
59
- """Decorator to mark a method as the handler for a particular VCS."""
59
+ """Create decorator to mark a method as the handler of a VCS."""
60
60
61
61
def decorate (f ):
62
62
"""Store f in HANDLERS[vcs][method]."""
@@ -73,20 +73,20 @@ def run_command(
73
73
):
74
74
"""Call the given command(s)."""
75
75
assert isinstance (commands , list )
76
- p = None
77
- for c in commands :
76
+ process = None
77
+ for command in commands :
78
78
try :
79
- dispcmd = str ([c ] + args )
79
+ dispcmd = str ([command ] + args )
80
80
# remember shell=False, so use git.cmd on windows, not just git
81
- p = subprocess .Popen (
82
- [c ] + args ,
81
+ process = subprocess .Popen (
82
+ [command ] + args ,
83
83
cwd = cwd ,
84
84
env = env ,
85
85
stdout = subprocess .PIPE ,
86
86
stderr = (subprocess .PIPE if hide_stderr else None ),
87
87
)
88
88
break
89
- except EnvironmentError :
89
+ except OSError :
90
90
e = sys .exc_info ()[1 ]
91
91
if e .errno == errno .ENOENT :
92
92
continue
@@ -98,15 +98,15 @@ def run_command(
98
98
if verbose :
99
99
print ("unable to find command, tried %s" % (commands ,))
100
100
return None , None
101
- stdout = p .communicate ()[0 ].strip ()
101
+ stdout = process .communicate ()[0 ].strip ()
102
102
if sys .version_info [0 ] >= 3 :
103
103
stdout = stdout .decode ()
104
- if p .returncode != 0 :
104
+ if process .returncode != 0 :
105
105
if verbose :
106
106
print ("unable to run %s (error)" % dispcmd )
107
107
print ("stdout was %s" % stdout )
108
- return None , p .returncode
109
- return stdout , p .returncode
108
+ return None , process .returncode
109
+ return stdout , process .returncode
110
110
111
111
112
112
def versions_from_parentdir (parentdir_prefix , root , verbose ):
@@ -118,7 +118,7 @@ def versions_from_parentdir(parentdir_prefix, root, verbose):
118
118
"""
119
119
rootdirs = []
120
120
121
- for i in range (3 ):
121
+ for _ in range (3 ):
122
122
dirname = os .path .basename (root )
123
123
if dirname .startswith (parentdir_prefix ):
124
124
return {
@@ -128,9 +128,8 @@ def versions_from_parentdir(parentdir_prefix, root, verbose):
128
128
"error" : None ,
129
129
"date" : None ,
130
130
}
131
- else :
132
- rootdirs .append (root )
133
- root = os .path .dirname (root ) # up a level
131
+ rootdirs .append (root )
132
+ root = os .path .dirname (root ) # up a level
134
133
135
134
if verbose :
136
135
print (
@@ -149,33 +148,36 @@ def git_get_keywords(versionfile_abs):
149
148
# _version.py.
150
149
keywords = {}
151
150
try :
152
- f = open (versionfile_abs , "r" )
153
- for line in f .readlines ():
154
- if line .strip ().startswith ("git_refnames =" ):
155
- mo = re .search (r'=\s*"(.*)"' , line )
156
- if mo :
157
- keywords ["refnames" ] = mo .group (1 )
158
- if line .strip ().startswith ("git_full =" ):
159
- mo = re .search (r'=\s*"(.*)"' , line )
160
- if mo :
161
- keywords ["full" ] = mo .group (1 )
162
- if line .strip ().startswith ("git_date =" ):
163
- mo = re .search (r'=\s*"(.*)"' , line )
164
- if mo :
165
- keywords ["date" ] = mo .group (1 )
166
- f .close ()
167
- except EnvironmentError :
151
+ with open (versionfile_abs , "r" ) as fobj :
152
+ for line in fobj :
153
+ if line .strip ().startswith ("git_refnames =" ):
154
+ mo = re .search (r'=\s*"(.*)"' , line )
155
+ if mo :
156
+ keywords ["refnames" ] = mo .group (1 )
157
+ if line .strip ().startswith ("git_full =" ):
158
+ mo = re .search (r'=\s*"(.*)"' , line )
159
+ if mo :
160
+ keywords ["full" ] = mo .group (1 )
161
+ if line .strip ().startswith ("git_date =" ):
162
+ mo = re .search (r'=\s*"(.*)"' , line )
163
+ if mo :
164
+ keywords ["date" ] = mo .group (1 )
165
+ except OSError :
168
166
pass
169
167
return keywords
170
168
171
169
172
170
@register_vcs_handler ("git" , "keywords" )
173
171
def git_versions_from_keywords (keywords , tag_prefix , verbose ):
174
172
"""Get version information from git keywords."""
175
- if not keywords :
176
- raise NotThisMethod ("no keywords at all, weird " )
173
+ if "refnames" not in keywords :
174
+ raise NotThisMethod ("Short version file found " )
177
175
date = keywords .get ("date" )
178
176
if date is not None :
177
+ # Use only the last line. Previous lines may contain GPG signature
178
+ # information.
179
+ date = date .splitlines ()[- 1 ]
180
+
179
181
# git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant
180
182
# datestamp. However we prefer "%ci" (which expands to an "ISO-8601
181
183
# -like" string, which we must then edit to make compliant), because
@@ -188,11 +190,11 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
188
190
if verbose :
189
191
print ("keywords are unexpanded, not using" )
190
192
raise NotThisMethod ("unexpanded keywords, not a git-archive tarball" )
191
- refs = set ([ r .strip () for r in refnames .strip ("()" ).split ("," )] )
193
+ refs = set (r .strip () for r in refnames .strip ("()" ).split ("," ))
192
194
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
193
195
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
194
196
TAG = "tag: "
195
- tags = set ([ r [len (TAG ) :] for r in refs if r .startswith (TAG )] )
197
+ tags = set (r [len (TAG ) :] for r in refs if r .startswith (TAG ))
196
198
if not tags :
197
199
# Either we're using git < 1.8.3, or there really are no tags. We use
198
200
# a heuristic: assume all version tags have a digit. The old git %d
@@ -201,7 +203,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
201
203
# between branches and tags. By ignoring refnames without digits, we
202
204
# filter out many common branch names like "release" and
203
205
# "stabilization", as well as "HEAD" and "master".
204
- tags = set ([ r for r in refs if re .search (r"\d" , r )] )
206
+ tags = set (r for r in refs if re .search (r"\d" , r ))
205
207
if verbose :
206
208
print ("discarding '%s', no digits" % "," .join (refs - tags ))
207
209
if verbose :
@@ -210,6 +212,11 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
210
212
# sorting will prefer e.g. "2.0" over "2.0rc1"
211
213
if ref .startswith (tag_prefix ):
212
214
r = ref [len (tag_prefix ) :]
215
+ # Filter out refs that exactly match prefix or that don't start
216
+ # with a number once the prefix is stripped (mostly a concern
217
+ # when prefix is '')
218
+ if not re .match (r"\d" , r ):
219
+ continue
213
220
if verbose :
214
221
print ("picking %s" % r )
215
222
return {
@@ -232,18 +239,20 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
232
239
233
240
234
241
@register_vcs_handler ("git" , "pieces_from_vcs" )
235
- def git_pieces_from_vcs (tag_prefix , root , verbose , run_command = run_command ):
242
+ def git_pieces_from_vcs (tag_prefix , root , verbose , runner = run_command ):
236
243
"""Get version from 'git describe' in the root of the source tree.
237
244
238
245
This only gets called if the git-archive 'subst' keywords were *not*
239
246
expanded, and _version.py hasn't already been rewritten with a short
240
247
version string, meaning we're inside a checked out source tree.
241
248
"""
242
249
GITS = ["git" ]
250
+ TAG_PREFIX_REGEX = "*"
243
251
if sys .platform == "win32" :
244
252
GITS = ["git.cmd" , "git.exe" ]
253
+ TAG_PREFIX_REGEX = r"\*"
245
254
246
- out , rc = run_command (
255
+ _ , rc = runner (
247
256
GITS , ["rev-parse" , "--git-dir" ], cwd = root , hide_stderr = True
248
257
)
249
258
if rc != 0 :
@@ -253,7 +262,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
253
262
254
263
# if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
255
264
# if there isn't one, this yields HEX[-dirty] (no NUM)
256
- describe_out , rc = run_command (
265
+ describe_out , rc = runner (
257
266
GITS ,
258
267
[
259
268
"describe" ,
@@ -262,15 +271,15 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
262
271
"--always" ,
263
272
"--long" ,
264
273
"--match" ,
265
- "%s* " % tag_prefix ,
274
+ "%s%s " % ( tag_prefix , TAG_PREFIX_REGEX ) ,
266
275
],
267
276
cwd = root ,
268
277
)
269
278
# --long was added in git-1.5.5
270
279
if describe_out is None :
271
280
raise NotThisMethod ("'git describe' failed" )
272
281
describe_out = describe_out .strip ()
273
- full_out , rc = run_command (GITS , ["rev-parse" , "HEAD" ], cwd = root )
282
+ full_out , rc = runner (GITS , ["rev-parse" , "HEAD" ], cwd = root )
274
283
if full_out is None :
275
284
raise NotThisMethod ("'git rev-parse' failed" )
276
285
full_out = full_out .strip ()
@@ -280,6 +289,40 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
280
289
pieces ["short" ] = full_out [:7 ] # maybe improved later
281
290
pieces ["error" ] = None
282
291
292
+ branch_name , rc = runner (
293
+ GITS , ["rev-parse" , "--abbrev-ref" , "HEAD" ], cwd = root
294
+ )
295
+ # --abbrev-ref was added in git-1.6.3
296
+ if rc != 0 or branch_name is None :
297
+ raise NotThisMethod ("'git rev-parse --abbrev-ref' returned error" )
298
+ branch_name = branch_name .strip ()
299
+
300
+ if branch_name == "HEAD" :
301
+ # If we aren't exactly on a branch, pick a branch which represents
302
+ # the current commit. If all else fails, we are on a branchless
303
+ # commit.
304
+ branches , rc = runner (GITS , ["branch" , "--contains" ], cwd = root )
305
+ # --contains was added in git-1.5.4
306
+ if rc != 0 or branches is None :
307
+ raise NotThisMethod ("'git branch --contains' returned error" )
308
+ branches = branches .split ("\n " )
309
+
310
+ # Remove the first line if we're running detached
311
+ if "(" in branches [0 ]:
312
+ branches .pop (0 )
313
+
314
+ # Strip off the leading "* " from the list of branches.
315
+ branches = [branch [2 :] for branch in branches ]
316
+ if "master" in branches :
317
+ branch_name = "master"
318
+ elif not branches :
319
+ branch_name = None
320
+ else :
321
+ # Pick the first branch that is returned. Good or bad.
322
+ branch_name = branches [0 ]
323
+
324
+ pieces ["branch" ] = branch_name
325
+
283
326
# parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
284
327
# TAG might have hyphens.
285
328
git_describe = describe_out
@@ -324,15 +367,16 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
324
367
else :
325
368
# HEX: no tags
326
369
pieces ["closest-tag" ] = None
327
- count_out , rc = run_command (
328
- GITS , ["rev-list" , "HEAD" , "--count" ], cwd = root
329
- )
370
+ count_out , rc = runner (GITS , ["rev-list" , "HEAD" , "--count" ], cwd = root )
330
371
pieces ["distance" ] = int (count_out ) # total number of commits
331
372
332
373
# commit date: see ISO-8601 comment in git_versions_from_keywords()
333
- date = run_command (GITS , ["show" , "-s" , "--format=%ci" , "HEAD" ], cwd = root )[
374
+ date = runner (GITS , ["show" , "-s" , "--format=%ci" , "HEAD" ], cwd = root )[
334
375
0
335
376
].strip ()
377
+ # Use only the last line. Previous lines may contain GPG signature
378
+ # information.
379
+ date = date .splitlines ()[- 1 ]
336
380
pieces ["date" ] = date .strip ().replace (" " , "T" , 1 ).replace (" " , "" , 1 )
337
381
338
382
return pieces
@@ -369,19 +413,71 @@ def render_pep440(pieces):
369
413
return rendered
370
414
371
415
372
- def render_pep440_pre (pieces ):
373
- """TAG[.post.devDISTANCE] -- No -dirty.
416
+ def render_pep440_branch (pieces ):
417
+ """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] .
418
+
419
+ The ".dev0" means not master branch. Note that .dev0 sorts backwards
420
+ (a feature branch will appear "older" than the master branch).
374
421
375
422
Exceptions:
376
- 1: no tags. 0.post.devDISTANCE
423
+ 1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty]
377
424
"""
378
425
if pieces ["closest-tag" ]:
379
426
rendered = pieces ["closest-tag" ]
427
+ if pieces ["distance" ] or pieces ["dirty" ]:
428
+ if pieces ["branch" ] != "master" :
429
+ rendered += ".dev0"
430
+ rendered += plus_or_dot (pieces )
431
+ rendered += "%d.g%s" % (pieces ["distance" ], pieces ["short" ])
432
+ if pieces ["dirty" ]:
433
+ rendered += ".dirty"
434
+ else :
435
+ # exception #1
436
+ rendered = "0"
437
+ if pieces ["branch" ] != "master" :
438
+ rendered += ".dev0"
439
+ rendered += "+untagged.%d.g%s" % (pieces ["distance" ], pieces ["short" ])
440
+ if pieces ["dirty" ]:
441
+ rendered += ".dirty"
442
+ return rendered
443
+
444
+
445
+ def pep440_split_post (ver ):
446
+ """Split pep440 version string at the post-release segment.
447
+
448
+ Returns the release segments before the post-release and the
449
+ post-release version number (or -1 if no post-release segment is present).
450
+ """
451
+ vc = str .split (ver , ".post" )
452
+ return vc [0 ], int (vc [1 ] or 0 ) if len (vc ) == 2 else None
453
+
454
+
455
+ def render_pep440_pre (pieces ):
456
+ """TAG[.postN.devDISTANCE] -- No -dirty.
457
+
458
+ Exceptions:
459
+ 1: no tags. 0.post0.devDISTANCE
460
+ """
461
+ if pieces ["closest-tag" ]:
380
462
if pieces ["distance" ]:
381
- rendered += ".post.dev%d" % pieces ["distance" ]
463
+ # update the post release segment
464
+ tag_version , post_version = pep440_split_post (
465
+ pieces ["closest-tag" ]
466
+ )
467
+ rendered = tag_version
468
+ if post_version is not None :
469
+ rendered += ".post%d.dev%d" % (
470
+ post_version + 1 ,
471
+ pieces ["distance" ],
472
+ )
473
+ else :
474
+ rendered += ".post0.dev%d" % (pieces ["distance" ])
475
+ else :
476
+ # no commits, use the tag as the version
477
+ rendered = pieces ["closest-tag" ]
382
478
else :
383
479
# exception #1
384
- rendered = "0.post .dev%d" % pieces ["distance" ]
480
+ rendered = "0.post0 .dev%d" % pieces ["distance" ]
385
481
return rendered
386
482
387
483
@@ -412,12 +508,41 @@ def render_pep440_post(pieces):
412
508
return rendered
413
509
414
510
511
+ def render_pep440_post_branch (pieces ):
512
+ """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] .
513
+
514
+ The ".dev0" means not master branch.
515
+
516
+ Exceptions:
517
+ 1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty]
518
+ """
519
+ if pieces ["closest-tag" ]:
520
+ rendered = pieces ["closest-tag" ]
521
+ if pieces ["distance" ] or pieces ["dirty" ]:
522
+ rendered += ".post%d" % pieces ["distance" ]
523
+ if pieces ["branch" ] != "master" :
524
+ rendered += ".dev0"
525
+ rendered += plus_or_dot (pieces )
526
+ rendered += "g%s" % pieces ["short" ]
527
+ if pieces ["dirty" ]:
528
+ rendered += ".dirty"
529
+ else :
530
+ # exception #1
531
+ rendered = "0.post%d" % pieces ["distance" ]
532
+ if pieces ["branch" ] != "master" :
533
+ rendered += ".dev0"
534
+ rendered += "+g%s" % pieces ["short" ]
535
+ if pieces ["dirty" ]:
536
+ rendered += ".dirty"
537
+ return rendered
538
+
539
+
415
540
def render_pep440_old (pieces ):
416
541
"""TAG[.postDISTANCE[.dev0]] .
417
542
418
543
The ".dev0" means dirty.
419
544
420
- Eexceptions :
545
+ Exceptions :
421
546
1: no tags. 0.postDISTANCE[.dev0]
422
547
"""
423
548
if pieces ["closest-tag" ]:
@@ -490,10 +615,14 @@ def render(pieces, style):
490
615
491
616
if style == "pep440" :
492
617
rendered = render_pep440 (pieces )
618
+ elif style == "pep440-branch" :
619
+ rendered = render_pep440_branch (pieces )
493
620
elif style == "pep440-pre" :
494
621
rendered = render_pep440_pre (pieces )
495
622
elif style == "pep440-post" :
496
623
rendered = render_pep440_post (pieces )
624
+ elif style == "pep440-post-branch" :
625
+ rendered = render_pep440_post_branch (pieces )
497
626
elif style == "pep440-old" :
498
627
rendered = render_pep440_old (pieces )
499
628
elif style == "git-describe" :
@@ -534,7 +663,7 @@ def get_versions():
534
663
# versionfile_source is the relative path from the top of the source
535
664
# tree (where the .git directory might live) to this file. Invert
536
665
# this to find the root from __file__.
537
- for i in cfg .versionfile_source .split ("/" ):
666
+ for _ in cfg .versionfile_source .split ("/" ):
538
667
root = os .path .dirname (root )
539
668
except NameError :
540
669
return {
0 commit comments