Esempio n. 1
0
    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
Esempio n. 2
0
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
Esempio n. 3
0
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'
Esempio n. 4
0
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
    )
Esempio n. 5
0
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"))
Esempio n. 7
0
    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
Esempio n. 8
0
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
Esempio n. 9
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