summaryrefslogtreecommitdiffstats
path: root/src/installer/__main__.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/installer/__main__.py')
-rw-r--r--src/installer/__main__.py98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/installer/__main__.py b/src/installer/__main__.py
new file mode 100644
index 0000000..51014b9
--- /dev/null
+++ b/src/installer/__main__.py
@@ -0,0 +1,98 @@
+"""Installer CLI."""
+
+import argparse
+import os.path
+import sys
+import sysconfig
+from typing import Dict, Optional, Sequence
+
+import installer
+from installer.destinations import SchemeDictionaryDestination
+from installer.sources import WheelFile
+from installer.utils import get_launcher_kind
+
+
+def _get_main_parser() -> argparse.ArgumentParser:
+ """Construct the main parser."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument("wheel", type=str, help="wheel file to install")
+ parser.add_argument(
+ "--destdir",
+ "-d",
+ metavar="path",
+ type=str,
+ help="destination directory (prefix to prepend to each file)",
+ )
+ parser.add_argument(
+ "--prefix",
+ "-p",
+ metavar="path",
+ type=str,
+ help="override prefix to install packages to",
+ )
+ parser.add_argument(
+ "--compile-bytecode",
+ action="append",
+ metavar="level",
+ type=int,
+ choices=[0, 1, 2],
+ help="generate bytecode for the specified optimization level(s) (default=0, 1)",
+ )
+ parser.add_argument(
+ "--no-compile-bytecode",
+ action="store_true",
+ help="don't generate bytecode for installed modules",
+ )
+ return parser
+
+
+def _get_scheme_dict(
+ distribution_name: str, prefix: Optional[str] = None
+) -> Dict[str, str]:
+ """Calculate the scheme dictionary for the current Python environment."""
+ vars = {}
+ if prefix is None:
+ installed_base = sysconfig.get_config_var("base")
+ assert installed_base
+ else:
+ vars["base"] = vars["platbase"] = installed_base = prefix
+
+ scheme_dict = sysconfig.get_paths(vars=vars)
+
+ # calculate 'headers' path, not currently in sysconfig - see
+ # https://bugs.python.org/issue44445. This is based on what distutils does.
+ # TODO: figure out original vs normalised distribution names
+ scheme_dict["headers"] = os.path.join(
+ sysconfig.get_path("include", vars={"installed_base": installed_base}),
+ distribution_name,
+ )
+
+ return scheme_dict
+
+
+def _main(cli_args: Sequence[str], program: Optional[str] = None) -> None:
+ """Process arguments and perform the install."""
+ parser = _get_main_parser()
+ if program:
+ parser.prog = program
+ args = parser.parse_args(cli_args)
+
+ bytecode_levels = args.compile_bytecode
+ if args.no_compile_bytecode:
+ bytecode_levels = []
+ elif not bytecode_levels:
+ bytecode_levels = [0, 1]
+
+ with WheelFile.open(args.wheel) as source:
+ destination = SchemeDictionaryDestination(
+ scheme_dict=_get_scheme_dict(source.distribution, prefix=args.prefix),
+ interpreter=sys.executable,
+ script_kind=get_launcher_kind(),
+ bytecode_optimization_levels=bytecode_levels,
+ destdir=args.destdir,
+ )
+ installer.install(source, destination, {})
+
+
+if __name__ == "__main__": # pragma: no cover
+ _main(sys.argv[1:], "python -m installer")