1
-
2
1
# This file helps to compute a version number in source trees obtained from
3
2
# git-archive tarball (such as those provided by githubs download-from-tag
4
3
# feature). Distribution tarballs (built by setup.py sdist) and build
11
10
"""Git implementation of _version.py."""
12
11
13
12
import errno
13
+ import functools
14
14
import os
15
15
import re
16
16
import subprocess
17
17
import sys
18
+
18
19
from typing import Callable , Dict
19
- import functools
20
20
21
21
22
22
def get_keywords ():
@@ -60,17 +60,18 @@ class NotThisMethod(Exception):
60
60
61
61
def register_vcs_handler (vcs , method ): # decorator
62
62
"""Create decorator to mark a method as the handler of a VCS."""
63
+
63
64
def decorate (f ):
64
65
"""Store f in HANDLERS[vcs][method]."""
65
66
if vcs not in HANDLERS :
66
67
HANDLERS [vcs ] = {}
67
68
HANDLERS [vcs ][method ] = f
68
69
return f
70
+
69
71
return decorate
70
72
71
73
72
- def run_command (commands , args , cwd = None , verbose = False , hide_stderr = False ,
73
- env = None ):
74
+ def run_command (commands , args , cwd = None , verbose = False , hide_stderr = False , env = None ):
74
75
"""Call the given command(s)."""
75
76
assert isinstance (commands , list )
76
77
process = None
@@ -86,10 +87,14 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
86
87
try :
87
88
dispcmd = str ([command ] + args )
88
89
# remember shell=False, so use git.cmd on windows, not just git
89
- process = subprocess .Popen ([command ] + args , cwd = cwd , env = env ,
90
- stdout = subprocess .PIPE ,
91
- stderr = (subprocess .PIPE if hide_stderr
92
- else None ), ** popen_kwargs )
90
+ process = subprocess .Popen (
91
+ [command ] + args ,
92
+ cwd = cwd ,
93
+ env = env ,
94
+ stdout = subprocess .PIPE ,
95
+ stderr = (subprocess .PIPE if hide_stderr else None ),
96
+ ** popen_kwargs ,
97
+ )
93
98
break
94
99
except OSError :
95
100
e = sys .exc_info ()[1 ]
@@ -101,7 +106,7 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
101
106
return None , None
102
107
else :
103
108
if verbose :
104
- print ("unable to find command, tried %s" % ( commands ,) )
109
+ print (f "unable to find command, tried { commands } " )
105
110
return None , None
106
111
stdout = process .communicate ()[0 ].strip ().decode ()
107
112
if process .returncode != 0 :
@@ -124,15 +129,21 @@ def versions_from_parentdir(parentdir_prefix, root, verbose):
124
129
for _ in range (3 ):
125
130
dirname = os .path .basename (root )
126
131
if dirname .startswith (parentdir_prefix ):
127
- return {"version" : dirname [len (parentdir_prefix ):],
128
- "full-revisionid" : None ,
129
- "dirty" : False , "error" : None , "date" : None }
132
+ return {
133
+ "version" : dirname [len (parentdir_prefix ) :],
134
+ "full-revisionid" : None ,
135
+ "dirty" : False ,
136
+ "error" : None ,
137
+ "date" : None ,
138
+ }
130
139
rootdirs .append (root )
131
140
root = os .path .dirname (root ) # up a level
132
141
133
142
if verbose :
134
- print ("Tried directories %s but none started with prefix %s" %
135
- (str (rootdirs ), parentdir_prefix ))
143
+ print (
144
+ "Tried directories %s but none started with prefix %s"
145
+ % (str (rootdirs ), parentdir_prefix )
146
+ )
136
147
raise NotThisMethod ("rootdir doesn't start with parentdir_prefix" )
137
148
138
149
@@ -145,7 +156,7 @@ def git_get_keywords(versionfile_abs):
145
156
# _version.py.
146
157
keywords = {}
147
158
try :
148
- with open (versionfile_abs , "r" ) as fobj :
159
+ with open (versionfile_abs ) as fobj :
149
160
for line in fobj :
150
161
if line .strip ().startswith ("git_refnames =" ):
151
162
mo = re .search (r'=\s*"(.*)"' , line )
@@ -191,7 +202,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
191
202
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
192
203
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
193
204
TAG = "tag: "
194
- tags = {r [len (TAG ):] for r in refs if r .startswith (TAG )}
205
+ tags = {r [len (TAG ) :] for r in refs if r .startswith (TAG )}
195
206
if not tags :
196
207
# Either we're using git < 1.8.3, or there really are no tags. We use
197
208
# a heuristic: assume all version tags have a digit. The old git %d
@@ -200,32 +211,39 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
200
211
# between branches and tags. By ignoring refnames without digits, we
201
212
# filter out many common branch names like "release" and
202
213
# "stabilization", as well as "HEAD" and "master".
203
- tags = {r for r in refs if re .search (r'\d' , r )}
214
+ tags = {r for r in refs if re .search (r"\d" , r )}
204
215
if verbose :
205
216
print ("discarding '%s', no digits" % "," .join (refs - tags ))
206
217
if verbose :
207
218
print ("likely tags: %s" % "," .join (sorted (tags )))
208
219
for ref in sorted (tags ):
209
220
# sorting will prefer e.g. "2.0" over "2.0rc1"
210
221
if ref .startswith (tag_prefix ):
211
- r = ref [len (tag_prefix ):]
222
+ r = ref [len (tag_prefix ) :]
212
223
# Filter out refs that exactly match prefix or that don't start
213
224
# with a number once the prefix is stripped (mostly a concern
214
225
# when prefix is '')
215
- if not re .match (r'\d' , r ):
226
+ if not re .match (r"\d" , r ):
216
227
continue
217
228
if verbose :
218
229
print ("picking %s" % r )
219
- return {"version" : r ,
220
- "full-revisionid" : keywords ["full" ].strip (),
221
- "dirty" : False , "error" : None ,
222
- "date" : date }
230
+ return {
231
+ "version" : r ,
232
+ "full-revisionid" : keywords ["full" ].strip (),
233
+ "dirty" : False ,
234
+ "error" : None ,
235
+ "date" : date ,
236
+ }
223
237
# no suitable tags, so version is "0+unknown", but full hex is still there
224
238
if verbose :
225
239
print ("no suitable tags, using unknown + full revision id" )
226
- return {"version" : "0+unknown" ,
227
- "full-revisionid" : keywords ["full" ].strip (),
228
- "dirty" : False , "error" : "no suitable tags" , "date" : None }
240
+ return {
241
+ "version" : "0+unknown" ,
242
+ "full-revisionid" : keywords ["full" ].strip (),
243
+ "dirty" : False ,
244
+ "error" : "no suitable tags" ,
245
+ "date" : None ,
246
+ }
229
247
230
248
231
249
@register_vcs_handler ("git" , "pieces_from_vcs" )
@@ -247,19 +265,27 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command):
247
265
env .pop ("GIT_DIR" , None )
248
266
runner = functools .partial (runner , env = env )
249
267
250
- _ , rc = runner (GITS , ["rev-parse" , "--git-dir" ], cwd = root ,
251
- hide_stderr = True )
268
+ _ , rc = runner (GITS , ["rev-parse" , "--git-dir" ], cwd = root , hide_stderr = True )
252
269
if rc != 0 :
253
270
if verbose :
254
271
print ("Directory %s not under git control" % root )
255
272
raise NotThisMethod ("'git rev-parse --git-dir' returned error" )
256
273
257
274
# if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
258
275
# if there isn't one, this yields HEX[-dirty] (no NUM)
259
- describe_out , rc = runner (GITS , [
260
- "describe" , "--tags" , "--dirty" , "--always" , "--long" ,
261
- "--match" , f"{ tag_prefix } [[:digit:]]*"
262
- ], cwd = root )
276
+ describe_out , rc = runner (
277
+ GITS ,
278
+ [
279
+ "describe" ,
280
+ "--tags" ,
281
+ "--dirty" ,
282
+ "--always" ,
283
+ "--long" ,
284
+ "--match" ,
285
+ f"{ tag_prefix } [[:digit:]]*" ,
286
+ ],
287
+ cwd = root ,
288
+ )
263
289
# --long was added in git-1.5.5
264
290
if describe_out is None :
265
291
raise NotThisMethod ("'git describe' failed" )
@@ -274,8 +300,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command):
274
300
pieces ["short" ] = full_out [:7 ] # maybe improved later
275
301
pieces ["error" ] = None
276
302
277
- branch_name , rc = runner (GITS , ["rev-parse" , "--abbrev-ref" , "HEAD" ],
278
- cwd = root )
303
+ branch_name , rc = runner (GITS , ["rev-parse" , "--abbrev-ref" , "HEAD" ], cwd = root )
279
304
# --abbrev-ref was added in git-1.6.3
280
305
if rc != 0 or branch_name is None :
281
306
raise NotThisMethod ("'git rev-parse --abbrev-ref' returned error" )
@@ -315,17 +340,16 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command):
315
340
dirty = git_describe .endswith ("-dirty" )
316
341
pieces ["dirty" ] = dirty
317
342
if dirty :
318
- git_describe = git_describe [:git_describe .rindex ("-dirty" )]
343
+ git_describe = git_describe [: git_describe .rindex ("-dirty" )]
319
344
320
345
# now we have TAG-NUM-gHEX or HEX
321
346
322
347
if "-" in git_describe :
323
348
# TAG-NUM-gHEX
324
- mo = re .search (r' ^(.+)-(\d+)-g([0-9a-f]+)$' , git_describe )
349
+ mo = re .search (r" ^(.+)-(\d+)-g([0-9a-f]+)$" , git_describe )
325
350
if not mo :
326
351
# unparsable. Maybe git-describe is misbehaving?
327
- pieces ["error" ] = ("unable to parse git-describe output: '%s'"
328
- % describe_out )
352
+ pieces ["error" ] = "unable to parse git-describe output: '%s'" % describe_out
329
353
return pieces
330
354
331
355
# tag
@@ -334,10 +358,9 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command):
334
358
if verbose :
335
359
fmt = "tag '%s' doesn't start with prefix '%s'"
336
360
print (fmt % (full_tag , tag_prefix ))
337
- pieces ["error" ] = ("tag '%s' doesn't start with prefix '%s'"
338
- % (full_tag , tag_prefix ))
361
+ pieces ["error" ] = f"tag '{ full_tag } ' doesn't start with prefix '{ tag_prefix } '"
339
362
return pieces
340
- pieces ["closest-tag" ] = full_tag [len (tag_prefix ):]
363
+ pieces ["closest-tag" ] = full_tag [len (tag_prefix ) :]
341
364
342
365
# distance: number of commits since tag
343
366
pieces ["distance" ] = int (mo .group (2 ))
@@ -386,8 +409,7 @@ def render_pep440(pieces):
386
409
rendered += ".dirty"
387
410
else :
388
411
# exception #1
389
- rendered = "0+untagged.%d.g%s" % (pieces ["distance" ],
390
- pieces ["short" ])
412
+ rendered = "0+untagged.%d.g%s" % (pieces ["distance" ], pieces ["short" ])
391
413
if pieces ["dirty" ]:
392
414
rendered += ".dirty"
393
415
return rendered
@@ -416,8 +438,7 @@ def render_pep440_branch(pieces):
416
438
rendered = "0"
417
439
if pieces ["branch" ] != "master" :
418
440
rendered += ".dev0"
419
- rendered += "+untagged.%d.g%s" % (pieces ["distance" ],
420
- pieces ["short" ])
441
+ rendered += "+untagged.%d.g%s" % (pieces ["distance" ], pieces ["short" ])
421
442
if pieces ["dirty" ]:
422
443
rendered += ".dirty"
423
444
return rendered
@@ -578,11 +599,13 @@ def render_git_describe_long(pieces):
578
599
def render (pieces , style ):
579
600
"""Render the given version pieces into the requested style."""
580
601
if pieces ["error" ]:
581
- return {"version" : "unknown" ,
582
- "full-revisionid" : pieces .get ("long" ),
583
- "dirty" : None ,
584
- "error" : pieces ["error" ],
585
- "date" : None }
602
+ return {
603
+ "version" : "unknown" ,
604
+ "full-revisionid" : pieces .get ("long" ),
605
+ "dirty" : None ,
606
+ "error" : pieces ["error" ],
607
+ "date" : None ,
608
+ }
586
609
587
610
if not style or style == "default" :
588
611
style = "pep440" # the default
@@ -606,9 +629,13 @@ def render(pieces, style):
606
629
else :
607
630
raise ValueError ("unknown style '%s'" % style )
608
631
609
- return {"version" : rendered , "full-revisionid" : pieces ["long" ],
610
- "dirty" : pieces ["dirty" ], "error" : None ,
611
- "date" : pieces .get ("date" )}
632
+ return {
633
+ "version" : rendered ,
634
+ "full-revisionid" : pieces ["long" ],
635
+ "dirty" : pieces ["dirty" ],
636
+ "error" : None ,
637
+ "date" : pieces .get ("date" ),
638
+ }
612
639
613
640
614
641
def get_versions ():
@@ -622,8 +649,7 @@ def get_versions():
622
649
verbose = cfg .verbose
623
650
624
651
try :
625
- return git_versions_from_keywords (get_keywords (), cfg .tag_prefix ,
626
- verbose )
652
+ return git_versions_from_keywords (get_keywords (), cfg .tag_prefix , verbose )
627
653
except NotThisMethod :
628
654
pass
629
655
@@ -632,13 +658,16 @@ def get_versions():
632
658
# versionfile_source is the relative path from the top of the source
633
659
# tree (where the .git directory might live) to this file. Invert
634
660
# this to find the root from __file__.
635
- for _ in cfg .versionfile_source .split ('/' ):
661
+ for _ in cfg .versionfile_source .split ("/" ):
636
662
root = os .path .dirname (root )
637
663
except NameError :
638
- return {"version" : "0+unknown" , "full-revisionid" : None ,
639
- "dirty" : None ,
640
- "error" : "unable to find root of source tree" ,
641
- "date" : None }
664
+ return {
665
+ "version" : "0+unknown" ,
666
+ "full-revisionid" : None ,
667
+ "dirty" : None ,
668
+ "error" : "unable to find root of source tree" ,
669
+ "date" : None ,
670
+ }
642
671
643
672
try :
644
673
pieces = git_pieces_from_vcs (cfg .tag_prefix , root , verbose )
@@ -652,6 +681,10 @@ def get_versions():
652
681
except NotThisMethod :
653
682
pass
654
683
655
- return {"version" : "0+unknown" , "full-revisionid" : None ,
656
- "dirty" : None ,
657
- "error" : "unable to compute version" , "date" : None }
684
+ return {
685
+ "version" : "0+unknown" ,
686
+ "full-revisionid" : None ,
687
+ "dirty" : None ,
688
+ "error" : "unable to compute version" ,
689
+ "date" : None ,
690
+ }
0 commit comments