def control_to_metadata(control_dir, wheel_dir): """Convert deb control to METADATA file.""" ctrl_info = read_control(control_dir) pkg_name = ctrl_info['Package'].replace('-', '_') pkg_version = re.search(r'\d.*', ctrl_info['Version'].replace('-', '_')) pkg_string = "%s-%s" % (pkg_name, pkg_version) metadata = Message() metadata.add_header('Metadata-Version', '2.0') metadata['Name'] = ctrl_info['Package'] metadata['Version'] = pkg_version metadata['Home-page'] = ctrl_info['Homepage'] # get maintainer name and email maintainer_pattern = r'\s*(?P<maintainer>.*?)\s*?\<(?P<m_email>.*?)\>' re_results = re.search(maintainer_pattern, ctrl_info['Maintainer']) metadata['Author'] = re_results.group('maintainer') metadata['Author-email'] = re_results.group('m_email') metadata['Summary'] = ctrl_info['Description'].split('\n', 1)[0] metadata['Description'] = ctrl_info['Description'] # Write wheelfile dist_info_dir = wheel_dir + "/" + pkg_string + ".dist-info" os.mkdir(dist_info_dir) metadata_path = os.path.join(dist_info_dir, 'METADATA') write_pkg_info(metadata_path, metadata) return (pkg_name, pkg_version)
def copy_file(filename, destination): """Copy the file and put the correct tag""" print("Updating file %s" % filename) out_dir = os.path.abspath(destination) tags = filename[:-4].split("-") tags[-2] = tags[-2].replace("m", "") new_name = "-".join(tags) + ".whl" wheel_flag = "-".join(tags[2:]) with InWheelCtx(os.path.join(destination, filename)) as ctx: info_fname = os.path.join(_dist_info_dir(ctx.path), 'WHEEL') infos = pkginfo.read_pkg_info(info_fname) print("Current Tags: ", ", ".join([v for k, v in infos.items() if k == "Tag"])) print("Adding Tag", wheel_flag) del infos['Tag'] infos.add_header('Tag', wheel_flag) pkginfo.write_pkg_info(info_fname, infos) ctx.out_wheel = os.path.join(out_dir, new_name) print("Saving new wheel into %s" % ctx.out_wheel)
def build_wheel(self, wheel_directory, config_settings=None, metadata_directory=None): requirements_path = Path('requirements.txt') if not requirements_path.exists(): raise ValueError('"requirements.txt" file must be present when using setup_requirements build backend') result_basename = super().build_wheel( wheel_directory, config_settings=config_settings, metadata_directory=metadata_directory ) wheel_file = Path(wheel_directory) / result_basename with zipfile.ZipFile(wheel_file) as zf: metas = [f for f in zf.infolist() if os.path.basename(f.filename) == 'METADATA'] assert len(metas) == 1, 'METADATA file not found in final wheel file' meta = metas[0] info = pkginfo.read_pkg_info_bytes(zf.read(meta)) for requirement in parse_requirements(requirements_path.read_text()): info['Requires-Dist'] = str(requirement) with tempfile.NamedTemporaryFile() as tmp: pkginfo.write_pkg_info(tmp.name, info) tmp.seek(0) new_meta = tmp.read() zip_overwrite(wheel_file, meta, new_meta) return result_basename
def add_requirements(self, metadata_path): """Add additional requirements from setup.cfg to file metadata_path""" additional = list(self.setupcfg_requirements()) if not additional: return pkg_info = read_pkg_info(metadata_path) if 'Provides-Extra' in pkg_info or 'Requires-Dist' in pkg_info: warnings.warn('setup.cfg requirements overwrite values from setup.py') del pkg_info['Provides-Extra'] del pkg_info['Requires-Dist'] for k, v in additional: pkg_info[k] = v write_pkg_info(metadata_path, pkg_info)
def add_requirements(self, metadata_path): """Add additional requirements from setup.cfg to file metadata_path""" additional = list(self.setupcfg_requirements()) if not additional: return pkg_info = read_pkg_info(metadata_path) if 'Provides-Extra' in pkg_info or 'Requires-Dist' in pkg_info: warnings.warn( 'setup.cfg requirements overwrite values from setup.py') del pkg_info['Provides-Extra'] del pkg_info['Requires-Dist'] for k, v in additional: pkg_info[k] = v write_pkg_info(metadata_path, pkg_info)
def add_platforms(wheel_ctx, platforms): """Add platform tags `platforms` to a wheel Add any platform tags in `platforms` that are missing to wheel_ctx's filename and ``WHEEL`` file. Parameters ---------- wheel_ctx : InWheelCtx An open wheel context platforms : iterable platform tags to add to wheel filename and WHEEL tags - e.g. ``('macosx_10_9_intel', 'macosx_10_9_x86_64') """ info_fname = pjoin(_dist_info_dir(wheel_ctx.path), 'WHEEL') info = read_pkg_info(info_fname) if info['Root-Is-Purelib'] == 'true': raise WheelToolsError('Cannot add platforms to pure wheel') # Check what tags we have if wheel_ctx.out_wheel is None: in_wheel = wheel_ctx.in_wheel else: raise NotImplementedError() parsed_fname = WHEEL_INFO_RE(basename(in_wheel)) in_fname_tags = parsed_fname.groupdict()['plat'].split('.') extra_fname_tags = [tag for tag in platforms if tag not in in_fname_tags] in_wheel_base, ext = splitext(basename(in_wheel)) out_wheel_base = '.'.join([in_wheel_base] + list(extra_fname_tags)) out_wheel = out_wheel_base + ext in_info_tags = [tag for name, tag in info.items() if name == 'Tag'] # Python version, C-API version combinations pyc_apis = ['-'.join(tag.split('-')[:2]) for tag in in_info_tags] # unique Python version, C-API version combinations pyc_apis = unique_by_index(pyc_apis) # Add new platform tags for each Python version, C-API combination required_tags = ['-'.join(tup) for tup in product(pyc_apis, platforms)] needs_write = False for req_tag in required_tags: if req_tag in in_info_tags: continue needs_write = True info.add_header('Tag', req_tag) if needs_write: write_pkg_info(info_fname, info) # Tell context manager to write wheel on exit by setting filename wheel_ctx.out_wheel = out_wheel return wheel_ctx.out_wheel
def test_pkginfo_mangle_from(tmpdir): """Test that write_pkginfo() will not prepend a ">" to a line starting with "From".""" metadata = """\ Metadata-Version: 2.0 Name: foo From blahblah ==== Test ==== """ message = Parser().parsestr(metadata) pkginfo_file = tmpdir.join('PKGINFO') write_pkg_info(str(pkginfo_file), message) assert pkginfo_file.read_text('ascii') == metadata
def test_pkginfo_mangle_from(tmpdir): """Test that write_pkginfo() will not prepend a ">" to a line starting with "From".""" metadata = """\ Metadata-Version: 2.1 Name: foo From blahblah ==== Test ==== """ message = Parser().parsestr(metadata) pkginfo_file = tmpdir.join('PKGINFO') write_pkg_info(str(pkginfo_file), message) assert pkginfo_file.read_text('ascii') == metadata
def copy_file(filename): """Copy the file and put the correct tag""" print("Updating file %s" % filename) out_dir = os.path.abspath(DIRECTORY) tags = filename[:-4].split("-") tags[-2] = tags[-2].replace("m", "") new_name = "-".join(tags) + ".whl" wheel_flag = "-".join(tags[2:]) with InWheelCtx(os.path.join(DIRECTORY, filename)) as ctx: info_fname = os.path.join(_dist_info_dir(ctx.path), 'WHEEL') infos = pkginfo.read_pkg_info(info_fname) print("Changing Tag %s to %s" % (infos["Tag"], wheel_flag)) del infos['Tag'] infos.add_header('Tag', wheel_flag) pkginfo.write_pkg_info(info_fname, infos) ctx.out_wheel = os.path.join(out_dir, new_name) print("Saving new wheel into %s" % ctx.out_wheel)
def egg2dist(self, egginfo_path, distinfo_path): """Convert an .egg-info directory into a .dist-info directory""" def adios(p): """Appropriately delete directory, file or link.""" if os.path.exists(p) and not os.path.islink(p) and os.path.isdir( p): shutil.rmtree(p) elif os.path.exists(p): os.unlink(p) adios(distinfo_path) if not os.path.exists(egginfo_path): # There is no egg-info. This is probably because the egg-info # file/directory is not named matching the distribution name used # to name the archive file. Check for this case and report # accordingly. import glob pat = os.path.join(os.path.dirname(egginfo_path), '*.egg-info') possible = glob.glob(pat) err = "Egg metadata expected at %s but not found" % ( egginfo_path, ) if possible: alt = os.path.basename(possible[0]) err += " (%s found - possible misnamed archive file?)" % ( alt, ) raise ValueError(err) if os.path.isfile(egginfo_path): # .egg-info is a single file pkginfo_path = egginfo_path pkg_info = self._pkginfo_to_metadata(egginfo_path, egginfo_path) os.mkdir(distinfo_path) else: # .egg-info is a directory pkginfo_path = os.path.join(egginfo_path, 'PKG-INFO') pkg_info = self._pkginfo_to_metadata(egginfo_path, pkginfo_path) # ignore common egg metadata that is useless to wheel shutil.copytree(egginfo_path, distinfo_path, ignore=lambda x, y: set(( 'PKG-INFO', 'requires.txt', 'SOURCES.txt', 'not-zip-safe', ))) # delete dependency_links if it is only whitespace dependency_links_path = os.path.join(distinfo_path, 'dependency_links.txt') with open(dependency_links_path, 'r') as dependency_links_file: dependency_links = dependency_links_file.read().strip() if not dependency_links: adios(dependency_links_path) write_pkg_info(os.path.join(distinfo_path, 'METADATA'), pkg_info) # XXX deprecated. Still useful for current distribute/setuptools. metadata_path = os.path.join(distinfo_path, 'METADATA') self.add_requirements(metadata_path) # XXX intentionally a different path than the PEP. metadata_json_path = os.path.join(distinfo_path, 'metadata.json') pymeta = pkginfo_to_dict(metadata_path, distribution=self.distribution) if 'description' in pymeta: description_filename = 'DESCRIPTION.rst' description_text = pymeta.pop('description') description_path = os.path.join(distinfo_path, description_filename) with open(description_path, "wb") as description_file: description_file.write(description_text.encode('utf-8')) pymeta['extensions']['python.details']['document_names'][ 'description'] = description_filename # XXX heuristically copy any LICENSE/LICENSE.txt? license = self.license_file() if license: license_filename = 'LICENSE.txt' shutil.copy(license, os.path.join(self.distinfo_dir, license_filename)) pymeta['extensions']['python.details']['document_names'][ 'license'] = license_filename with open(metadata_json_path, "w") as metadata_json: json.dump(pymeta, metadata_json, sort_keys=True) adios(egginfo_path)
def _convert_to_generic_platform_wheel(wheel_ctx, py2_py3, additional_platforms): """Switch to generic python tags and remove ABI tags from a wheel Convert implementation specific python tags to their generic equivalent and remove all ABI tags from wheel_ctx's filename and ``WHEEL`` file. Parameters ---------- wheel_ctx : InWheelCtx An open wheel context py2_py3: Bool Wether the pyver tag shall be py2.py3 or just the one inferred from the wheel name additional_platforms : Optional[Iterable[str]] An optional iterable of additional platform to add to the wheel """ abi_tags = ['none'] wf = WheelFile(wheel_ctx.in_wheel) info_fname = _get_wheelinfo_name(wf) info = read_pkg_info(info_fname) # Check what tags we have if wheel_ctx.out_wheel is not None: out_dir = dirname(wheel_ctx.out_wheel) wheel_fname = basename(wheel_ctx.out_wheel) else: out_dir = '.' wheel_fname = basename(wheel_ctx.in_wheel) # Update wheel filename fparts = wf.parsed_filename.groupdict() platform_tags = fparts['plat'].split('.') logger.debug('Previous platform tags: %s', ', '.join(platform_tags)) if additional_platforms: platform_tags = list( sorted(set(platform_tags + [p for p in additional_platforms]))) fparts['plat'] = '.'.join(platform_tags) logger.debug('New platform tags ....: %s', ', '.join(platform_tags)) else: logger.debug('No platform tags change needed.') original_abi_tags = fparts['abi'].split('.') logger.debug('Previous ABI tags: %s', ', '.join(original_abi_tags)) if abi_tags != original_abi_tags: logger.debug('New ABI tags ....: %s', ', '.join(abi_tags)) fparts['abi'] = '.'.join(abi_tags) else: logger.debug('No ABI tags change needed.') original_pyver_tags = fparts['pyver'].split('.') logger.debug('Previous pyver tags: %s', ', '.join(original_pyver_tags)) pyver_tags = _to_generic_pyver(original_pyver_tags) if py2_py3: if len({"py2", "py3"} & set(pyver_tags)) == 0: raise ValueError("pyver_tags does not contain py2 nor py3") pyver_tags = list(sorted(set(pyver_tags + ["py2", "py3"]))) if pyver_tags != original_pyver_tags: logger.debug('New pyver tags ....: %s', ', '.join(pyver_tags)) fparts['pyver'] = '.'.join(pyver_tags) else: logger.debug('No pyver change needed.') _, ext = splitext(wheel_fname) fparts['ext'] = ext out_wheel_fname = "{namever}-{pyver}-{abi}-{plat}{ext}".format(**fparts) logger.info('Previous filename: %s', wheel_fname) if out_wheel_fname != wheel_fname: logger.info('New filename ....: %s', out_wheel_fname) else: logger.info('No filename change needed.') out_wheel = pjoin(out_dir, out_wheel_fname) # Update wheel tags in_info_tags = [tag for name, tag in info.items() if name == 'Tag'] logger.info('Previous WHEEL info tags: %s', ', '.join(in_info_tags)) # Python version, C-API version combinations pyc_apis = [] for py_ver in pyver_tags: abi = 'none' pyc_apis.append('-'.join([py_ver, abi])) # unique Python version, C-API version combinations pyc_apis = unique_by_index(pyc_apis) # Set tags for each Python version, C-API combination updated_tags = ['-'.join(tup) for tup in product(pyc_apis, platform_tags)] if updated_tags != in_info_tags: del info['Tag'] for tag in updated_tags: info.add_header('Tag', tag) logger.info('New WHEEL info tags ....: %s', ', '.join(info.get_all('Tag'))) write_pkg_info(info_fname, info) else: logger.info('No WHEEL info change needed.') return out_wheel
def add_platforms(wheel_ctx, platforms, remove_platforms=()): """Add platform tags `platforms` to a wheel Add any platform tags in `platforms` that are missing to wheel_ctx's filename and ``WHEEL`` file. Parameters ---------- wheel_ctx : InWheelCtx An open wheel context platforms : iterable platform tags to add to wheel filename and WHEEL tags - e.g. ``('macosx_10_9_intel', 'macosx_10_9_x86_64') remove_platforms : iterable platform tags to remove to the wheel filename and WHEEL tags, e.g. ``('linux_x86_64',)`` when ``('manylinux_x86_64')`` is added """ definitely_not_purelib = False info_fname = pjoin(_dist_info_dir(wheel_ctx.path), 'WHEEL') info = read_pkg_info(info_fname) # Check what tags we have if wheel_ctx.out_wheel is not None: out_dir = dirname(wheel_ctx.out_wheel) wheel_fname = basename(wheel_ctx.out_wheel) else: out_dir = '.' wheel_fname = basename(wheel_ctx.in_wheel) parsed_fname = WHEEL_INFO_RE(wheel_fname) fparts = parsed_fname.groupdict() original_fname_tags = fparts['plat'].split('.') logger.info('Previous filename tags: %s', ', '.join(original_fname_tags)) fname_tags = { tag for tag in original_fname_tags if tag not in remove_platforms } fname_tags |= set(platforms) # Can't be 'any' and another platform if 'any' in fname_tags and len(fname_tags) > 1: fname_tags.remove('any') remove_platforms.append('any') definitely_not_purelib = True if fname_tags != original_fname_tags: logger.info('New filename tags: %s', ', '.join(fname_tags)) else: logger.info('No filename tags change needed.') _, ext = splitext(wheel_fname) fparts['plat'] = '.'.join(fname_tags) fparts['ext'] = ext out_wheel_fname = "{namever}-{pyver}-{abi}-{plat}{ext}".format(**fparts) out_wheel = pjoin(out_dir, out_wheel_fname) in_info_tags = [tag for name, tag in info.items() if name == 'Tag'] logger.info('Previous WHEEL info tags: %s', ', '.join(in_info_tags)) # Python version, C-API version combinations pyc_apis = ['-'.join(tag.split('-')[:2]) for tag in in_info_tags] # unique Python version, C-API version combinations pyc_apis = unique_by_index(pyc_apis) # Add new platform tags for each Python version, C-API combination wanted_tags = ['-'.join(tup) for tup in product(pyc_apis, platforms)] new_tags = [tag for tag in wanted_tags if tag not in in_info_tags] unwanted_tags = [ '-'.join(tup) for tup in product(pyc_apis, remove_platforms) ] updated_tags = [tag for tag in in_info_tags if tag not in unwanted_tags] updated_tags += new_tags if updated_tags != in_info_tags: del info['Tag'] for tag in updated_tags: info.add_header('Tag', tag) if definitely_not_purelib: info['Root-Is-Purelib'] = 'False' logger.info('Changed wheel type to Platlib') logger.info('New WHEEL info tags: %s', ', '.join(info.get_all('Tag'))) write_pkg_info(info_fname, info) else: logger.info('No WHEEL info change needed.') return out_wheel
def add_platforms(wheel_ctx, platforms, remove_platforms=()): """Add platform tags `platforms` to a wheel Add any platform tags in `platforms` that are missing to wheel_ctx's filename and ``WHEEL`` file. Parameters ---------- wheel_ctx : InWheelCtx An open wheel context platforms : iterable platform tags to add to wheel filename and WHEEL tags - e.g. ``('macosx_10_9_intel', 'macosx_10_9_x86_64') remove_platforms : iterable platform tags to remove to the wheel filename and WHEEL tags, e.g. ``('linux_x86_64',)`` when ``('manylinux_x86_64')`` is added """ info_fname = pjoin(_dist_info_dir(wheel_ctx.path), 'WHEEL') info = read_pkg_info(info_fname) if info['Root-Is-Purelib'] == 'true': print('No need to add platforms to pure wheel - Skipping {}'.format(wheel_ctx.in_wheel)) return # Check what tags we have if wheel_ctx.out_wheel is not None: out_dir = dirname(wheel_ctx.out_wheel) wheel_fname = basename(wheel_ctx.out_wheel) else: out_dir = '.' wheel_fname = basename(wheel_ctx.in_wheel) parsed_fname = WHEEL_INFO_RE(wheel_fname) fparts = parsed_fname.groupdict() original_fname_tags = fparts['plat'].split('.') print('Previous filename tags:', ', '.join(original_fname_tags)) fname_tags = [tag for tag in original_fname_tags if tag not in remove_platforms] for platform in platforms: if platform not in fname_tags: fname_tags.append(platform) if fname_tags != original_fname_tags: print('New filename tags:', ', '.join(fname_tags)) else: print('No filename tags change needed.') wheel_base, ext = splitext(wheel_fname) fparts['plat'] = '.'.join(fname_tags) fparts['ext'] = ext out_wheel_fname = "{namever}-{pyver}-{abi}-{plat}{ext}".format(**fparts) out_wheel = pjoin(out_dir, out_wheel_fname) in_info_tags = [tag for name, tag in info.items() if name == 'Tag'] print('Previous WHEEL info tags:', ', '.join(in_info_tags)) # Python version, C-API version combinations pyc_apis = ['-'.join(tag.split('-')[:2]) for tag in in_info_tags] # unique Python version, C-API version combinations pyc_apis = unique_by_index(pyc_apis) # Add new platform tags for each Python version, C-API combination wanted_tags = ['-'.join(tup) for tup in product(pyc_apis, platforms)] new_tags = [tag for tag in wanted_tags if tag not in in_info_tags] unwanted_tags = ['-'.join(tup) for tup in product(pyc_apis, remove_platforms)] updated_tags = [tag for tag in in_info_tags if tag not in unwanted_tags] updated_tags += new_tags needs_write = updated_tags != in_info_tags if needs_write: del info['Tag'] for tag in updated_tags: info.add_header('Tag', tag) print('New WHEEL info tags:', ', '.join(info.get_all('Tag'))) write_pkg_info(info_fname, info) else: print('No WHEEL info change needed.') return out_wheel
def egg2dist(self, egginfo_path, distinfo_path): """Convert an .egg-info directory into a .dist-info directory""" def adios(p): """Appropriately delete directory, file or link.""" if os.path.exists(p) and not os.path.islink(p) and os.path.isdir(p): shutil.rmtree(p) elif os.path.exists(p): os.unlink(p) adios(distinfo_path) if not os.path.exists(egginfo_path): # There is no egg-info. This is probably because the egg-info # file/directory is not named matching the distribution name used # to name the archive file. Check for this case and report # accordingly. import glob pat = os.path.join(os.path.dirname(egginfo_path), '*.egg-info') possible = glob.glob(pat) err = "Egg metadata expected at %s but not found" % (egginfo_path,) if possible: alt = os.path.basename(possible[0]) err += " (%s found - possible misnamed archive file?)" % (alt,) raise ValueError(err) if os.path.isfile(egginfo_path): # .egg-info is a single file pkginfo_path = egginfo_path pkg_info = self._pkginfo_to_metadata(egginfo_path, egginfo_path) os.mkdir(distinfo_path) else: # .egg-info is a directory pkginfo_path = os.path.join(egginfo_path, 'PKG-INFO') pkg_info = self._pkginfo_to_metadata(egginfo_path, pkginfo_path) # ignore common egg metadata that is useless to wheel shutil.copytree(egginfo_path, distinfo_path, ignore=lambda x, y: set(('PKG-INFO', 'requires.txt', 'SOURCES.txt', 'not-zip-safe',))) # delete dependency_links if it is only whitespace dependency_links_path = os.path.join(distinfo_path, 'dependency_links.txt') with open(dependency_links_path, 'r') as dependency_links_file: dependency_links = dependency_links_file.read().strip() if not dependency_links: adios(dependency_links_path) write_pkg_info(os.path.join(distinfo_path, 'METADATA'), pkg_info) # XXX deprecated. Still useful for current distribute/setuptools. metadata_path = os.path.join(distinfo_path, 'METADATA') self.add_requirements(metadata_path) # XXX intentionally a different path than the PEP. metadata_json_path = os.path.join(distinfo_path, 'metadata.json') pymeta = pkginfo_to_dict(metadata_path, distribution=self.distribution) if 'description' in pymeta: description_filename = 'DESCRIPTION.rst' description_text = pymeta.pop('description') description_path = os.path.join(distinfo_path, description_filename) with open(description_path, "wb") as description_file: description_file.write(description_text.encode('utf-8')) pymeta['extensions']['python.details']['document_names']['description'] = description_filename # XXX heuristically copy any LICENSE/LICENSE.txt? license = self.license_file() if license: license_filename = 'LICENSE.txt' shutil.copy(license, os.path.join(self.distinfo_dir, license_filename)) pymeta['extensions']['python.details']['document_names']['license'] = license_filename with open(metadata_json_path, "w") as metadata_json: json.dump(pymeta, metadata_json, sort_keys=True) adios(egginfo_path)
def add_platforms(in_wheel, platforms, out_path=None, clobber=False): """ Add platform tags `platforms` to `in_wheel` filename and WHEEL tags Add any platform tags in `platforms` that are missing from `in_wheel` filename. Add any platform tags in `platforms` that are missing from `in_wheel` ``WHEEL`` file. Parameters ---------- in_wheel : str Filename of wheel to which to add platform tags platforms : iterable platform tags to add to wheel filename and WHEEL tags - e.g. ``('macosx_10_9_intel', 'macosx_10_9_x86_64') out_path : None or str, optional Directory to which to write new wheel. Default is directory containing `in_wheel` clobber : bool, optional If True, overwrite existing output filename, otherwise raise error Returns ------- out_wheel : None or str Absolute path of wheel file written, or None if no wheel file written. """ in_wheel = abspath(in_wheel) out_path = dirname(in_wheel) if out_path is None else abspath(out_path) wf = WheelFile(in_wheel) info_fname = _get_wheelinfo_name(wf) # Check what tags we have in_fname_tags = wf.parsed_filename.groupdict()['plat'].split('.') extra_fname_tags = [tag for tag in platforms if tag not in in_fname_tags] in_wheel_base, ext = splitext(basename(in_wheel)) out_wheel_base = '.'.join([in_wheel_base] + list(extra_fname_tags)) out_wheel = pjoin(out_path, out_wheel_base + ext) if exists(out_wheel) and not clobber: raise WheelToolsError('Not overwriting {0}; set clobber=True ' 'to overwrite'.format(out_wheel)) with InWheelCtx(in_wheel) as ctx: info = read_pkg_info(info_fname) if info['Root-Is-Purelib'] == 'true': raise WheelToolsError('Cannot add platforms to pure wheel') in_info_tags = [tag for name, tag in info.items() if name == 'Tag'] # Python version, C-API version combinations pyc_apis = ['-'.join(tag.split('-')[:2]) for tag in in_info_tags] # unique Python version, C-API version combinations pyc_apis = unique_by_index(pyc_apis) # Add new platform tags for each Python version, C-API combination required_tags = ['-'.join(tup) for tup in product(pyc_apis, platforms)] needs_write = False for req_tag in required_tags: if req_tag in in_info_tags: continue needs_write = True info.add_header('Tag', req_tag) if needs_write: write_pkg_info(info_fname, info) # Tell context manager to write wheel on exit by setting filename ctx.out_wheel = out_wheel return ctx.out_wheel
def _convert_to_generic_platform_wheel(wheel_ctx): """Switch to generic python tags and remove ABI tags from a wheel Convert implementation specific python tags to their generic equivalent and remove all ABI tags from wheel_ctx's filename and ``WHEEL`` file. Parameters ---------- wheel_ctx : InWheelCtx An open wheel context """ abi_tags = ['none'] wf = WheelFile(wheel_ctx.in_wheel) info_fname = _get_wheelinfo_name(wf) info = read_pkg_info(info_fname) # Check what tags we have if wheel_ctx.out_wheel is not None: out_dir = dirname(wheel_ctx.out_wheel) wheel_fname = basename(wheel_ctx.out_wheel) else: out_dir = '.' wheel_fname = basename(wheel_ctx.in_wheel) # Update wheel filename fparts = wf.parsed_filename.groupdict() original_platform_tags = fparts['plat'].split('.') original_abi_tags = fparts['abi'].split('.') logger.debug('Previous ABI tags: %s', ', '.join(original_abi_tags)) if abi_tags != original_abi_tags: logger.debug('New ABI tags ....: %s', ', '.join(abi_tags)) fparts['abi'] = '.'.join(abi_tags) else: logger.debug('No ABI tags change needed.') original_pyver_tags = fparts['pyver'].split('.') logger.debug('Previous pyver tags: %s', ', '.join(original_pyver_tags)) pyver_tags = _to_generic_pyver(original_pyver_tags) if pyver_tags != original_pyver_tags: logger.debug('New pyver tags ....: %s', ', '.join(pyver_tags)) fparts['pyver'] = '.'.join(pyver_tags) else: logger.debug('No pyver change needed.') _, ext = splitext(wheel_fname) fparts['ext'] = ext out_wheel_fname = "{namever}-{pyver}-{abi}-{plat}{ext}".format(**fparts) logger.info('Previous filename: %s', wheel_fname) if out_wheel_fname != wheel_fname: logger.info('New filename ....: %s', out_wheel_fname) else: logger.info('No filename change needed.') out_wheel = pjoin(out_dir, out_wheel_fname) # Update wheel tags in_info_tags = [tag for name, tag in info.items() if name == 'Tag'] logger.info('Previous WHEEL info tags: %s', ', '.join(in_info_tags)) # Python version, C-API version combinations pyc_apis = [] for tag in in_info_tags: py_ver = '.'.join(_to_generic_pyver(tag.split('-')[0].split('.'))) abi = 'none' pyc_apis.append('-'.join([py_ver, abi])) # unique Python version, C-API version combinations pyc_apis = unique_by_index(pyc_apis) # Set tags for each Python version, C-API combination updated_tags = ['-'.join(tup) for tup in product(pyc_apis, original_platform_tags)] if updated_tags != in_info_tags: del info['Tag'] for tag in updated_tags: info.add_header('Tag', tag) logger.info('New WHEEL info tags ....: %s', ', '.join(info.get_all('Tag'))) write_pkg_info(info_fname, info) else: logger.info('No WHEEL info change needed.') return out_wheel