예제 #1
0
 def assemble(self):
     if _check_path_overlap(self.name) and os.path.isdir(self.name):
         _rmtree(self.name)
     logger.info("Building COLLECT %s", self.tocbasename)
     os.makedirs(self.name)
     toc = add_suffix_to_extensions(self.toc)
     for inm, fnm, typ in toc:
         if not os.path.exists(fnm) or not os.path.isfile(fnm) and is_path_to_egg(fnm):
             # file is contained within python egg, it is added with the egg
             continue
         if os.pardir in os.path.normpath(inm) or os.path.isabs(inm):
             raise SystemExit('Security-Alert: try to store file outside '
                              'of dist-directory. Aborting. %r' % inm)
         tofnm = os.path.join(self.name, inm)
         todir = os.path.dirname(tofnm)
         if not os.path.exists(todir):
             os.makedirs(todir)
         if typ in ('EXTENSION', 'BINARY'):
             fnm = checkCache(fnm, strip=self.strip_binaries,
                              upx=(self.upx_binaries and (is_win or is_cygwin)),
                              dist_nm=inm)
         if typ != 'DEPENDENCY':
             shutil.copy(fnm, tofnm)
             try:
                 shutil.copystat(fnm, tofnm)
             except OSError:
                 logger.warn("failed to copy flags of %s", fnm)
         if typ in ('EXTENSION', 'BINARY'):
             os.chmod(tofnm, 0o755)
예제 #2
0
def test_add_to_suffix__extension():
    toc = [
        ('mypkg', 'lib38/site-packages/mypkg' + EXTENSION_SUFFIXES[0],
         'EXTENSION'),
    ]
    toc = utils.add_suffix_to_extensions(toc)
    assert toc == [
        ('mypkg' + EXTENSION_SUFFIXES[0],
         'lib38/site-packages/mypkg' + EXTENSION_SUFFIXES[0], 'EXTENSION'),
    ]
예제 #3
0
 def assemble(self):
     _make_clean_directory(self.name)
     logger.info("Building COLLECT %s", self.tocbasename)
     toc = add_suffix_to_extensions(self.toc)
     for inm, fnm, typ in toc:
         if not os.path.exists(
                 fnm) or not os.path.isfile(fnm) and is_path_to_egg(fnm):
             # file is contained within python egg, it is added with the egg
             continue
         if os.pardir in os.path.normpath(inm).split(os.sep) \
            or os.path.isabs(inm):
             raise SystemExit('Security-Alert: try to store file outside '
                              'of dist-directory. Aborting. %r' % inm)
         tofnm = os.path.join(self.name, inm)
         todir = os.path.dirname(tofnm)
         if not os.path.exists(todir):
             os.makedirs(todir)
         elif not os.path.isdir(todir):
             raise SystemExit(
                 "Pyinstaller needs to make a directory, but there "
                 "already is a file at that path. "
                 "The file at issue is {!r}".format(todir))
         if typ in ('EXTENSION', 'BINARY'):
             fnm = checkCache(fnm,
                              strip=self.strip_binaries,
                              upx=self.upx_binaries,
                              upx_exclude=self.upx_exclude,
                              dist_nm=inm)
         if typ != 'DEPENDENCY':
             if os.path.isdir(fnm):
                 # beacuse shutil.copy2() is the default copy function
                 # for shutil.copytree, this will also copy file metadata
                 shutil.copytree(fnm, tofnm)
             else:
                 shutil.copy(fnm, tofnm)
             try:
                 shutil.copystat(fnm, tofnm)
             except OSError:
                 logger.warning("failed to copy flags of %s", fnm)
         if typ in ('EXTENSION', 'BINARY'):
             os.chmod(tofnm, 0o755)
     logger.info("Building COLLECT %s completed successfully.",
                 self.tocbasename)
예제 #4
0
    def assemble(self):
        logger.info("Building PKG (CArchive) %s", os.path.basename(self.name))
        trash = []
        mytoc = []
        srctoc = []
        seenInms = {}
        seenFnms = {}
        seenFnms_typ = {}
        toc = add_suffix_to_extensions(self.toc)
        # 'inm'  - relative filename inside a CArchive
        # 'fnm'  - absolute filename as it is on the file system.
        for inm, fnm, typ in toc:
            # Ensure filename 'fnm' is not None or empty string. Otherwise
            # it will fail in case of 'typ' being type OPTION.
            if fnm and not os.path.isfile(fnm) and is_path_to_egg(fnm):
                # file is contained within python egg, it is added with the egg
                continue
            if typ in ('BINARY', 'EXTENSION', 'DEPENDENCY'):
                if self.exclude_binaries and typ != 'DEPENDENCY':
                    self.dependencies.append((inm, fnm, typ))
                else:
                    if typ == 'BINARY':
                        # Avoid importing the same binary extension twice. This might
                        # happen if they come from different sources (eg. once from
                        # binary dependence, and once from direct import).
                        if inm in seenInms:
                            logger.warning(
                                'Two binaries added with the same internal name.'
                            )
                            logger.warning(pprint.pformat((inm, fnm, typ)))
                            logger.warning('was placed previously at')
                            logger.warning(
                                pprint.pformat((inm, seenInms[inm],
                                                seenFnms_typ[seenInms[inm]])))
                            logger.warning('Skipping %s.' % fnm)
                            continue

                        # Warn if the same binary extension was included
                        # with multiple internal names
                        if fnm in seenFnms:
                            logger.warning(
                                'One binary added with two internal names.')
                            logger.warning(pprint.pformat((inm, fnm, typ)))
                            logger.warning('was placed previously at')
                            logger.warning(
                                pprint.pformat(
                                    (seenFnms[fnm], fnm, seenFnms_typ[fnm])))
                    seenInms[inm] = fnm
                    seenFnms[fnm] = inm
                    seenFnms_typ[fnm] = typ

                    fnm = checkCache(fnm,
                                     strip=self.strip_binaries,
                                     upx=(self.upx_binaries
                                          and (is_win or is_cygwin)),
                                     dist_nm=inm)

                    mytoc.append((inm, fnm, self.cdict.get(typ, 0),
                                  self.xformdict.get(typ, 'b')))
            elif typ == 'OPTION':
                mytoc.append((inm, '', 0, 'o'))
            elif typ in ('PYSOURCE', 'PYMODULE'):
                # collect sourcefiles and module in a toc of it's own
                # which will not be sorted.
                srctoc.append((inm, fnm, self.cdict[typ], self.xformdict[typ]))
            else:
                mytoc.append((inm, fnm, self.cdict.get(typ, 0),
                              self.xformdict.get(typ, 'b')))

        # Bootloader has to know the name of Python library. Pass python libname to CArchive.
        pylib_name = os.path.basename(bindepend.get_python_library_path())

        # Sort content alphabetically by type and name to support
        # reproducible builds.
        mytoc.sort(key=itemgetter(3, 0))
        # Do *not* sort modules and scripts, as their order is important.
        # TODO: Think about having all modules first and then all scripts.
        archive = CArchiveWriter(self.name,
                                 srctoc + mytoc,
                                 pylib_name=pylib_name)

        for item in trash:
            os.remove(item)
        logger.info("Building PKG (CArchive) %s completed successfully.",
                    os.path.basename(self.name))
예제 #5
0
    def assemble(self):
        logger.info("Building PKG (CArchive) %s", os.path.basename(self.name))
        trash = []
        mytoc = []
        seenInms = {}
        seenFnms = {}
        seenFnms_typ = {}
        toc = add_suffix_to_extensions(self.toc)
        # 'inm'  - relative filename inside a CArchive
        # 'fnm'  - absolute filename as it is on the file system.
        for inm, fnm, typ in toc:
            # Ensure filename 'fnm' is not None or empty string. Otherwise
            # it will fail in case of 'typ' being type OPTION.
            if fnm and not os.path.isfile(fnm) and is_path_to_egg(fnm):
                # file is contained within python egg, it is added with the egg
                continue
            if typ in ('BINARY', 'EXTENSION', 'DEPENDENCY'):
                if self.exclude_binaries and typ != 'DEPENDENCY':
                    self.dependencies.append((inm, fnm, typ))
                else:
                    if typ == 'BINARY':
                        # Avoid importing the same binary extension twice. This might
                        # happen if they come from different sources (eg. once from
                        # binary dependence, and once from direct import).
                        if inm in seenInms:
                            logger.warn('Two binaries added with the same internal name.')
                            logger.warn(pprint.pformat((inm, fnm, typ)))
                            logger.warn('was placed previously at')
                            logger.warn(pprint.pformat((inm, seenInms[inm], seenFnms_typ[seenInms[inm]])))
                            logger.warn('Skipping %s.' % fnm)
                            continue

                        # Warn if the same binary extension was included
                        # with multiple internal names
                        if fnm in seenFnms:
                            logger.warn('One binary added with two internal names.')
                            logger.warn(pprint.pformat((inm, fnm, typ)))
                            logger.warn('was placed previously at')
                            logger.warn(pprint.pformat((seenFnms[fnm], fnm, seenFnms_typ[fnm])))
                    seenInms[inm] = fnm
                    seenFnms[fnm] = inm
                    seenFnms_typ[fnm] = typ

                    fnm = checkCache(fnm, strip=self.strip_binaries,
                                     upx=(self.upx_binaries and (is_win or is_cygwin)),
                                     dist_nm=inm)

                    mytoc.append((inm, fnm, self.cdict.get(typ, 0),
                                  self.xformdict.get(typ, 'b')))
            elif typ == 'OPTION':
                mytoc.append((inm, '', 0, 'o'))
            else:
                mytoc.append((inm, fnm, self.cdict.get(typ, 0), self.xformdict.get(typ, 'b')))

        # Bootloader has to know the name of Python library. Pass python libname to CArchive.
        pylib_name = os.path.basename(bindepend.get_python_library_path())
        archive = CArchiveWriter(pylib_name=pylib_name)

        archive.build(self.name, mytoc)
        for item in trash:
            os.remove(item)
예제 #6
0
    def assemble(self):
        if _check_path_overlap(self.name) and os.path.isdir(self.name):
            _rmtree(self.name)
        logger.info("Building BUNDLE %s", self.tocbasename)

        # Create a minimal Mac bundle structure
        os.makedirs(os.path.join(self.name, "Contents", "MacOS"))
        os.makedirs(os.path.join(self.name, "Contents", "Resources"))
        os.makedirs(os.path.join(self.name, "Contents", "Frameworks"))

        # Copy icns icon to Resources directory.
        if os.path.exists(self.icon):
            shutil.copy(self.icon, os.path.join(self.name, 'Contents', 'Resources'))
        else:
            logger.warning("icon not found %s", self.icon)

        # Key/values for a minimal Info.plist file
        info_plist_dict = {"CFBundleDisplayName": self.appname,
                           "CFBundleName": self.appname,

                           # Required by 'codesign' utility.
                           # The value for CFBundleIdentifier is used as the default unique
                           # name of your program for Code Signing purposes.
                           # It even identifies the APP for access to restricted OS X areas
                           # like Keychain.
                           #
                           # The identifier used for signing must be globally unique. The usal
                           # form for this identifier is a hierarchical name in reverse DNS
                           # notation, starting with the toplevel domain, followed by the
                           # company name, followed by the department within the company, and
                           # ending with the product name. Usually in the form:
                           #   com.mycompany.department.appname
                           # Cli option --osx-bundle-identifier sets this value.
                           "CFBundleIdentifier": self.bundle_identifier,

                           # Fix for #156 - 'MacOS' must be in the name - not sure why
                           "CFBundleExecutable": 'MacOS/%s' % os.path.basename(self.exename),
                           "CFBundleIconFile": os.path.basename(self.icon),
                           "CFBundleInfoDictionaryVersion": "6.0",
                           "CFBundlePackageType": "APPL",
                           "CFBundleShortVersionString": self.version,

                           }

        # Set some default values.
        # But they still can be overwritten by the user.
        if self.console:
            # Setting EXE console=True implies LSBackgroundOnly=True.
            info_plist_dict['LSBackgroundOnly'] = True
        else:
            # Let's use high resolution by default.
            info_plist_dict['NSHighResolutionCapable'] = True

        # Merge info_plist settings from spec file
        if isinstance(self.info_plist, dict) and self.info_plist:
            info_plist_dict.update(self.info_plist)

        plist_filename = os.path.join(self.name, "Contents", "Info.plist")
        with open(plist_filename, "wb") as plist_fh:
            plistlib.dump(info_plist_dict, plist_fh)

        links = []
        toc = add_suffix_to_extensions(self.toc)
        for inm, fnm, typ in toc:
            # Copy files from cache. This ensures that are used files with relative
            # paths to dynamic library dependencies (@executable_path)
            base_path = inm.split('/', 1)[0]
            if typ in ('EXTENSION', 'BINARY'):
                fnm = checkCache(fnm, strip=self.strip, upx=self.upx,
                                 upx_exclude=self.upx_exclude, dist_nm=inm)
            # Add most data files to a list for symlinking later.
            if typ == 'DATA' and base_path not in ('PySide2', 'PyQt5'):
                links.append((inm, fnm))
            else:
                tofnm = os.path.join(self.name, "Contents", "MacOS", inm)
                todir = os.path.dirname(tofnm)
                if not os.path.exists(todir):
                    os.makedirs(todir)
                if os.path.isdir(fnm):
                    # beacuse shutil.copy2() is the default copy function
                    # for shutil.copytree, this will also copy file metadata
                    shutil.copytree(fnm, tofnm)
                else:
                    shutil.copy(fnm, tofnm)

        logger.info('moving BUNDLE data files to Resource directory')

        # Mac OS X Code Signing does not work when .app bundle contains
        # data files in dir ./Contents/MacOS.
        #
        # Put all data files in ./Resources and create symlinks in ./MacOS.
        bin_dir = os.path.join(self.name, 'Contents', 'MacOS')
        res_dir = os.path.join(self.name, 'Contents', 'Resources')
        for inm, fnm in links:
            tofnm = os.path.join(res_dir, inm)
            todir = os.path.dirname(tofnm)
            if not os.path.exists(todir):
                os.makedirs(todir)
            if os.path.isdir(fnm):
                # beacuse shutil.copy2() is the default copy function
                # for shutil.copytree, this will also copy file metadata
                shutil.copytree(fnm, tofnm)
            else:
                shutil.copy(fnm, tofnm)
            base_path = os.path.split(inm)[0]
            if base_path:
                if not os.path.exists(os.path.join(bin_dir, inm)):
                    path = ''
                    for part in iter(base_path.split(os.path.sep)):
                        # Build path from previous path and the next part of the base path
                        path = os.path.join(path, part)
                        try:
                            relative_source_path = os.path.relpath(os.path.join(res_dir, path),
                                                                   os.path.split(os.path.join(bin_dir, path))[0])
                            dest_path = os.path.join(bin_dir, path)
                            os.symlink(relative_source_path, dest_path)
                            break
                        except FileExistsError:
                            pass
                    if not os.path.exists(os.path.join(bin_dir, inm)):
                        relative_source_path = os.path.relpath(os.path.join(res_dir, inm),
                                                               os.path.split(os.path.join(bin_dir, inm))[0])
                        dest_path = os.path.join(bin_dir, inm)
                        os.symlink(relative_source_path, dest_path)
            else:  # If path is empty, e.g., a top level file, try to just symlink the file
                os.symlink(os.path.relpath(os.path.join(res_dir, inm),
                                           os.path.split(os.path.join(bin_dir, inm))[0]),
                           os.path.join(bin_dir, inm))
예제 #7
0
파일: api.py 프로젝트: ChaiZQ/pyinstaller
    def assemble(self):
        logger.info("Building PKG (CArchive) %s", os.path.basename(self.name))
        trash = []
        mytoc = []
        srctoc = []
        seenInms = {}
        seenFnms = {}
        seenFnms_typ = {}
        toc = add_suffix_to_extensions(self.toc)
        # 'inm'  - relative filename inside a CArchive
        # 'fnm'  - absolute filename as it is on the file system.
        for inm, fnm, typ in toc:
            # Ensure filename 'fnm' is not None or empty string. Otherwise
            # it will fail in case of 'typ' being type OPTION.
            if fnm and not os.path.isfile(fnm) and is_path_to_egg(fnm):
                # file is contained within python egg, it is added with the egg
                continue
            if typ in ('BINARY', 'EXTENSION', 'DEPENDENCY'):
                if self.exclude_binaries and typ != 'DEPENDENCY':
                    self.dependencies.append((inm, fnm, typ))
                else:
                    if typ == 'BINARY':
                        # Avoid importing the same binary extension twice. This might
                        # happen if they come from different sources (eg. once from
                        # binary dependence, and once from direct import).
                        if inm in seenInms:
                            logger.warning('Two binaries added with the same internal name.')
                            logger.warning(pprint.pformat((inm, fnm, typ)))
                            logger.warning('was placed previously at')
                            logger.warning(pprint.pformat((inm, seenInms[inm], seenFnms_typ[seenInms[inm]])))
                            logger.warning('Skipping %s.' % fnm)
                            continue

                        # Warn if the same binary extension was included
                        # with multiple internal names
                        if fnm in seenFnms:
                            logger.warning('One binary added with two internal names.')
                            logger.warning(pprint.pformat((inm, fnm, typ)))
                            logger.warning('was placed previously at')
                            logger.warning(pprint.pformat((seenFnms[fnm], fnm, seenFnms_typ[fnm])))
                    seenInms[inm] = fnm
                    seenFnms[fnm] = inm
                    seenFnms_typ[fnm] = typ

                    fnm = checkCache(fnm, strip=self.strip_binaries,
                                     upx=(self.upx_binaries and (is_win or is_cygwin)),
                                     dist_nm=inm)

                    mytoc.append((inm, fnm, self.cdict.get(typ, 0),
                                  self.xformdict.get(typ, 'b')))
            elif typ == 'OPTION':
                mytoc.append((inm, '', 0, 'o'))
            elif typ in ('PYSOURCE', 'PYMODULE'):
                # collect sourcefiles and module in a toc of it's own
                # which will not be sorted.
                srctoc.append((inm, fnm, self.cdict[typ], self.xformdict[typ]))
            else:
                mytoc.append((inm, fnm, self.cdict.get(typ, 0), self.xformdict.get(typ, 'b')))

        # Bootloader has to know the name of Python library. Pass python libname to CArchive.
        pylib_name = os.path.basename(bindepend.get_python_library_path())

        # Sort content alphabetically by type and name to support
        # reproducible builds.
        mytoc.sort(key=itemgetter(3, 0))
        # Do *not* sort modules and scripts, as their order is important.
        # TODO: Think about having all modules first and then all scripts.
        archive = CArchiveWriter(self.name, srctoc + mytoc,
                                 pylib_name=pylib_name)

        for item in trash:
            os.remove(item)
        logger.info("Building PKG (CArchive) %s completed successfully.",
                    os.path.basename(self.name))