def get_tag(self): # bdist sets self.plat_name if unset, we should only use it for purepy # wheels if the user supplied it. if self.plat_name_supplied: plat_name = self.plat_name elif self.root_is_pure: plat_name = 'any' else: # macosx contains system version in platform name so need special handle if self.plat_name and not self.plat_name.startswith("macosx"): plat_name = self.plat_name else: plat_name = get_platform(self.bdist_dir) if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647: plat_name = 'linux_i686' plat_name = plat_name.replace('-', '_').replace('.', '_') if self.root_is_pure: if self.universal: impl = 'py2.py3' else: impl = self.python_tag tag = (impl, 'none', plat_name) else: impl_name = tags.interpreter_name() impl_ver = tags.interpreter_version() impl = impl_name + impl_ver # We don't work on CPython 3.1, 3.0. if self.py_limited_api and (impl_name + impl_ver).startswith('cp3'): impl = self.py_limited_api abi_tag = 'abi3' else: abi_tag = str(get_abi_tag()).lower() abi_tag = self.abi_tag tag = (impl, abi_tag, plat_name) supported_tags = [(t.interpreter, t.abi, t.platform) for t in tags.sys_tags()] # XXX switch to this alternate implementation for non-pure: if not self.py_limited_api: assert tag == supported_tags[0], "%s != %s" % ( tag, supported_tags[0]) # assert tag in supported_tags, "would build wheel with unsupported tag {}".format(tag) return tag
def get_tags(): """Get proper tags using wheel's package implementation of PEP427.""" impl = wheel_tags.interpreter_name() + wheel_tags.interpreter_version() abi = pep.get_abi_tag() try: arch = pep.safer_name(pep.get_platform(None)) except: arch = pep.safer_name(pep.get_platform()) if arch == "linux_x86_64": arch = 'manylinux2014_x86_64' elif arch == "linux_i686": arch = 'manylinux2014_i686' elif arch == "linux_aarch64": arch = 'manylinux2014_aarch64' if 'macosx' in arch: arch = arch.replace('.', '_') tags = f'{impl}-{abi}-{arch}' return tags
def generate_whl_name( input_folder, distribution, version, build_tag, abi_tag=None, platform_tag=None, ): python_tag = 'cp' + ''.join(map(str, sys.version_info[:2])) abi_tag = abi_tag or get_abi_tag() platform_tag = platform_tag or get_platform_tag(input_folder) components = [distribution, version] if build_tag: components.append(build_tag) components.extend([python_tag, abi_tag, platform_tag]) return '-'.join(components) + '.whl'
def patch_mac(): # Find delocate location delocate_wheel = find_program('delocate-wheel') delocate_list = find_program('delocate-listdeps') if delocate_wheel is None: raise FileNotFoundError('Delocate was not found in the system, ' 'please install it via pip') # Produce wheel print('Producing wheel...') subprocess.check_output( [ sys.executable, 'setup.py', 'bdist_wheel' ], cwd=PACKAGE_ROOT ) package_info = get_metadata() version = package_info['version'].replace('-', '.') wheel_name = 'pyduckling_native-{0}-cp{1}{2}-{3}-macosx_10_15_{4}.whl'.format( version, PYTHON_VERSION.major, PYTHON_VERSION.minor, get_abi_tag(), PLATFORM_ARCH) dist = osp.join(PACKAGE_ROOT, 'dist', wheel_name) print('Calling delocate...') subprocess.check_output( [ delocate_wheel, '-v', dist ], cwd=PACKAGE_ROOT ) print('Resulting libraries') subprocess.check_output( [ delocate_list, '--all', dist ], cwd=PACKAGE_ROOT )
def patch_linux(): # Get patchelf location patchelf = find_program('patchelf') if patchelf is None: raise FileNotFoundError('Patchelf was not found in the system, please' ' make sure that is available on the PATH.') # Produce wheel print('Producing wheel...') subprocess.check_output( [ sys.executable, 'setup.py', 'bdist_wheel' ], cwd=PACKAGE_ROOT ) package_info = get_metadata() version = package_info['version'].replace('-', '.') wheel_name = 'pyduckling_native-{0}-cp{1}{2}-{3}-linux_{4}.whl'.format( version, PYTHON_VERSION.major, PYTHON_VERSION.minor, get_abi_tag(), PLATFORM_ARCH) dist = osp.join(PACKAGE_ROOT, 'dist', wheel_name) output_dir = osp.join(PACKAGE_ROOT, '.wheel-process') print(glob.glob(osp.join(PACKAGE_ROOT, 'dist', '*.whl'))) if osp.exists(output_dir): shutil.rmtree(output_dir) os.makedirs(output_dir) print('Unzipping wheel...') unzip_file(dist, output_dir) print('Finding ELF dependencies...') main_binary = 'duckling.cpython-{0}-{1}-linux-gnu.so'.format( get_abi_tag().replace('cp', ''), PLATFORM_ARCH) output_library = osp.join(output_dir, 'duckling') binary_path = osp.join(output_library, main_binary) ld_tree = lddtree(binary_path) tree_libs = ld_tree['libs'] binary_queue = [(n, main_binary) for n in ld_tree['needed']] binary_paths = {main_binary: binary_path} binary_dependencies = {} while binary_queue != []: library, parent = binary_queue.pop(0) library_info = tree_libs[library] print(library) print(library_info) if (library_info['path'].startswith('/lib') and not library.startswith('libpcre')): # Omit glibc/gcc/system libraries continue parent_dependencies = binary_dependencies.get(parent, []) parent_dependencies.append(library) binary_dependencies[parent] = parent_dependencies if library in binary_paths: continue binary_paths[library] = library_info['path'] binary_queue += [(n, library) for n in library_info['needed']] print('Copying dependencies to wheel directory') new_libraries_path = osp.join(output_dir, 'duckling.libs') os.makedirs(new_libraries_path) new_names = {main_binary: binary_path} for library in binary_paths: if library != main_binary: library_path = binary_paths[library] new_library_path = patch_new_path(library_path, new_libraries_path) print('{0} -> {1}'.format(library, new_library_path)) shutil.copyfile(library_path, new_library_path) new_names[library] = new_library_path print('Updating dependency names by new files') for library in binary_paths: if library != main_binary: if library not in binary_dependencies: continue library_dependencies = binary_dependencies[library] new_library_name = new_names[library] for dep in library_dependencies: new_dep = osp.basename(new_names[dep]) print('{0}: {1} -> {2}'.format(library, dep, new_dep)) subprocess.check_output( [ patchelf, '--replace-needed', dep, new_dep, new_library_name ], cwd=new_libraries_path) print('Updating library rpath') subprocess.check_output( [ patchelf, '--set-rpath', "$ORIGIN", new_library_name ], cwd=new_libraries_path) subprocess.check_output( [ patchelf, '--print-rpath', new_library_name ], cwd=new_libraries_path) print("Update main library dependencies") library_dependencies = binary_dependencies[main_binary] for dep in library_dependencies: new_dep = osp.basename(new_names[dep]) print('{0}: {1} -> {2}'.format(main_binary, dep, new_dep)) subprocess.check_output( [ patchelf, '--replace-needed', dep, new_dep, main_binary ], cwd=output_library) print('Update main library rpath') subprocess.check_output( [ patchelf, '--set-rpath', "$ORIGIN:$ORIGIN/../duckling.libs", binary_path ], cwd=output_library ) print('Update RECORD file in wheel') dist_info = osp.join( output_dir, 'pyduckling_native-{0}.dist-info'.format(version)) record_file = osp.join(dist_info, 'RECORD') with open(record_file, 'w') as f: for root, _, files in os.walk(output_dir): for this_file in files: full_file = osp.join(root, this_file) rel_file = osp.relpath(full_file, output_dir) if full_file == record_file: f.write('{0},,\n'.format(rel_file)) else: digest, size = rehash(full_file) f.write('{0},{1},{2}\n'.format(rel_file, digest, size)) print('Compressing wheel') shutil.make_archive(dist, 'zip', output_dir) os.remove(dist) shutil.move('{0}.zip'.format(dist), dist) shutil.rmtree(output_dir)
import os, sys, shutil, unittest, tempfile, tarfile, virtualenv, warnings from wheel.bdist_wheel import get_abi_tag, get_platform from packaging.tags import interpreter_name, interpreter_version sys.path.insert(0, "src") from from_file import versions_from_file import common pyver_major = "py%d" % sys.version_info[0] pyver = "py%d.%d" % sys.version_info[:2] # For binary wheels with native code impl, impl_ver = interpreter_name(), interpreter_version() abi = get_abi_tag() try: plat = get_platform(None) except TypeError: # wheel < 0.34 plat = get_platform() class _Invocations(common.Common): def setUp(self): if False: # when debugging, put the generated files in a predictable place self.testdir = os.path.abspath("t") if os.path.exists(self.testdir): return os.mkdir(self.testdir) else: self.testdir = tempfile.mkdtemp() os.mkdir(self.subpath("cache"))
def get_tag(self): # bdist sets self.plat_name if unset, we should only use it for purepy # wheels if the user supplied it. if self.plat_name_supplied: plat_name = self.plat_name elif self.root_is_pure: plat_name = 'any' else: # macosx contains system version in platform name so need special handle if self.plat_name and not self.plat_name.startswith("macosx"): plat_name = self.plat_name else: # on macosx always limit the platform name to comply with any # c-extension modules in bdist_dir, since the user can specify # a higher MACOSX_DEPLOYMENT_TARGET via tools like CMake # on other platforms, and on macosx if there are no c-extension # modules, use the default platform name. plat_name = get_platform(self.bdist_dir) if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647: plat_name = 'linux_i686' # To allow uploading to pypi, we need the wheel name # to contain 'manylinux1'. # The wheel which will be uploaded to pypi will be # built on RHEL7, so it doesn't completely qualify for # manylinux1 support, but it's the minimum requirement # for building Qt. We only enable this for x64 limited # api builds (which are the only ones uploaded to # pypi). # TODO: Add actual distro detection, instead of # relying on limited_api option. if (plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize > 2147483647 and (self.py_limited_api or sys.version_info[0] == 2)): plat_name = 'manylinux1_x86_64' plat_name = plat_name.replace('-', '_').replace('.', '_') if self.root_is_pure: if self.universal: impl = 'py2.py3' else: impl = self.python_tag tag = (impl, 'none', plat_name) else: impl_name = tags.interpreter_name() impl_ver = tags.interpreter_version() impl = impl_name + impl_ver # We don't work on CPython 3.1, 3.0. if self.py_limited_api and (impl_name + impl_ver).startswith('cp3'): impl = self.py_limited_api abi_tag = "abi3" if sys.platform != "win32" else "none" else: abi_tag = str(get_abi_tag()).lower() tag = (impl, abi_tag, plat_name) supported_tags = [(t.interpreter, t.abi, t.platform) for t in tags.sys_tags()] # XXX switch to this alternate implementation for non-pure: if (self.py_limited_api) or (plat_name in ('manylinux1_x86_64') and sys.version_info[0] == 2): return tag assert tag in supported_tags, ( "would build wheel with unsupported tag {}".format(tag)) return tag
def main(): """Console script function for casa6_install.""" description = """ casa6_install will download the latest Py36 casatool whl, repack and install it under Py37/38. Optionally, other casa6 components (casaplotms etc.) can also be installed along the way. This CLI tools provide a temprory workaround for install casa6 within Py>36 interpreter before the incoming official support from NRAO. Use this with your own risk and full functions of casa6 is not gauraranteed! tested on macOS10.15 and Ubuntu20.04 """ parser = argparse.ArgumentParser( description=description, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('--user', dest="user", action="store_true", help="pass --user to pip") parser.add_argument('-u', '--upgrade', dest="upgrade", action="store_true", help="pass --upgrade to pip") parser.add_argument('--no-deps', '--no-dependencies', dest="nodeps", action="store_true", help="pass --non-deps to pip") parser.add_argument('-c', '--core', dest="core", action="store_true", help="""only install casatools/casatasks by default, most casa6 components will be installed: casatools,casatask,casashell,casaplotms, etc, some of which might not work properly yet""") parser.add_argument( '-d', '--dir', type=str, dest="workdir", help='select working directory (instead of the default /tmp') args = parser.parse_args() print("check your platform:") platform = '{}{}-{}'.format(get_abbr_impl(), get_impl_ver(), get_abi_tag()) print(' {}'.format(sys.executable)) print(' {}'.format(platform)) if args.workdir is None: workdir = '/tmp' else: workdir = args.workdir whl_path = download_casatools(version='latest', workdir='/tmp') casatools_path = casatools_repack(whl_path, abi=None, workdir='/tmp') if args.core == True: select = 'core' else: select = 'full' casa6_install(casatools_path, select=select, user=args.user, upgrade=args.upgrade, nodeps=args.nodeps) return 0
def casatools_repack(whlname, abi=None, workdir='/tmp'): """ repack a Py37 casatools whl for Py37/38 Usage: casatools_repack(casatools-6.1.0.79-cp36-cp36m-macosx_10_15_x86_64.whl,abi='cp38') casatools_repack(casatools-6.1.0.79-cp36-cp36m-macosx_10_15_x86_64.whl,abi='cp37m') """ if abi is None: abi = get_abi_tag() if abi == 'cp36m': # do nothing them return whlname # Step 1: wheel unpack .whl # https://github.com/pypa/wheel/blob/master/src/wheel/cli/unpack.py whl_unpack(whlname, dest=workdir) wf = WheelFile(whlname) namever = wf.parsed_filename.group('namever') dirname = os.path.join(workdir, namever) # Step 2: modify the casacore library file (.so) names flist = glob.glob(dirname + '/casatools/__casac__/*-36m-*', recursive=True) for filename in flist: newfilename = filename.replace('-36m-', '-' + abi.replace('cp', '') + '-') print('Rename {} to {}'.format(filename, newfilename)) shutil.move(filename, newfilename) # Step 3: rename the function keyword "async" to "isasync" pyfile = dirname + '/casatools/imager.py' print('rename the kwarg "async" in {}'.format(pyfile)) with fileinput.FileInput(pyfile, inplace=True, backup='.bak') as file: for line in file: print(line.replace(', async=', ', isasync=').replace(': async', ': isasync'), end='') # Step 4: modify the .whl tag within .dist-info/WHEEL pyfile = dirname + '/' + namever + '.dist-info/WHEEL' dict_oldname = wf.parsed_filename.groupdict() dict_newname = copy.deepcopy(dict_oldname) dict_newname['pyver'] = '{}{}'.format(get_abbr_impl(), get_impl_ver()) dict_newname['abi'] = abi print('change "tag" in {}'.format(pyfile)) with fileinput.FileInput(pyfile, inplace=True, backup='.bak') as file: oldtag = '{pyver}-{abi}-{plat}'.format(**dict_oldname) newtag = '{pyver}-{abi}-{plat}'.format(**dict_newname) for line in file: print(line.replace(oldtag, newtag), end='') # Step 5: repack: whl: wheel pack * whl_path = whl_pack(dirname, workdir, None) return whl_path