Merge pull request #265 from YannickJadoul/drop-2.7

Dropping Python 2.7 host support
This commit is contained in:
Yannick Jadoul
2020-02-04 23:35:19 +01:00
committed by GitHub
16 changed files with 72 additions and 112 deletions
+8 -25
View File
@@ -1,11 +1,11 @@
version: 2 version: 2
jobs: jobs:
osx-python2: osx-python3.6:
macos: macos:
xcode: "10.0.0" xcode: "9.4.1"
environment: environment:
PYTHON: python2 PYTHON: python3
steps: steps:
- checkout - checkout
@@ -16,7 +16,7 @@ jobs:
name: Test. name: Test.
command: venv/bin/python ./bin/run_tests.py command: venv/bin/python ./bin/run_tests.py
osx-python3: osx-python3.7:
macos: macos:
xcode: "10.0.0" xcode: "10.0.0"
environment: environment:
@@ -31,23 +31,7 @@ jobs:
name: Test. name: Test.
command: venv/bin/python ./bin/run_tests.py command: venv/bin/python ./bin/run_tests.py
linux-python2: linux-python3.6:
docker:
- image: circleci/python:2.7
environment:
PYTHON: python2
steps:
- checkout
- setup_remote_docker
- run:
name: Prepare the environment.
command: bash .circleci/prepare.sh
- run:
name: Test.
command: venv/bin/python ./bin/run_tests.py
linux-python3:
docker: docker:
- image: circleci/python:3.6 - image: circleci/python:3.6
environment: environment:
@@ -67,7 +51,6 @@ workflows:
version: 2 version: 2
all-tests: all-tests:
jobs: jobs:
- osx-python2 - osx-python3.6
- osx-python3 - osx-python3.7
- linux-python2 - linux-python3.6
- linux-python3
-7
View File
@@ -2,13 +2,6 @@ language: generic
matrix: matrix:
include: include:
# Linux Python 2
- sudo: required
language: python
python: 2.7
services: docker
env: PYTHON=python
# Linux Python 3 # Linux Python 3
- sudo: required - sudo: required
language: python language: python
+9
View File
@@ -0,0 +1,9 @@
This is a summary of the Python versions and platforms covered by the different CI platforms:
| | 3.5 | 3.6 | 3.7 | 3.8 |
|----------|------------------|------------------|-----------------------|------------------|
| Linux | Travis CI | CircleCI | AppVeyor | Azure Pipelines |
| macOS | Azure Pipelines | CircleCI | Travis CI¹ / CircleCI | Azure Pipelines |
| Windows | TravisCI | Azure Pipelines | AppVeyor | Azure Pipelines |
> ¹ Python version not really pinned, but dependent on the (default) version of image used.
+2 -2
View File
@@ -3,9 +3,9 @@ image:
- Visual Studio 2015 - Visual Studio 2015
build_script: build_script:
- cmd: "C:\\Python27\\python.exe -m pip install -r requirements-dev.txt" - cmd: "C:\\Python37\\python.exe -m pip install -r requirements-dev.txt"
- sh: "${HOME}/.localpython3.7.4/bin/python3 -m pip install -r requirements-dev.txt" - sh: "${HOME}/.localpython3.7.4/bin/python3 -m pip install -r requirements-dev.txt"
# the '-u' flag is required so the output is in the correct order. # the '-u' flag is required so the output is in the correct order.
# See https://github.com/joerick/cibuildwheel/pull/24 for more info. # See https://github.com/joerick/cibuildwheel/pull/24 for more info.
- cmd: "C:\\Python27\\python.exe -u ./bin/run_tests.py" - cmd: "C:\\Python37\\python.exe -u ./bin/run_tests.py"
- sh: "${HOME}/.localpython3.7.4/bin/python3 ./bin/run_tests.py" - sh: "${HOME}/.localpython3.7.4/bin/python3 ./bin/run_tests.py"
+25 -3
View File
@@ -1,5 +1,5 @@
jobs: jobs:
- job: linux - job: linux_38
pool: {vmImage: 'Ubuntu-18.04'} pool: {vmImage: 'Ubuntu-18.04'}
steps: steps:
- task: UsePythonVersion@0 - task: UsePythonVersion@0
@@ -9,7 +9,17 @@ jobs:
python -m pip install -r requirements-dev.txt python -m pip install -r requirements-dev.txt
python ./bin/run_tests.py python ./bin/run_tests.py
- job: macos - job: macos_35
pool: {vmImage: 'macOS-10.13'}
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.5'
- bash: |
python -m pip install -r requirements-dev.txt
python ./bin/run_tests.py
- job: macos_38
pool: {vmImage: 'macOS-10.13'} pool: {vmImage: 'macOS-10.13'}
steps: steps:
- task: UsePythonVersion@0 - task: UsePythonVersion@0
@@ -19,7 +29,19 @@ jobs:
python -m pip install -r requirements-dev.txt python -m pip install -r requirements-dev.txt
python ./bin/run_tests.py python ./bin/run_tests.py
- job: windows - job: windows_36
pool: {vmImage: 'vs2017-win2016'}
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.6'
- script: choco install vcpython27 -f -y
displayName: Install Visual C++ for Python 2.7
- bash: |
python -m pip install -r requirements-dev.txt
python ./bin/run_tests.py
- job: windows_38
pool: {vmImage: 'vs2017-win2016'} pool: {vmImage: 'vs2017-win2016'}
steps: steps:
- task: UsePythonVersion@0 - task: UsePythonVersion@0
+1 -2
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python3
from __future__ import print_function
import os, sys, subprocess, shutil import os, sys, subprocess, shutil
+1 -2
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python3
from __future__ import print_function
import os, sys, subprocess, shutil, json import os, sys, subprocess, shutil, json
from glob import glob from glob import glob
-1
View File
@@ -1,4 +1,3 @@
from __future__ import print_function
import argparse, os, subprocess, sys, textwrap import argparse, os, subprocess, sys, textwrap
import cibuildwheel import cibuildwheel
+1 -5
View File
@@ -60,12 +60,8 @@ def evaluate_word_node(node, context):
def evaluate_command_node(node, context): def evaluate_command_node(node, context):
words = [evaluate_node(part, context=context) for part in node.parts] words = [evaluate_node(part, context=context) for part in node.parts]
command = ' '.join(words) command = ' '.join(words)
output = subprocess.check_output(shlex.split(command), env=context.environment) return subprocess.check_output(shlex.split(command), env=context.environment, universal_newlines=True)
if sys.version_info[0] >= 3:
return output.decode('utf8', 'replace')
else:
return output
def evaluate_parameter_node(node, context): def evaluate_parameter_node(node, context):
return context.environment.get(node.value, '') return context.environment.get(node.value, '')
+2 -2
View File
@@ -41,7 +41,7 @@ def split_env_items(env_string):
return result return result
class EnvironmentAssignment(object): class EnvironmentAssignment:
def __init__(self, assignment): def __init__(self, assignment):
name, equals, value = assignment.partition('=') name, equals, value = assignment.partition('=')
if not equals: if not equals:
@@ -60,7 +60,7 @@ class EnvironmentAssignment(object):
return '%s=%s' % (self.name, self.value) return '%s=%s' % (self.name, self.value)
class ParsedEnvironment(object): class ParsedEnvironment:
def __init__(self, assignments): def __init__(self, assignments):
self.assignments = assignments self.assignments = assignments
+15 -35
View File
@@ -1,13 +1,7 @@
from __future__ import print_function import os, shlex, subprocess, sys, textwrap, uuid
import os, subprocess, sys, uuid, textwrap
from collections import namedtuple from collections import namedtuple
from .util import prepare_command, get_build_verbosity_extra_flags from .util import prepare_command, get_build_verbosity_extra_flags
try:
from shlex import quote as shlex_quote
except ImportError:
from pipes import quote as shlex_quote
def get_python_configurations(build_selector): def get_python_configurations(build_selector):
PythonConfiguration = namedtuple('PythonConfiguration', ['identifier', 'path']) PythonConfiguration = namedtuple('PythonConfiguration', ['identifier', 'path'])
@@ -132,14 +126,14 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
pybin_paths=' '.join(c.path+'/bin' for c in platform_configs), pybin_paths=' '.join(c.path+'/bin' for c in platform_configs),
test_requires=' '.join(test_requires), test_requires=' '.join(test_requires),
test_extras=test_extras, test_extras=test_extras,
test_command=shlex_quote( test_command=shlex.quote(
prepare_command(test_command, project='/project') if test_command else '' prepare_command(test_command, project='/project') if test_command else ''
), ),
before_build=shlex_quote( before_build=shlex.quote(
prepare_command(before_build, project='/project') if before_build else '' prepare_command(before_build, project='/project') if before_build else ''
), ),
build_verbosity_flag=' '.join(get_build_verbosity_extra_flags(build_verbosity)), build_verbosity_flag=' '.join(get_build_verbosity_extra_flags(build_verbosity)),
repair_command=shlex_quote( repair_command=shlex.quote(
prepare_command(repair_command, wheel='"$1"', dest_dir='/tmp/repaired_wheels') if repair_command else '' prepare_command(repair_command, wheel='"$1"', dest_dir='/tmp/repaired_wheels') if repair_command else ''
), ),
environment_exports='\n'.join(environment.as_shell_commands()), environment_exports='\n'.join(environment.as_shell_commands()),
@@ -147,38 +141,24 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
gid=os.getgid(), gid=os.getgid(),
) )
def run_docker(command, stdin_str=None):
print('docker command: docker {}'.format(' '.join(map(shlex_quote, command))))
if stdin_str is None:
subprocess.check_call(['docker'] + command)
else:
args = ['docker'] + command
process = subprocess.Popen(args, stdin=subprocess.PIPE, universal_newlines=True)
try:
process.communicate(stdin_str)
except KeyboardInterrupt:
process.kill()
process.wait()
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, args)
container_name = 'cibuildwheel-{}'.format(uuid.uuid4()) container_name = 'cibuildwheel-{}'.format(uuid.uuid4())
try: try:
run_docker(['create', subprocess.run(['docker', 'create',
'--env', 'CIBUILDWHEEL', '--env', 'CIBUILDWHEEL',
'--name', container_name, '--name', container_name,
'-i', '-i',
'-v', '/:/host', # ignored on Circle '-v', '/:/host', # ignored on CircleCI
docker_image, '/bin/bash']) docker_image, '/bin/bash'],
run_docker(['cp', os.path.abspath(project_dir) + '/.', container_name + ':/project']) check=True)
run_docker(['start', '-i', '-a', container_name], stdin_str=bash_script) subprocess.run(['docker', 'cp', os.path.abspath(project_dir) + '/.', container_name + ':/project'], check=True)
run_docker(['cp', container_name + ':/output/.', os.path.abspath(output_dir)]) subprocess.run(['docker', 'start', '-i', '-a', container_name], input=bash_script, universal_newlines=True, check=True)
subprocess.run(['docker', 'cp', container_name + ':/output/.', os.path.abspath(output_dir)], check=True)
except subprocess.CalledProcessError as error: except subprocess.CalledProcessError as error:
troubleshoot(project_dir, error) troubleshoot(project_dir, error)
exit(1) exit(1)
finally: finally:
# Still gets executed, even when 'exit(1)' gets called # Still gets executed, even when 'exit(1)' gets called
run_docker(['rm', '--force', '-v', container_name]) subprocess.run(['docker', 'rm', '--force', '-v', container_name], check=True)
def troubleshoot(project_dir, error): def troubleshoot(project_dir, error):
+2 -9
View File
@@ -1,12 +1,7 @@
from __future__ import print_function
import tempfile import tempfile
import os, subprocess, shlex, sys, shutil import os, subprocess, shlex, sys, shutil
from collections import namedtuple from collections import namedtuple
from glob import glob from glob import glob
try:
from shlex import quote as shlex_quote
except ImportError:
from pipes import quote as shlex_quote
from .util import prepare_command, get_build_verbosity_extra_flags, download from .util import prepare_command, get_build_verbosity_extra_flags, download
@@ -36,9 +31,7 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
get_pip_url = 'https://bootstrap.pypa.io/get-pip.py' get_pip_url = 'https://bootstrap.pypa.io/get-pip.py'
get_pip_script = '/tmp/get-pip.py' get_pip_script = '/tmp/get-pip.py'
pkgs_output = subprocess.check_output(['pkgutil', '--pkgs']) pkgs_output = subprocess.check_output(['pkgutil', '--pkgs'], universal_newlines=True)
if sys.version_info[0] >= 3:
pkgs_output = pkgs_output.decode('utf8')
installed_system_packages = pkgs_output.splitlines() installed_system_packages = pkgs_output.splitlines()
def call(args, env=None, cwd=None, shell=False): def call(args, env=None, cwd=None, shell=False):
@@ -46,7 +39,7 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
if shell: if shell:
print('+ %s' % args) print('+ %s' % args)
else: else:
print('+ ' + ' '.join(shlex_quote(a) for a in args)) print('+ ' + ' '.join(shlex.quote(a) for a in args))
return subprocess.check_call(args, env=env, cwd=cwd, shell=shell) return subprocess.check_call(args, env=env, cwd=cwd, shell=shell)
+4 -9
View File
@@ -1,13 +1,8 @@
from fnmatch import fnmatch from fnmatch import fnmatch
import warnings import warnings
import os import os, urllib.request
from time import sleep from time import sleep
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
def prepare_command(command, **kwargs): def prepare_command(command, **kwargs):
''' '''
@@ -28,7 +23,7 @@ def get_build_verbosity_extra_flags(level):
return [] return []
class BuildSelector(object): class BuildSelector:
def __init__(self, build_config, skip_config): def __init__(self, build_config, skip_config):
self.build_patterns = build_config.split() self.build_patterns = build_config.split()
self.skip_patterns = skip_config.split() self.skip_patterns = skip_config.split()
@@ -43,7 +38,7 @@ class BuildSelector(object):
# Taken from https://stackoverflow.com/a/107717 # Taken from https://stackoverflow.com/a/107717
class Unbuffered(object): class Unbuffered:
def __init__(self, stream): def __init__(self, stream):
self.stream = stream self.stream = stream
@@ -68,7 +63,7 @@ def download(url, dest):
repeat_num = 3 repeat_num = 3
for i in range(repeat_num): for i in range(repeat_num):
try: try:
response = urlopen(url) response = urllib.request.urlopen(url)
except: except:
if i == repeat_num - 1: if i == repeat_num - 1:
raise raise
-6
View File
@@ -1,13 +1,7 @@
from __future__ import print_function
import os, tempfile, subprocess, shutil, sys import os, tempfile, subprocess, shutil, sys
from collections import namedtuple from collections import namedtuple
from glob import glob from glob import glob
try:
from shlex import quote as shlex_quote
except ImportError:
from pipes import quote as shlex_quote
from .util import prepare_command, get_build_verbosity_extra_flags, download from .util import prepare_command, get_build_verbosity_extra_flags, download
+1 -3
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os, io import os, io
@@ -28,12 +27,11 @@ setup(
'cibuildwheel': ['resources/*'], 'cibuildwheel': ['resources/*'],
}, },
# Supported python versions # Supported python versions
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', python_requires='>=3.5',
keywords='ci wheel packaging pypi travis appveyor macos linux windows', keywords='ci wheel packaging pypi travis appveyor macos linux windows',
classifiers=[ classifiers=[
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'Natural Language :: English', 'Natural Language :: English',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Development Status :: 5 - Production/Stable', 'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: BSD License', 'License :: OSI Approved :: BSD License',
+1 -1
View File
@@ -7,7 +7,7 @@ import subprocess
from cibuildwheel import linux, macos, windows, util from cibuildwheel import linux, macos, windows, util
class ArgsInterceptor(object): class ArgsInterceptor:
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs