1+ # -*- coding: utf-8 -*-
2+ # This file is part of 'miniver': https://github.com/jbweston/miniver
3+ #
14from collections import namedtuple
25import os
36import subprocess
4- import sys
57
6- from distutils .command .build import build as build_orig
8+ from distutils .command .build_py import build_py as build_py_orig
79from setuptools .command .sdist import sdist as sdist_orig
810
911Version = namedtuple ('Version' , ('release' , 'dev' , 'labels' ))
1921
2022
2123def get_version (version_file = STATIC_VERSION_FILE ):
22- version_info = {}
23- with open (os .path .join (package_root , version_file ), 'rb' ) as f :
24- exec (f .read (), {}, version_info )
24+ version_info = get_static_version_info (version_file )
2525 version = version_info ['version' ]
26- version_is_from_git = (version == "__use_git__" )
27- if version_is_from_git :
26+ if version == "__use_git__" :
2827 version = get_version_from_git ()
2928 if not version :
3029 version = get_version_from_git_archive (version_info )
3130 if not version :
3231 version = Version ("unknown" , None , None )
33- return semver_format (version )
32+ return pep440_format (version )
3433 else :
3534 return version
3635
3736
38- def semver_format (version_info ):
37+ def get_static_version_info (version_file = STATIC_VERSION_FILE ):
38+ version_info = {}
39+ with open (os .path .join (package_root , version_file ), 'rb' ) as f :
40+ exec (f .read (), {}, version_info )
41+ return version_info
42+
43+
44+ def version_is_from_git (version_file = STATIC_VERSION_FILE ):
45+ return get_static_version_info (version_file )['version' ] == '__use_git__'
46+
47+
48+ def pep440_format (version_info ):
3949 release , dev , labels = version_info
4050
4151 version_parts = [release ]
4252 if dev :
43- if release .endswith ('-dev' ):
53+ if release .endswith ('-dev' ) or release . endswith ( '.dev' ) :
4454 version_parts .append (dev )
45- else :
46- version_parts .append ('- dev{}' .format (dev ))
55+ else : # prefer PEP440 over strict adhesion to semver
56+ version_parts .append ('. dev{}' .format (dev ))
4757
4858 if labels :
4959 version_parts .append ('+' )
@@ -64,26 +74,42 @@ def get_version_from_git():
6474 if not os .path .samefile (p .communicate ()[0 ].decode ().rstrip ('\n ' ),
6575 distr_root ):
6676 # The top-level directory of the current Git repository is not the same
67- # as the root directory of the Kwant distribution: do not extract the
77+ # as the root directory of the distribution: do not extract the
6878 # version from Git.
6979 return
7080
7181 # git describe --first-parent does not take into account tags from branches
72- # that were merged-in.
82+ # that were merged-in. The '--long' flag gets us the 'dev' version and
83+ # git hash, '--always' returns the git hash even if there are no tags.
7384 for opts in [['--first-parent' ], []]:
7485 try :
75- p = subprocess .Popen (['git' , 'describe' , '--long' ] + opts ,
76- cwd = distr_root ,
77- stdout = subprocess .PIPE , stderr = subprocess .PIPE )
86+ p = subprocess .Popen (
87+ ['git' , 'describe' , '--long' , '--always' ] + opts ,
88+ cwd = distr_root ,
89+ stdout = subprocess .PIPE , stderr = subprocess .PIPE )
7890 except OSError :
7991 return
8092 if p .wait () == 0 :
8193 break
8294 else :
8395 return
84- description = p .communicate ()[0 ].decode ().strip ('v' ).rstrip ('\n ' )
8596
86- release , dev , git = description .rsplit ('-' , 2 )
97+ description = (
98+ p .communicate ()[0 ]
99+ .decode ()
100+ .strip ('v' ) # Tags can have a leading 'v', but the version should not
101+ .rstrip ('\n ' )
102+ .rsplit ('-' , 2 ) # Split the latest tag, commits since tag, and hash
103+ )
104+
105+ try :
106+ release , dev , git = description
107+ except ValueError : # No tags, only the git hash
108+ # prepend 'g' to match with format returned by 'git describe'
109+ git = 'g{}' .format (* description )
110+ release = 'unknown'
111+ dev = None
112+
87113 labels = []
88114 if dev == "0" :
89115 dev = None
@@ -93,7 +119,7 @@ def get_version_from_git():
93119 try :
94120 p = subprocess .Popen (['git' , 'diff' , '--quiet' ], cwd = distr_root )
95121 except OSError :
96- labels .append ('confused' ) # This should never happen.
122+ labels .append ('confused' ) # This should never happen.
97123 else :
98124 if p .wait () == 1 :
99125 labels .append ('dirty' )
@@ -126,14 +152,15 @@ def get_version_from_git_archive(version_info):
126152 release , * _ = sorted (version_tags ) # prefer e.g. "2.0" over "2.0rc1"
127153 return Version (release , dev = None , labels = None )
128154 else :
129- return Version ('unknown' , dev = None , labels = [f'g{ git_hash } ' ])
155+ return Version ('unknown' , dev = None , labels = ['g{}' .format (git_hash )])
156+
130157
158+ __version__ = get_version ()
131159
132- version = get_version ()
133160
134161# The following section defines a module global 'cmdclass',
135162# which can be used from setup.py. The 'package_name' and
136- # 'version ' module globals are used (but not modified).
163+ # '__version__ ' module globals are used (but not modified).
137164
138165def _write_version (fname ):
139166 # This could be a hard link, so try to delete it first. Is there any way
@@ -144,10 +171,10 @@ def _write_version(fname):
144171 pass
145172 with open (fname , 'w' ) as f :
146173 f .write ("# This file has been created by setup.py.\n "
147- "version = '{}'\n " .format (version ))
174+ "version = '{}'\n " .format (__version__ ))
148175
149176
150- class _build ( build_orig ):
177+ class _build_py ( build_py_orig ):
151178 def run (self ):
152179 super ().run ()
153180 _write_version (os .path .join (self .build_lib , package_name ,
@@ -161,4 +188,4 @@ def make_release_tree(self, base_dir, files):
161188 STATIC_VERSION_FILE ))
162189
163190
164- cmdclass = dict (sdist = _sdist , build = _build )
191+ cmdclass = dict (sdist = _sdist , build_py = _build_py )
0 commit comments