ยปCore Development>Code coverage>Lib/packaging/command/install_lib.py

Python code coverage for Lib/packaging/command/install_lib.py

#countcontent
1n/a"""Install all modules (extensions and pure Python)."""
2n/a
3n/aimport os
4n/aimport imp
5n/a
6n/afrom packaging import logger
7n/afrom packaging.command.cmd import Command
8n/afrom packaging.errors import PackagingOptionError
9n/a
10n/a
11n/a# Extension for Python source files.
12n/a# XXX dead code? most of the codebase checks for literal '.py'
13n/aif hasattr(os, 'extsep'):
14n/a PYTHON_SOURCE_EXTENSION = os.extsep + "py"
15n/aelse:
16n/a PYTHON_SOURCE_EXTENSION = ".py"
17n/a
18n/a
19n/aclass install_lib(Command):
20n/a
21n/a description = "install all modules (extensions and pure Python)"
22n/a
23n/a # The options for controlling byte compilation are two independent sets:
24n/a # 'compile' is strictly boolean, and only decides whether to
25n/a # generate .pyc files. 'optimize' is three-way (0, 1, or 2), and
26n/a # decides both whether to generate .pyo files and what level of
27n/a # optimization to use.
28n/a
29n/a user_options = [
30n/a ('install-dir=', 'd', "directory to install to"),
31n/a ('build-dir=', 'b', "build directory (where to install from)"),
32n/a ('force', 'f', "force installation (overwrite existing files)"),
33n/a ('compile', 'c', "compile .py to .pyc [default]"),
34n/a ('no-compile', None, "don't compile .py files"),
35n/a ('optimize=', 'O',
36n/a "also compile with optimization: -O1 for \"python -O\", "
37n/a "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
38n/a ('skip-build', None, "skip the build steps"),
39n/a ]
40n/a
41n/a boolean_options = ['force', 'compile', 'skip-build']
42n/a
43n/a negative_opt = {'no-compile': 'compile'}
44n/a
45n/a def initialize_options(self):
46n/a # let the 'install_dist' command dictate our installation directory
47n/a self.install_dir = None
48n/a self.build_dir = None
49n/a self.force = False
50n/a self.compile = None
51n/a self.optimize = None
52n/a self.skip_build = None
53n/a
54n/a def finalize_options(self):
55n/a # Get all the information we need to install pure Python modules
56n/a # from the umbrella 'install_dist' command -- build (source) directory,
57n/a # install (target) directory, and whether to compile .py files.
58n/a self.set_undefined_options('install_dist',
59n/a ('build_lib', 'build_dir'),
60n/a ('install_lib', 'install_dir'),
61n/a 'force', 'compile', 'optimize',
62n/a 'skip_build')
63n/a
64n/a if self.compile is None:
65n/a self.compile = True
66n/a if self.optimize is None:
67n/a self.optimize = 0
68n/a
69n/a if not isinstance(self.optimize, int):
70n/a try:
71n/a self.optimize = int(self.optimize)
72n/a if self.optimize not in (0, 1, 2):
73n/a raise AssertionError
74n/a except (ValueError, AssertionError):
75n/a raise PackagingOptionError("optimize must be 0, 1, or 2")
76n/a
77n/a def run(self):
78n/a # Make sure we have built everything we need first
79n/a self.build()
80n/a
81n/a # Install everything: simply dump the entire contents of the build
82n/a # directory to the installation directory (that's the beauty of
83n/a # having a build directory!)
84n/a outfiles = self.install()
85n/a
86n/a # (Optionally) compile .py to .pyc and/or .pyo
87n/a if outfiles is not None and self.distribution.has_pure_modules():
88n/a # XXX comment from distutils: "This [prefix stripping] is far from
89n/a # complete, but it should at least generate usable bytecode in RPM
90n/a # distributions." -> need to find exact requirements for
91n/a # byte-compiled files and fix it
92n/a install_root = self.get_finalized_command('install_dist').root
93n/a self.byte_compile(outfiles, prefix=install_root)
94n/a
95n/a # -- Top-level worker functions ------------------------------------
96n/a # (called from 'run()')
97n/a
98n/a def build(self):
99n/a if not self.skip_build:
100n/a if self.distribution.has_pure_modules():
101n/a self.run_command('build_py')
102n/a if self.distribution.has_ext_modules():
103n/a self.run_command('build_ext')
104n/a
105n/a def install(self):
106n/a if os.path.isdir(self.build_dir):
107n/a outfiles = self.copy_tree(self.build_dir, self.install_dir)
108n/a else:
109n/a logger.warning(
110n/a '%s: %r does not exist -- no Python modules to install',
111n/a self.get_command_name(), self.build_dir)
112n/a return
113n/a return outfiles
114n/a
115n/a # -- Utility methods -----------------------------------------------
116n/a
117n/a def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir):
118n/a if not has_any:
119n/a return []
120n/a
121n/a build_cmd = self.get_finalized_command(build_cmd)
122n/a build_files = build_cmd.get_outputs()
123n/a build_dir = getattr(build_cmd, cmd_option)
124n/a
125n/a prefix_len = len(build_dir) + len(os.sep)
126n/a outputs = []
127n/a for file in build_files:
128n/a outputs.append(os.path.join(output_dir, file[prefix_len:]))
129n/a
130n/a return outputs
131n/a
132n/a def _bytecode_filenames(self, py_filenames):
133n/a bytecode_files = []
134n/a for py_file in py_filenames:
135n/a # Since build_py handles package data installation, the
136n/a # list of outputs can contain more than just .py files.
137n/a # Make sure we only report bytecode for the .py files.
138n/a ext = os.path.splitext(os.path.normcase(py_file))[1]
139n/a if ext != PYTHON_SOURCE_EXTENSION:
140n/a continue
141n/a if self.compile:
142n/a bytecode_files.append(imp.cache_from_source(py_file, True))
143n/a if self.optimize:
144n/a bytecode_files.append(imp.cache_from_source(py_file, False))
145n/a
146n/a return bytecode_files
147n/a
148n/a # -- External interface --------------------------------------------
149n/a # (called by outsiders)
150n/a
151n/a def get_outputs(self):
152n/a """Return the list of files that would be installed if this command
153n/a were actually run. Not affected by the "dry-run" flag or whether
154n/a modules have actually been built yet.
155n/a """
156n/a pure_outputs = \
157n/a self._mutate_outputs(self.distribution.has_pure_modules(),
158n/a 'build_py', 'build_lib',
159n/a self.install_dir)
160n/a if self.compile:
161n/a bytecode_outputs = self._bytecode_filenames(pure_outputs)
162n/a else:
163n/a bytecode_outputs = []
164n/a
165n/a ext_outputs = \
166n/a self._mutate_outputs(self.distribution.has_ext_modules(),
167n/a 'build_ext', 'build_lib',
168n/a self.install_dir)
169n/a
170n/a return pure_outputs + bytecode_outputs + ext_outputs
171n/a
172n/a def get_inputs(self):
173n/a """Get the list of files that are input to this command, ie. the
174n/a files that get installed as they are named in the build tree.
175n/a The files in this list correspond one-to-one to the output
176n/a filenames returned by 'get_outputs()'.
177n/a """
178n/a inputs = []
179n/a
180n/a if self.distribution.has_pure_modules():
181n/a build_py = self.get_finalized_command('build_py')
182n/a inputs.extend(build_py.get_outputs())
183n/a
184n/a if self.distribution.has_ext_modules():
185n/a build_ext = self.get_finalized_command('build_ext')
186n/a inputs.extend(build_ext.get_outputs())
187n/a
188n/a return inputs