Enhance release.py
* Only get the python executable once per python version * Much lesser verbose output: by default, hide all logs when building trollius
This commit is contained in:
175
release.py
175
release.py
@@ -28,6 +28,47 @@ HG = 'hg'
|
||||
SDK_ROOT = r"C:\Program Files\Microsoft SDKs\Windows"
|
||||
BATCH_FAIL_ON_ERROR = "@IF %errorlevel% neq 0 exit /b %errorlevel%"
|
||||
|
||||
|
||||
class PythonVersion:
|
||||
def __init__(self, major, minor, bits):
|
||||
self.major = major
|
||||
self.minor = minor
|
||||
self.bits = bits
|
||||
self._executable = None
|
||||
|
||||
def get_executable(self, app):
|
||||
if self._executable:
|
||||
return self._executable
|
||||
|
||||
if self.bits == 32:
|
||||
python = 'c:\\Python%s%s_32bit\\python.exe' % (self.major, self.minor)
|
||||
else:
|
||||
python = 'c:\\Python%s%s\\python.exe' % (self.major, self.minor)
|
||||
if not os.path.exists(python):
|
||||
print("Unable to find python %s" % self)
|
||||
print("%s does not exists" % python)
|
||||
sys.exit(1)
|
||||
code = (
|
||||
'import platform, sys; '
|
||||
'print("{ver.major}.{ver.minor} {bits}".format('
|
||||
'ver=sys.version_info, '
|
||||
'bits=platform.architecture()[0]))'
|
||||
)
|
||||
exitcode, stdout = app.get_output(python, '-c', code)
|
||||
stdout = stdout.rstrip()
|
||||
expected = "%s.%s %sbit" % (self.major, self.minor, self.bits)
|
||||
if stdout != expected:
|
||||
print("Python version or architecture doesn't match")
|
||||
print("got %r, expected %r" % (stdout, expected))
|
||||
print(python)
|
||||
sys.exit(1)
|
||||
self._executable = python
|
||||
return python
|
||||
|
||||
def __str__(self):
|
||||
return 'Python %s.%s (%s bits)' % (self.major, self.minor, self.bits)
|
||||
|
||||
|
||||
class Release(object):
|
||||
def __init__(self):
|
||||
root = os.path.dirname(__file__)
|
||||
@@ -37,11 +78,17 @@ class Release(object):
|
||||
self.sdist = False
|
||||
self.dry_run = True
|
||||
self.test = True
|
||||
self.aiotest = True
|
||||
self.aiotest = False
|
||||
self.verbose = False
|
||||
self.python_versions = [
|
||||
PythonVersion(pyver[0], pyver[1], bits)
|
||||
for pyver, bits in PYTHON_VERSIONS]
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _popen(self, args, **kw):
|
||||
print('+ ' + ' '.join(args))
|
||||
verbose = kw.pop('verbose', True)
|
||||
if self.verbose and verbose:
|
||||
print('+ ' + ' '.join(args))
|
||||
if PY3:
|
||||
kw['universal_newlines'] = True
|
||||
proc = subprocess.Popen(args, **kw)
|
||||
@@ -49,9 +96,11 @@ class Release(object):
|
||||
yield proc
|
||||
|
||||
def get_output(self, *args, **kw):
|
||||
with self._popen(args, stdout=subprocess.PIPE, **kw) as proc:
|
||||
kw['stdout'] = subprocess.PIPE
|
||||
kw['stderr'] = subprocess.STDOUT
|
||||
with self._popen(args, **kw) as proc:
|
||||
stdout, stderr = proc.communicate()
|
||||
return stdout
|
||||
return proc.returncode, stdout
|
||||
|
||||
def run_command(self, *args, **kw):
|
||||
with self._popen(args, **kw) as proc:
|
||||
@@ -60,65 +109,42 @@ class Release(object):
|
||||
sys.exit(exitcode)
|
||||
|
||||
def get_local_changes(self):
|
||||
status = self.get_output(HG, 'status')
|
||||
exitcode, status = self.get_output(HG, 'status')
|
||||
return [line for line in status.splitlines()
|
||||
if not line.startswith("?")]
|
||||
|
||||
def remove_directory(self, name):
|
||||
path = os.path.join(self.root, name)
|
||||
if os.path.exists(path):
|
||||
print("Remove directory: %s" % name)
|
||||
if self.verbose:
|
||||
print("Remove directory: %s" % name)
|
||||
shutil.rmtree(path)
|
||||
|
||||
def remove_file(self, name):
|
||||
path = os.path.join(self.root, name)
|
||||
if os.path.exists(path):
|
||||
print("Remove file: %s" % name)
|
||||
if self.verbose:
|
||||
print("Remove file: %s" % name)
|
||||
os.unlink(path)
|
||||
|
||||
def windows_sdk_setenv(self, pyver, bits):
|
||||
if pyver >= (3, 3):
|
||||
def windows_sdk_setenv(self, pyver):
|
||||
if (pyver.major, pyver.minor) >= (3, 3):
|
||||
sdkver = "v7.1"
|
||||
else:
|
||||
sdkver = "v7.0"
|
||||
setenv = os.path.join(SDK_ROOT, sdkver, 'Bin', 'SetEnv.cmd')
|
||||
if not os.path.exists(setenv):
|
||||
print("Unable to find Windows SDK %s for Python %s.%s"
|
||||
% (sdkver, pyver[0], pyver[1]))
|
||||
print("Unable to find Windows SDK %s for %s"
|
||||
% (sdkver, pyver))
|
||||
print("Please download and install it")
|
||||
print("%s does not exists" % setenv)
|
||||
sys.exit(1)
|
||||
if bits == 64:
|
||||
if pyver.bits == 64:
|
||||
arch = '/x64'
|
||||
else:
|
||||
arch = '/x86'
|
||||
return ["CALL", setenv, "/release", arch]
|
||||
|
||||
def get_python(self, version, bits):
|
||||
if bits == 32:
|
||||
python = 'c:\\Python%s%s_32bit\\python.exe' % version
|
||||
else:
|
||||
python = 'c:\\Python%s%s\\python.exe' % version
|
||||
if not os.path.exists(python):
|
||||
print("Unable to find python%s.%s" % version)
|
||||
print("%s does not exists" % python)
|
||||
sys.exit(1)
|
||||
code = (
|
||||
'import platform, sys; '
|
||||
'print("{ver.major}.{ver.minor} {bits}".format('
|
||||
'ver=sys.version_info, '
|
||||
'bits=platform.architecture()[0]))'
|
||||
)
|
||||
stdout = self.get_output(python, '-c', code)
|
||||
stdout = stdout.rstrip()
|
||||
expected = "%s.%s %sbit" % (version[0], version[1], bits)
|
||||
if stdout != expected:
|
||||
print("Python version or architecture doesn't match")
|
||||
print("got %r, expected %r" % (stdout, expected))
|
||||
print(python)
|
||||
sys.exit(1)
|
||||
return python
|
||||
|
||||
def quote(self, arg):
|
||||
if not re.search("[ '\"]", arg):
|
||||
return arg
|
||||
@@ -129,6 +155,8 @@ class Release(object):
|
||||
return ' '.join(self.quote(arg) for arg in args)
|
||||
|
||||
def cleanup(self):
|
||||
if self.verbose:
|
||||
print("Cleanup")
|
||||
self.remove_directory('build')
|
||||
self.remove_directory('dist')
|
||||
self.remove_file('_overlapped.pyd')
|
||||
@@ -138,16 +166,18 @@ class Release(object):
|
||||
self.cleanup()
|
||||
self.run_command(sys.executable, 'setup.py', 'sdist', 'upload')
|
||||
|
||||
def runtests(self, pyver, bits):
|
||||
pythonstr = "%s.%s (%s bits)" % (pyver[0], pyver[1], bits)
|
||||
python = self.get_python(pyver, bits)
|
||||
def runtests(self, pyver):
|
||||
print("Run tests on %s" % pyver)
|
||||
|
||||
self.build(pyver, bits, 'build')
|
||||
if bits == 64:
|
||||
python = pyver.get_executable(self)
|
||||
|
||||
print("Build _overlapped.pyd for %s" % pyver)
|
||||
self.build(pyver, 'build')
|
||||
if pyver.bits == 64:
|
||||
arch = 'win-amd64'
|
||||
else:
|
||||
arch = 'win32'
|
||||
build_dir = 'lib.%s-%s.%s' % (arch, pyver[0], pyver[1])
|
||||
build_dir = 'lib.%s-%s.%s' % (arch, pyver.major, pyver.minor)
|
||||
src = os.path.join(self.root, 'build', build_dir, PROJECT, '_overlapped.pyd')
|
||||
dst = os.path.join(self.root, PROJECT, '_overlapped.pyd')
|
||||
shutil.copyfile(src, dst)
|
||||
@@ -159,26 +189,27 @@ class Release(object):
|
||||
dbg_env[DEBUG_ENV_VAR] = '1'
|
||||
|
||||
args = (python, 'runtests.py', '-r')
|
||||
print("Run runtests.py in release mode with %s" % pythonstr)
|
||||
print("Run runtests.py in release mode on %s" % pyver)
|
||||
self.run_command(*args, env=release_env)
|
||||
|
||||
print("Run runtests.py in debug mode with %s" % pythonstr)
|
||||
print("Run runtests.py in debug mode on %s" % pyver)
|
||||
self.run_command(*args, env=dbg_env)
|
||||
|
||||
if self.aiotest:
|
||||
args = (python, 'run_aiotest.py')
|
||||
print("Run aiotest in release mode with %s" % pythonstr)
|
||||
print("Run aiotest in release mode on %s" % pyver)
|
||||
self.run_command(*args, env=release_env)
|
||||
|
||||
print("Run aiotest in debug mode with %s" % pythonstr)
|
||||
print("Run aiotest in debug mode on %s" % pyver)
|
||||
self.run_command(*args, env=dbg_env)
|
||||
print("")
|
||||
|
||||
def build(self, pyver, bits, *cmds):
|
||||
def build(self, pyver, *cmds):
|
||||
self.cleanup()
|
||||
|
||||
setenv = self.windows_sdk_setenv(pyver, bits)
|
||||
setenv = self.windows_sdk_setenv(pyver)
|
||||
|
||||
python = self.get_python(pyver, bits)
|
||||
python = pyver.get_executable(self)
|
||||
|
||||
cmd = [python, 'setup.py'] + list(cmds)
|
||||
|
||||
@@ -196,15 +227,25 @@ class Release(object):
|
||||
print(BATCH_FAIL_ON_ERROR, file=temp)
|
||||
|
||||
try:
|
||||
self.run_command(temp.name)
|
||||
if self.verbose:
|
||||
print("Setup Windows SDK")
|
||||
print("+ " + ' '.join(cmd))
|
||||
if self.verbose:
|
||||
self.run_command(temp.name, verbose=False)
|
||||
else:
|
||||
exitcode, stdout = self.get_output(temp.name, verbose=False)
|
||||
if exitcode:
|
||||
sys.stdout.write(stdout)
|
||||
sys.stdout.flush()
|
||||
finally:
|
||||
os.unlink(temp.name)
|
||||
|
||||
def test_wheel(self, pyver, bits):
|
||||
self.build(pyver, bits, 'bdist_wheel')
|
||||
def test_wheel(self, pyver):
|
||||
print("Test building wheel package for %s" % pyver)
|
||||
self.build(pyver, 'bdist_wheel')
|
||||
|
||||
def publish_wheel(self, pyver, bits):
|
||||
self.build(pyver, bits, 'bdist_wheel', 'upload')
|
||||
def publish_wheel(self, pyver):
|
||||
self.build(pyver, 'bdist_wheel', 'upload')
|
||||
|
||||
def main(self):
|
||||
try:
|
||||
@@ -235,14 +276,19 @@ class Release(object):
|
||||
sys.exit(1)
|
||||
|
||||
hg_tag = sys.argv[1]
|
||||
self.run_command(HG, 'up', hg_tag)
|
||||
print("Update repository to revision %s" % hg_tag)
|
||||
exitcode, output = self.get_output(HG, 'update', hg_tag)
|
||||
if exitcode:
|
||||
sys.stdout.write(output)
|
||||
sys.stdout.flush()
|
||||
sys.exit(exitcode)
|
||||
|
||||
if self.test:
|
||||
for pyver, bits in PYTHON_VERSIONS:
|
||||
self.runtests(pyver, bits)
|
||||
for pyver in self.python_versions:
|
||||
self.runtests(pyver)
|
||||
|
||||
for pyver, bits in PYTHON_VERSIONS:
|
||||
self.test_wheel(pyver, bits)
|
||||
for pyver in self.python_versions:
|
||||
self.test_wheel(pyver)
|
||||
|
||||
if self.dry_run:
|
||||
sys.exit(0)
|
||||
@@ -253,8 +299,8 @@ class Release(object):
|
||||
if self.sdist:
|
||||
self.sdist_upload()
|
||||
|
||||
for pyver, bits in PYTHON_VERSIONS:
|
||||
self.publish_wheel(pyver, bits)
|
||||
for pyver in self.python_versions:
|
||||
self.publish_wheel(pyver)
|
||||
|
||||
print("")
|
||||
if self.register:
|
||||
@@ -262,9 +308,8 @@ class Release(object):
|
||||
print("Uploaded:")
|
||||
if self.sdist:
|
||||
print("- sdist")
|
||||
for pyver, bits in PYTHON_VERSIONS:
|
||||
print("- Windows wheel %s bits package for Python %s.%s"
|
||||
% (bits, pyver[0], pyver[1]))
|
||||
for pyver in self.python_versions:
|
||||
print("- Windows wheel package for %s" % pyver)
|
||||
|
||||
if __name__ == "__main__":
|
||||
Release().main()
|
||||
|
||||
Reference in New Issue
Block a user