diff options
author | Anthon van der Neut <anthon@mnt.org> | 2017-01-18 09:32:22 +0100 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2017-01-18 09:32:22 +0100 |
commit | 87a5ef4574e4cb666ab0752e729693ad1ab3d782 (patch) | |
tree | 89e81d64b84c355f4e1c912e6beb76a44315a3e9 /setup.py | |
parent | f6fe5bcac3694c10e3300875398b1f94873dd091 (diff) | |
download | ruamel.yaml-87a5ef4574e4cb666ab0752e729693ad1ab3d782.tar.gz |
fix deepcopy of TimeStamp, fix #91: crash if no compiler0.13.8
Diffstat (limited to 'setup.py')
-rw-r--r-- | setup.py | 146 |
1 files changed, 131 insertions, 15 deletions
@@ -39,6 +39,12 @@ if sys.version_info < (3, 4): class NameConstant: pass +if sys.version_info < (3, ): + open_kw = dict() +else: + open_kw = dict(encoding='utf-8') + + if sys.version_info < (2, 7) or platform.python_implementation() == 'Jython': class Set(): pass @@ -119,7 +125,7 @@ def literal_eval(node_or_string): # parses python ( "= dict( )" ) or ( "= {" ) def _package_data(fn): data = {} - with open(fn) as fp: + with open(fn, **open_kw) as fp: parsing = False lines = [] for line in fp.readlines(): @@ -225,6 +231,74 @@ class MyInstallLib(install_lib.install_lib): return alt_files +class InMemoryZipFile(object): + def __init__(self, file_name=None): + try: + from cStringIO import StringIO + except ImportError: + from io import BytesIO as StringIO + import zipfile + self.zip_file = zipfile + # Create the in-memory file-like object + self._file_name = file_name + self.in_memory_data = StringIO() + # Create the in-memory zipfile + self.in_memory_zip = self.zip_file.ZipFile( + self.in_memory_data, "w", self.zip_file.ZIP_DEFLATED, False) + self.in_memory_zip.debug = 3 + + def append(self, filename_in_zip, file_contents): + '''Appends a file with name filename_in_zip and contents of + file_contents to the in-memory zip.''' + self.in_memory_zip.writestr(filename_in_zip, file_contents) + return self # so you can daisy-chain + + def write_to_file(self, filename): + '''Writes the in-memory zip to a file.''' + # Mark the files as having been created on Windows so that + # Unix permissions are not inferred as 0000 + for zfile in self.in_memory_zip.filelist: + zfile.create_system = 0 + self.in_memory_zip.close() + with open(filename, 'wb') as f: + f.write(self.in_memory_data.getvalue()) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + if self._file_name is None: + return + self.write_to_file(self._file_name) + + def delete_from_zip_file(self, pattern=None, file_names=None): + """ + zip_file can be a string or a zipfile.ZipFile object, the latter will be closed + any name in file_names is deleted, all file_names provided have to be in the ZIP + archive or else an IOError is raised + """ + if pattern and isinstance(pattern, string_type): + import re + pattern = re.compile(pattern) + if file_names: + if not isinstance(file_names, list): + file_names = [file_names] + else: + file_names = [] + with self.zip_file.ZipFile(self._file_name) as zf: + for l in zf.infolist(): + if l.filename in file_names: + file_names.remove(l.filename) + continue + if pattern and pattern.match(l.filename): + continue + self.append(l.filename, zf.read(l)) + if file_names: + raise IOError('[Errno 2] No such file{}: {}'.format( + '' if len(file_names) == 1 else 's', + ', '.join([repr(f) for f in file_names]))) + + class NameSpacePackager(object): def __init__(self, pkg_data): assert isinstance(pkg_data, dict) @@ -232,6 +306,7 @@ class NameSpacePackager(object): self.full_package_name = self.pn(self._pkg_data['full_package_name']) self._split = None self.depth = self.full_package_name.count('.') + self.nested = self._pkg_data.get('nested', False) self.command = None self.python_version() self._pkg = [None, None] # required and pre-installable packages @@ -526,6 +601,11 @@ class NameSpacePackager(object): packages = ir.get('any', []) if isinstance(packages, string_type): packages = packages.split() # assume white space separated string + if self.nested: + # parent dir is also a package, make sure it is installed (need its .pth file) + parent_pkg = self.full_package_name.rsplit('.', 1)[0] + if parent_pkg not in packages: + packages.append(parent_pkg) implementation = platform.python_implementation() if implementation == 'CPython': pyver = 'py{0}{1}'.format(*sys.version_info) @@ -566,8 +646,16 @@ class NameSpacePackager(object): @property def ext_modules(self): - """check if the C module can be build by trying to compile a small - program against the libyaml development library""" + """check if all modules specified in the value for 'ext_modules' can be build + that value (if not None) is a list of dicts with 'name', 'src', 'lib' + Optional 'test' can be used to make sure trying to compile will work on the host + + creates and return the external modules as Extensions, unless that + is not necessary at all for the action (like --version) + + test existence of compiler by using export CC=nonexistent; export CXX=nonexistent + """ + if hasattr(self, '_ext_modules'): return self._ext_modules if '--version' in sys.argv: @@ -582,6 +670,23 @@ class NameSpacePackager(object): return None except ValueError: pass + self._ext_modules = [] + no_test_compile = False + if '--restructuredtext' in sys.argv: + no_test_compile = True + elif 'sdist' in sys.argv: + no_test_compile = True + if no_test_compile: + for target in self._pkg_data.get('ext_modules', []): + ext = Extension( + self.pn(target['name']), + sources=[self.pn(x) for x in target['src']], + libraries=[self.pn(x) for x in target.get('lib')], + ) + self._ext_modules.append(ext) + return self._ext_modules + + print('sys.argv', sys.argv) import tempfile import shutil from textwrap import dedent @@ -590,16 +695,13 @@ class NameSpacePackager(object): import distutils.ccompiler from distutils.errors import CompileError, LinkError - self._ext_modules = [] for target in self._pkg_data.get('ext_modules', []): # list of dicts - test_code = target.get('test') - libraries = [self.pn(x) for x in target.get('lib')] ext = Extension( self.pn(target['name']), sources=[self.pn(x) for x in target['src']], - libraries=libraries, + libraries=[self.pn(x) for x in target.get('lib')], ) - if not test_code: + if 'test' not in target: # no test just hope it works self._ext_modules.append(ext) continue # write a temporary .c file to compile @@ -607,24 +709,30 @@ class NameSpacePackager(object): try: tmp_dir = tempfile.mkdtemp(prefix='tmp_ruamel_') bin_file_name = 'test' + self.pn(target['name']) + print('test compiling', bin_file_name) file_name = os.path.join(tmp_dir, bin_file_name + '.c') - with open(file_name, 'w') as fp: + with open(file_name, 'w') as fp: # write source fp.write(c_code) - # and try to compile it compiler = distutils.ccompiler.new_compiler() assert isinstance(compiler, distutils.ccompiler.CCompiler) + # do any platform specific initialisations distutils.sysconfig.customize_compiler(compiler) - + # make sure you can reach header files because compile does change dir + compiler.add_include_dir(os.getcwd()) + if sys.version_info < (3, ): + tmp_dir = tmp_dir.encode('utf-8') + # used to be a different directory, not necessary + compile_out_dir = tmp_dir try: compiler.link_executable( compiler.compile( [file_name], - output_dir='/', # as file_name has absolute prefix + output_dir=compile_out_dir, ), bin_file_name, output_dir=tmp_dir, - libraries=libraries, + libraries=ext.libraries, ) except CompileError: print('compile error:', file_name) @@ -634,7 +742,7 @@ class NameSpacePackager(object): continue self._ext_modules.append(ext) except Exception as e: # NOQA - # print('Exception:', e) + print('Exception:', e) pass finally: shutil.rmtree(tmp_dir) @@ -728,6 +836,14 @@ def main(): break try_dir = os.path.dirname(try_dir) setup(**kw) - + if nsp.nested and sys.argv[:2] == ['-c', 'bdist_wheel']: + d = sys.argv[sys.argv.index('-d')+1] + for x in os.listdir(d): + if x.endswith('.whl'): + # remove .pth file from the wheel + full_name = os.path.join(d, x) + with InMemoryZipFile(full_name) as imz: + imz.delete_from_zip_file(nsp.full_package_name + '.*.pth') + break main() |