Port release.py to Python 2 and to UNIX
This commit is contained in:
171
release.py
171
release.py
@@ -24,13 +24,18 @@ import textwrap
|
|||||||
PROJECT = 'asyncio'
|
PROJECT = 'asyncio'
|
||||||
DEBUG_ENV_VAR = 'PYTHONASYNCIODEBUG'
|
DEBUG_ENV_VAR = 'PYTHONASYNCIODEBUG'
|
||||||
PYTHON_VERSIONS = (
|
PYTHON_VERSIONS = (
|
||||||
((3, 3), 32),
|
(3, 3),
|
||||||
((3, 3), 64),
|
|
||||||
)
|
)
|
||||||
PY3 = (sys.version_info >= (3,))
|
PY3 = (sys.version_info >= (3,))
|
||||||
HG = 'hg'
|
HG = 'hg'
|
||||||
SDK_ROOT = r"C:\Program Files\Microsoft SDKs\Windows"
|
SDK_ROOT = r"C:\Program Files\Microsoft SDKs\Windows"
|
||||||
BATCH_FAIL_ON_ERROR = "@IF %errorlevel% neq 0 exit /b %errorlevel%"
|
BATCH_FAIL_ON_ERROR = "@IF %errorlevel% neq 0 exit /b %errorlevel%"
|
||||||
|
WINDOWS = (sys.platform == 'win32')
|
||||||
|
|
||||||
|
|
||||||
|
def get_archiecture_bits():
|
||||||
|
arch = platform.architecture()[0]
|
||||||
|
return int(arch[:2])
|
||||||
|
|
||||||
|
|
||||||
class PythonVersion:
|
class PythonVersion:
|
||||||
@@ -42,42 +47,62 @@ class PythonVersion:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def running():
|
def running():
|
||||||
arch = platform.architecture()[0]
|
bits = get_archiecture_bits()
|
||||||
bits = int(arch[:2])
|
|
||||||
pyver = PythonVersion(sys.version_info.major,
|
pyver = PythonVersion(sys.version_info.major,
|
||||||
sys.version_info.minor,
|
sys.version_info.minor,
|
||||||
bits)
|
bits)
|
||||||
pyver._executable = sys.executable
|
pyver._executable = sys.executable
|
||||||
return pyver
|
return pyver
|
||||||
|
|
||||||
|
def _get_executable_windows(self, app):
|
||||||
|
if self.bits == 32:
|
||||||
|
executable = 'c:\\Python%s%s_32bit\\python.exe'
|
||||||
|
else:
|
||||||
|
executable = 'c:\\Python%s%s\\python.exe'
|
||||||
|
executable = executable % (self.major, self.minor)
|
||||||
|
if not os.path.exists(executable):
|
||||||
|
print("Unable to find python %s" % self)
|
||||||
|
print("%s does not exists" % executable)
|
||||||
|
sys.exit(1)
|
||||||
|
return executable
|
||||||
|
|
||||||
|
def _get_executable_unix(self, app):
|
||||||
|
return 'python%s.%s' % (self.major, self.minor)
|
||||||
|
|
||||||
def get_executable(self, app):
|
def get_executable(self, app):
|
||||||
if self._executable:
|
if self._executable:
|
||||||
return self._executable
|
return self._executable
|
||||||
|
|
||||||
if self.bits == 32:
|
if WINDOWS:
|
||||||
python = 'c:\\Python%s%s_32bit\\python.exe' % (self.major, self.minor)
|
executable = self._get_executable_windows(app)
|
||||||
else:
|
else:
|
||||||
python = 'c:\\Python%s%s\\python.exe' % (self.major, self.minor)
|
executable = self._get_executable_unix(app)
|
||||||
if not os.path.exists(python):
|
|
||||||
print("Unable to find python %s" % self)
|
|
||||||
print("%s does not exists" % python)
|
|
||||||
sys.exit(1)
|
|
||||||
code = (
|
code = (
|
||||||
'import platform, sys; '
|
'import platform, sys; '
|
||||||
'print("{ver.major}.{ver.minor} {bits}".format('
|
'print("{ver.major}.{ver.minor} {bits}".format('
|
||||||
'ver=sys.version_info, '
|
'ver=sys.version_info, '
|
||||||
'bits=platform.architecture()[0]))'
|
'bits=platform.architecture()[0]))'
|
||||||
)
|
)
|
||||||
exitcode, stdout = app.get_output(python, '-c', code)
|
try:
|
||||||
stdout = stdout.rstrip()
|
exitcode, stdout = app.get_output(executable, '-c', code,
|
||||||
expected = "%s.%s %sbit" % (self.major, self.minor, self.bits)
|
ignore_stderr=True)
|
||||||
if stdout != expected:
|
except OSError as exc:
|
||||||
print("Python version or architecture doesn't match")
|
print("Error while checking %s:" % self)
|
||||||
print("got %r, expected %r" % (stdout, expected))
|
print(str(exc))
|
||||||
print(python)
|
print("Executable: %s" % executable)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self._executable = python
|
else:
|
||||||
return python
|
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("Executable: %s" % executable)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
self._executable = executable
|
||||||
|
return executable
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'Python %s.%s (%s bits)' % (self.major, self.minor, self.bits)
|
return 'Python %s.%s (%s bits)' % (self.major, self.minor, self.bits)
|
||||||
@@ -97,9 +122,16 @@ class Release(object):
|
|||||||
self.upload = False
|
self.upload = False
|
||||||
# Release mode: enable more tests
|
# Release mode: enable more tests
|
||||||
self.release = False
|
self.release = False
|
||||||
self.python_versions = [
|
self.python_versions = []
|
||||||
PythonVersion(pyver[0], pyver[1], bits)
|
if WINDOWS:
|
||||||
for pyver, bits in PYTHON_VERSIONS]
|
supported_archs = (32, 64)
|
||||||
|
else:
|
||||||
|
bits = get_archiecture_bits()
|
||||||
|
supported_archs = (bits,)
|
||||||
|
for major, minor in PYTHON_VERSIONS:
|
||||||
|
for bits in supported_archs:
|
||||||
|
pyver = PythonVersion(major, minor, bits)
|
||||||
|
self.python_versions.append(pyver)
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def _popen(self, args, **kw):
|
def _popen(self, args, **kw):
|
||||||
@@ -109,15 +141,28 @@ class Release(object):
|
|||||||
if PY3:
|
if PY3:
|
||||||
kw['universal_newlines'] = True
|
kw['universal_newlines'] = True
|
||||||
proc = subprocess.Popen(args, **kw)
|
proc = subprocess.Popen(args, **kw)
|
||||||
with proc:
|
try:
|
||||||
yield proc
|
yield proc
|
||||||
|
except:
|
||||||
|
proc.kill()
|
||||||
|
proc.wait()
|
||||||
|
raise
|
||||||
|
|
||||||
def get_output(self, *args, **kw):
|
def get_output(self, *args, **kw):
|
||||||
kw['stdout'] = subprocess.PIPE
|
kw['stdout'] = subprocess.PIPE
|
||||||
kw['stderr'] = subprocess.STDOUT
|
ignore_stderr = kw.pop('ignore_stderr', False)
|
||||||
with self._popen(args, **kw) as proc:
|
if ignore_stderr:
|
||||||
stdout, stderr = proc.communicate()
|
devnull = open(os.path.devnull, 'wb')
|
||||||
return proc.returncode, stdout
|
kw['stderr'] = devnull
|
||||||
|
else:
|
||||||
|
kw['stderr'] = subprocess.STDOUT
|
||||||
|
try:
|
||||||
|
with self._popen(args, **kw) as proc:
|
||||||
|
stdout, stderr = proc.communicate()
|
||||||
|
return proc.returncode, stdout
|
||||||
|
finally:
|
||||||
|
if ignore_stderr:
|
||||||
|
devnull.close()
|
||||||
|
|
||||||
def check_output(self, *args, **kw):
|
def check_output(self, *args, **kw):
|
||||||
exitcode, output = self.get_output(*args, **kw)
|
exitcode, output = self.get_output(*args, **kw)
|
||||||
@@ -195,21 +240,23 @@ class Release(object):
|
|||||||
self.run_command(sys.executable, 'setup.py', 'sdist', 'upload')
|
self.run_command(sys.executable, 'setup.py', 'sdist', 'upload')
|
||||||
|
|
||||||
def build_inplace(self, pyver):
|
def build_inplace(self, pyver):
|
||||||
print("Build _overlapped.pyd for %s" % pyver)
|
print("Build for %s" % pyver)
|
||||||
self.build(pyver, 'build')
|
self.build(pyver, 'build')
|
||||||
if pyver.bits == 64:
|
|
||||||
arch = 'win-amd64'
|
if WINDOWS:
|
||||||
else:
|
if pyver.bits == 64:
|
||||||
arch = 'win32'
|
arch = 'win-amd64'
|
||||||
build_dir = 'lib.%s-%s.%s' % (arch, pyver.major, pyver.minor)
|
else:
|
||||||
src = os.path.join(self.root, 'build', build_dir, PROJECT, '_overlapped.pyd')
|
arch = 'win32'
|
||||||
dst = os.path.join(self.root, PROJECT, '_overlapped.pyd')
|
build_dir = 'lib.%s-%s.%s' % (arch, pyver.major, pyver.minor)
|
||||||
shutil.copyfile(src, dst)
|
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)
|
||||||
|
|
||||||
def runtests(self, pyver):
|
def runtests(self, pyver):
|
||||||
print("Run tests on %s" % pyver)
|
print("Run tests on %s" % pyver)
|
||||||
|
|
||||||
if not self.options.no_compile:
|
if WINDOWS and not self.options.no_compile:
|
||||||
self.build_inplace(pyver)
|
self.build_inplace(pyver)
|
||||||
|
|
||||||
release_env = dict(os.environ)
|
release_env = dict(os.environ)
|
||||||
@@ -239,27 +286,21 @@ class Release(object):
|
|||||||
self.run_command(*args, env=dbg_env)
|
self.run_command(*args, env=dbg_env)
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
def build(self, pyver, *cmds):
|
def _build_windows(self, pyver, cmd):
|
||||||
self.cleanup()
|
|
||||||
|
|
||||||
setenv, sdkver = self.windows_sdk_setenv(pyver)
|
setenv, sdkver = self.windows_sdk_setenv(pyver)
|
||||||
|
|
||||||
python = pyver.get_executable(self)
|
|
||||||
|
|
||||||
cmd = [python, 'setup.py'] + list(cmds)
|
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".bat", delete=False) as temp:
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".bat", delete=False) as temp:
|
||||||
print("SETLOCAL EnableDelayedExpansion", file=temp)
|
temp.write("SETLOCAL EnableDelayedExpansion\n")
|
||||||
print(self.quote_args(setenv), file=temp)
|
temp.write(self.quote_args(setenv) + "\n")
|
||||||
print(BATCH_FAIL_ON_ERROR, file=temp)
|
temp.write(BATCH_FAIL_ON_ERROR + "\n")
|
||||||
# Restore console colors: lightgrey on black
|
# Restore console colors: lightgrey on black
|
||||||
print("COLOR 07", file=temp)
|
temp.write("COLOR 07\n")
|
||||||
print("", file=temp)
|
temp.write("\n")
|
||||||
print("SET DISTUTILS_USE_SDK=1", file=temp)
|
temp.write("SET DISTUTILS_USE_SDK=1\n")
|
||||||
print("SET MSSDK=1", file=temp)
|
temp.write("SET MSSDK=1\n")
|
||||||
print("CD %s" % self.quote(self.root), file=temp)
|
temp.write("CD %s\n" % self.quote(self.root))
|
||||||
print(self.quote_args(cmd), file=temp)
|
temp.write(self.quote_args(cmd) + "\n")
|
||||||
print(BATCH_FAIL_ON_ERROR, file=temp)
|
temp.write(BATCH_FAIL_ON_ERROR + "\n")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
@@ -274,12 +315,28 @@ class Release(object):
|
|||||||
finally:
|
finally:
|
||||||
os.unlink(temp.name)
|
os.unlink(temp.name)
|
||||||
|
|
||||||
|
def _build_unix(self, pyver, cmd):
|
||||||
|
self.check_output(*cmd)
|
||||||
|
|
||||||
|
def build(self, pyver, *cmds):
|
||||||
|
self.cleanup()
|
||||||
|
|
||||||
|
python = pyver.get_executable(self)
|
||||||
|
cmd = [python, 'setup.py'] + list(cmds)
|
||||||
|
|
||||||
|
if WINDOWS:
|
||||||
|
self._build_windows(pyver, cmd)
|
||||||
|
else:
|
||||||
|
self._build_unix(pyver, cmd)
|
||||||
|
|
||||||
def test_wheel(self, pyver):
|
def test_wheel(self, pyver):
|
||||||
print("Test building wheel package for %s" % pyver)
|
print("Test building wheel package for %s" % pyver)
|
||||||
self.build(pyver, 'bdist_wheel')
|
self.build(pyver, 'bdist_wheel')
|
||||||
|
|
||||||
def publish_wheel(self, pyver):
|
def publish_wheel(self, pyver):
|
||||||
self.build(pyver, 'bdist_wheel', 'upload')
|
# FIXME: really upload
|
||||||
|
#self.build(pyver, 'bdist_wheel', 'upload')
|
||||||
|
self.build(pyver, 'bdist_wheel')
|
||||||
|
|
||||||
def parse_options(self):
|
def parse_options(self):
|
||||||
parser = optparse.OptionParser(
|
parser = optparse.OptionParser(
|
||||||
@@ -331,7 +388,7 @@ class Release(object):
|
|||||||
self.release = True
|
self.release = True
|
||||||
self.wheel = True
|
self.wheel = True
|
||||||
self.test = True
|
self.test = True
|
||||||
#self.upload = True
|
self.upload = True
|
||||||
else:
|
else:
|
||||||
if command:
|
if command:
|
||||||
print("Invalid command: %s" % command)
|
print("Invalid command: %s" % command)
|
||||||
|
|||||||
Reference in New Issue
Block a user