Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
install_lib.py237 linesDownload Raw Back to command
1"""distutils.command.install_lib2 3Implements the Distutils 'install_lib' command4(install all Python modules)."""5 6import importlib.util7import os8import sys9 10from ..core import Command11from ..errors import DistutilsOptionError12 13# Extension for Python source files.14PYTHON_SOURCE_EXTENSION = ".py"15 16 17class install_lib(Command):18    description = "install all Python modules (extensions and pure Python)"19 20    # The byte-compilation options are a tad confusing.  Here are the21    # possible scenarios:22    #   1) no compilation at all (--no-compile --no-optimize)23    #   2) compile .pyc only (--compile --no-optimize; default)24    #   3) compile .pyc and "opt-1" .pyc (--compile --optimize)25    #   4) compile "opt-1" .pyc only (--no-compile --optimize)26    #   5) compile .pyc and "opt-2" .pyc (--compile --optimize-more)27    #   6) compile "opt-2" .pyc only (--no-compile --optimize-more)28    #29    # The UI for this is two options, 'compile' and 'optimize'.30    # 'compile' is strictly boolean, and only decides whether to31    # generate .pyc files.  'optimize' is three-way (0, 1, or 2), and32    # decides both whether to generate .pyc files and what level of33    # optimization to use.34 35    user_options = [36        ('install-dir=', 'd', "directory to install to"),37        ('build-dir=', 'b', "build directory (where to install from)"),38        ('force', 'f', "force installation (overwrite existing files)"),39        ('compile', 'c', "compile .py to .pyc [default]"),40        ('no-compile', None, "don't compile .py files"),41        (42            'optimize=',43            'O',44            "also compile with optimization: -O1 for \"python -O\", "45            "-O2 for \"python -OO\", and -O0 to disable [default: -O0]",46        ),47        ('skip-build', None, "skip the build steps"),48    ]49 50    boolean_options = ['force', 'compile', 'skip-build']51    negative_opt = {'no-compile': 'compile'}52 53    def initialize_options(self):54        # let the 'install' command dictate our installation directory55        self.install_dir = None56        self.build_dir = None57        self.force = 058        self.compile = None59        self.optimize = None60        self.skip_build = None61 62    def finalize_options(self):63        # Get all the information we need to install pure Python modules64        # from the umbrella 'install' command -- build (source) directory,65        # install (target) directory, and whether to compile .py files.66        self.set_undefined_options(67            'install',68            ('build_lib', 'build_dir'),69            ('install_lib', 'install_dir'),70            ('force', 'force'),71            ('compile', 'compile'),72            ('optimize', 'optimize'),73            ('skip_build', 'skip_build'),74        )75 76        if self.compile is None:77            self.compile = True78        if self.optimize is None:79            self.optimize = False80 81        if not isinstance(self.optimize, int):82            try:83                self.optimize = int(self.optimize)84                if self.optimize not in (0, 1, 2):85                    raise AssertionError86            except (ValueError, AssertionError):87                raise DistutilsOptionError("optimize must be 0, 1, or 2")88 89    def run(self):90        # Make sure we have built everything we need first91        self.build()92 93        # Install everything: simply dump the entire contents of the build94        # directory to the installation directory (that's the beauty of95        # having a build directory!)96        outfiles = self.install()97 98        # (Optionally) compile .py to .pyc99        if outfiles is not None and self.distribution.has_pure_modules():100            self.byte_compile(outfiles)101 102    # -- Top-level worker functions ------------------------------------103    # (called from 'run()')104 105    def build(self):106        if not self.skip_build:107            if self.distribution.has_pure_modules():108                self.run_command('build_py')109            if self.distribution.has_ext_modules():110                self.run_command('build_ext')111 112    def install(self):113        if os.path.isdir(self.build_dir):114            outfiles = self.copy_tree(self.build_dir, self.install_dir)115        else:116            self.warn(117                "'%s' does not exist -- no Python modules to install" % self.build_dir118            )119            return120        return outfiles121 122    def byte_compile(self, files):123        if sys.dont_write_bytecode:124            self.warn('byte-compiling is disabled, skipping.')125            return126 127        from ..util import byte_compile128 129        # Get the "--root" directory supplied to the "install" command,130        # and use it as a prefix to strip off the purported filename131        # encoded in bytecode files.  This is far from complete, but it132        # should at least generate usable bytecode in RPM distributions.133        install_root = self.get_finalized_command('install').root134 135        if self.compile:136            byte_compile(137                files,138                optimize=0,139                force=self.force,140                prefix=install_root,141                dry_run=self.dry_run,142            )143        if self.optimize > 0:144            byte_compile(145                files,146                optimize=self.optimize,147                force=self.force,148                prefix=install_root,149                verbose=self.verbose,150                dry_run=self.dry_run,151            )152 153    # -- Utility methods -----------------------------------------------154 155    def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir):156        if not has_any:157            return []158 159        build_cmd = self.get_finalized_command(build_cmd)160        build_files = build_cmd.get_outputs()161        build_dir = getattr(build_cmd, cmd_option)162 163        prefix_len = len(build_dir) + len(os.sep)164        outputs = []165        for file in build_files:166            outputs.append(os.path.join(output_dir, file[prefix_len:]))167 168        return outputs169 170    def _bytecode_filenames(self, py_filenames):171        bytecode_files = []172        for py_file in py_filenames:173            # Since build_py handles package data installation, the174            # list of outputs can contain more than just .py files.175            # Make sure we only report bytecode for the .py files.176            ext = os.path.splitext(os.path.normcase(py_file))[1]177            if ext != PYTHON_SOURCE_EXTENSION:178                continue179            if self.compile:180                bytecode_files.append(181                    importlib.util.cache_from_source(py_file, optimization='')182                )183            if self.optimize > 0:184                bytecode_files.append(185                    importlib.util.cache_from_source(186                        py_file, optimization=self.optimize187                    )188                )189 190        return bytecode_files191 192    # -- External interface --------------------------------------------193    # (called by outsiders)194 195    def get_outputs(self):196        """Return the list of files that would be installed if this command197        were actually run.  Not affected by the "dry-run" flag or whether198        modules have actually been built yet.199        """200        pure_outputs = self._mutate_outputs(201            self.distribution.has_pure_modules(),202            'build_py',203            'build_lib',204            self.install_dir,205        )206        if self.compile:207            bytecode_outputs = self._bytecode_filenames(pure_outputs)208        else:209            bytecode_outputs = []210 211        ext_outputs = self._mutate_outputs(212            self.distribution.has_ext_modules(),213            'build_ext',214            'build_lib',215            self.install_dir,216        )217 218        return pure_outputs + bytecode_outputs + ext_outputs219 220    def get_inputs(self):221        """Get the list of files that are input to this command, ie. the222        files that get installed as they are named in the build tree.223        The files in this list correspond one-to-one to the output224        filenames returned by 'get_outputs()'.225        """226        inputs = []227 228        if self.distribution.has_pure_modules():229            build_py = self.get_finalized_command('build_py')230            inputs.extend(build_py.get_outputs())231 232        if self.distribution.has_ext_modules():233            build_ext = self.get_finalized_command('build_ext')234            inputs.extend(build_ext.get_outputs())235 236        return inputs237 
codekingpro/portable-devtools · Team Ai