Beispiel #1
0
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)
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
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)
Beispiel #11
0
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)
Beispiel #12
0
    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)
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
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)
Beispiel #17
0
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