1import py, os, sys, shutil 2import subprocess 3from testing.udir import udir 4import pytest 5 6if sys.platform == 'win32': 7 pytestmark = pytest.mark.skip('snippets do not run on win32') 8if sys.version_info < (2, 7): 9 pytestmark = pytest.mark.skip( 10 'fails e.g. on a Debian/Ubuntu which patches virtualenv' 11 ' in a non-2.6-friendly way') 12 13def create_venv(name): 14 tmpdir = udir.join(name) 15 try: 16 subprocess.check_call(['virtualenv', 17 #'--never-download', <= could be added, but causes failures 18 # in random cases on random machines 19 '-p', os.path.abspath(sys.executable), 20 str(tmpdir)]) 21 except OSError as e: 22 py.test.skip("Cannot execute virtualenv: %s" % (e,)) 23 24 site_packages = None 25 for dirpath, dirnames, filenames in os.walk(str(tmpdir)): 26 if os.path.basename(dirpath) == 'site-packages': 27 site_packages = dirpath 28 break 29 paths = "" 30 if site_packages: 31 try: 32 from cffi import _pycparser 33 modules = ('cffi', '_cffi_backend') 34 except ImportError: 35 modules = ('cffi', '_cffi_backend', 'pycparser') 36 try: 37 import ply 38 except ImportError: 39 pass 40 else: 41 modules += ('ply',) # needed for older versions of pycparser 42 paths = [] 43 for module in modules: 44 target = __import__(module, None, None, []) 45 if not hasattr(target, '__file__'): # for _cffi_backend on pypy 46 continue 47 src = os.path.abspath(target.__file__) 48 for end in ['__init__.pyc', '__init__.pyo', '__init__.py']: 49 if src.lower().endswith(end): 50 src = src[:-len(end)-1] 51 break 52 paths.append(os.path.dirname(src)) 53 paths = os.pathsep.join(paths) 54 return tmpdir, paths 55 56SNIPPET_DIR = py.path.local(__file__).join('..', 'snippets') 57 58def really_run_setup_and_program(dirname, venv_dir_and_paths, python_snippet): 59 venv_dir, paths = venv_dir_and_paths 60 def remove(dir): 61 dir = str(SNIPPET_DIR.join(dirname, dir)) 62 shutil.rmtree(dir, ignore_errors=True) 63 remove('build') 64 remove('__pycache__') 65 for basedir in os.listdir(str(SNIPPET_DIR.join(dirname))): 66 remove(os.path.join(basedir, '__pycache__')) 67 olddir = os.getcwd() 68 python_f = udir.join('x.py') 69 python_f.write(py.code.Source(python_snippet)) 70 try: 71 os.chdir(str(SNIPPET_DIR.join(dirname))) 72 if os.name == 'nt': 73 bindir = 'Scripts' 74 else: 75 bindir = 'bin' 76 vp = str(venv_dir.join(bindir).join('python')) 77 env = os.environ.copy() 78 env['PYTHONPATH'] = paths 79 subprocess.check_call((vp, 'setup.py', 'clean'), env=env) 80 # there's a setuptools/easy_install bug that causes this to fail when the build/install occur together and 81 # we're in the same directory with the build (it tries to look up dependencies for itself on PyPI); 82 # subsequent runs will succeed because this test doesn't properly clean up the build- use pip for now. 83 subprocess.check_call((vp, '-m', 'pip', 'install', '.'), env=env) 84 subprocess.check_call((vp, str(python_f)), env=env) 85 finally: 86 os.chdir(olddir) 87 88def run_setup_and_program(dirname, python_snippet): 89 venv_dir = create_venv(dirname + '-cpy') 90 really_run_setup_and_program(dirname, venv_dir, python_snippet) 91 # 92 sys._force_generic_engine_ = True 93 try: 94 venv_dir = create_venv(dirname + '-gen') 95 really_run_setup_and_program(dirname, venv_dir, python_snippet) 96 finally: 97 del sys._force_generic_engine_ 98 # the two files lextab.py and yacctab.py are created by not-correctly- 99 # installed versions of pycparser. 100 assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'lextab.py'))) 101 assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'yacctab.py'))) 102 103class TestZIntegration(object): 104 def teardown_class(self): 105 if udir.isdir(): 106 udir.remove(ignore_errors=True) 107 udir.ensure(dir=1) 108 109 def test_infrastructure(self): 110 run_setup_and_program('infrastructure', ''' 111 import snip_infrastructure 112 assert snip_infrastructure.func() == 42 113 ''') 114 115 def test_distutils_module(self): 116 run_setup_and_program("distutils_module", ''' 117 import snip_basic_verify 118 p = snip_basic_verify.C.getpwuid(0) 119 assert snip_basic_verify.ffi.string(p.pw_name) == b"root" 120 ''') 121 122 def test_distutils_package_1(self): 123 run_setup_and_program("distutils_package_1", ''' 124 import snip_basic_verify1 125 p = snip_basic_verify1.C.getpwuid(0) 126 assert snip_basic_verify1.ffi.string(p.pw_name) == b"root" 127 ''') 128 129 def test_distutils_package_2(self): 130 run_setup_and_program("distutils_package_2", ''' 131 import snip_basic_verify2 132 p = snip_basic_verify2.C.getpwuid(0) 133 assert snip_basic_verify2.ffi.string(p.pw_name) == b"root" 134 ''') 135 136 def test_setuptools_module(self): 137 run_setup_and_program("setuptools_module", ''' 138 import snip_setuptools_verify 139 p = snip_setuptools_verify.C.getpwuid(0) 140 assert snip_setuptools_verify.ffi.string(p.pw_name) == b"root" 141 ''') 142 143 def test_setuptools_package_1(self): 144 run_setup_and_program("setuptools_package_1", ''' 145 import snip_setuptools_verify1 146 p = snip_setuptools_verify1.C.getpwuid(0) 147 assert snip_setuptools_verify1.ffi.string(p.pw_name) == b"root" 148 ''') 149 150 def test_setuptools_package_2(self): 151 run_setup_and_program("setuptools_package_2", ''' 152 import snip_setuptools_verify2 153 p = snip_setuptools_verify2.C.getpwuid(0) 154 assert snip_setuptools_verify2.ffi.string(p.pw_name) == b"root" 155 ''') 156 157 def test_set_py_limited_api(self): 158 from cffi.setuptools_ext import _set_py_limited_api 159 try: 160 import setuptools 161 except ImportError as e: 162 py.test.skip(str(e)) 163 orig_version = setuptools.__version__ 164 expecting_limited_api = not hasattr(sys, 'gettotalrefcount') 165 try: 166 setuptools.__version__ = '26.0.0' 167 from setuptools import Extension 168 169 kwds = _set_py_limited_api(Extension, {}) 170 assert kwds.get('py_limited_api', False) == expecting_limited_api 171 172 setuptools.__version__ = '25.0' 173 kwds = _set_py_limited_api(Extension, {}) 174 assert kwds.get('py_limited_api', False) == False 175 176 setuptools.__version__ = 'development' 177 kwds = _set_py_limited_api(Extension, {}) 178 assert kwds.get('py_limited_api', False) == expecting_limited_api 179 180 finally: 181 setuptools.__version__ = orig_version 182