summaryrefslogtreecommitdiff
path: root/wheel/tool/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'wheel/tool/__init__.py')
-rw-r--r--wheel/tool/__init__.py359
1 files changed, 0 insertions, 359 deletions
diff --git a/wheel/tool/__init__.py b/wheel/tool/__init__.py
deleted file mode 100644
index 4c0187b..0000000
--- a/wheel/tool/__init__.py
+++ /dev/null
@@ -1,359 +0,0 @@
-"""
-Wheel command-line utility.
-"""
-
-import os
-import hashlib
-import sys
-import json
-
-from glob import iglob
-from .. import signatures
-from ..util import (urlsafe_b64decode, urlsafe_b64encode, native, binary,
- matches_requirement)
-from ..install import WheelFile, VerifyingZipFile
-from ..paths import get_install_command
-
-def require_pkgresources(name):
- try:
- import pkg_resources
- except ImportError:
- raise RuntimeError("'{0}' needs pkg_resources (part of setuptools).".format(name))
-
-import argparse
-
-class WheelError(Exception): pass
-
-# For testability
-def get_keyring():
- try:
- from ..signatures import keys
- import keyring
- assert keyring.get_keyring().priority
- except (ImportError, AssertionError):
- raise WheelError("Install wheel[signatures] (requires keyring, keyrings.alt, pyxdg) for signatures.")
- return keys.WheelKeys, keyring
-
-def keygen(get_keyring=get_keyring):
- """Generate a public/private key pair."""
- WheelKeys, keyring = get_keyring()
-
- ed25519ll = signatures.get_ed25519ll()
-
- wk = WheelKeys().load()
-
- keypair = ed25519ll.crypto_sign_keypair()
- vk = native(urlsafe_b64encode(keypair.vk))
- sk = native(urlsafe_b64encode(keypair.sk))
- kr = keyring.get_keyring()
- kr.set_password("wheel", vk, sk)
- sys.stdout.write("Created Ed25519 keypair with vk={0}\n".format(vk))
- sys.stdout.write("in {0!r}\n".format(kr))
-
- sk2 = kr.get_password('wheel', vk)
- if sk2 != sk:
- raise WheelError("Keyring is broken. Could not retrieve secret key.")
-
- sys.stdout.write("Trusting {0} to sign and verify all packages.\n".format(vk))
- wk.add_signer('+', vk)
- wk.trust('+', vk)
- wk.save()
-
-def sign(wheelfile, replace=False, get_keyring=get_keyring):
- """Sign a wheel"""
- WheelKeys, keyring = get_keyring()
-
- ed25519ll = signatures.get_ed25519ll()
-
- wf = WheelFile(wheelfile, append=True)
- wk = WheelKeys().load()
-
- name = wf.parsed_filename.group('name')
- sign_with = wk.signers(name)[0]
- sys.stdout.write("Signing {0} with {1}\n".format(name, sign_with[1]))
-
- vk = sign_with[1]
- kr = keyring.get_keyring()
- sk = kr.get_password('wheel', vk)
- keypair = ed25519ll.Keypair(urlsafe_b64decode(binary(vk)),
- urlsafe_b64decode(binary(sk)))
-
-
- record_name = wf.distinfo_name + '/RECORD'
- sig_name = wf.distinfo_name + '/RECORD.jws'
- if sig_name in wf.zipfile.namelist():
- raise WheelError("Wheel is already signed.")
- record_data = wf.zipfile.read(record_name)
- payload = {"hash":"sha256=" + native(urlsafe_b64encode(hashlib.sha256(record_data).digest()))}
- sig = signatures.sign(payload, keypair)
- wf.zipfile.writestr(sig_name, json.dumps(sig, sort_keys=True))
- wf.zipfile.close()
-
-def unsign(wheelfile):
- """
- Remove RECORD.jws from a wheel by truncating the zip file.
-
- RECORD.jws must be at the end of the archive. The zip file must be an
- ordinary archive, with the compressed files and the directory in the same
- order, and without any non-zip content after the truncation point.
- """
- vzf = VerifyingZipFile(wheelfile, "a")
- info = vzf.infolist()
- if not (len(info) and info[-1].filename.endswith('/RECORD.jws')):
- raise WheelError("RECORD.jws not found at end of archive.")
- vzf.pop()
- vzf.close()
-
-def verify(wheelfile):
- """Verify a wheel.
-
- The signature will be verified for internal consistency ONLY and printed.
- Wheel's own unpack/install commands verify the manifest against the
- signature and file contents.
- """
- wf = WheelFile(wheelfile)
- sig_name = wf.distinfo_name + '/RECORD.jws'
- sig = json.loads(native(wf.zipfile.open(sig_name).read()))
- verified = signatures.verify(sig)
- sys.stderr.write("Signatures are internally consistent.\n")
- sys.stdout.write(json.dumps(verified, indent=2))
- sys.stdout.write('\n')
-
-def unpack(wheelfile, dest='.'):
- """Unpack a wheel.
-
- Wheel content will be unpacked to {dest}/{name}-{ver}, where {name}
- is the package name and {ver} its version.
-
- :param wheelfile: The path to the wheel.
- :param dest: Destination directory (default to current directory).
- """
- wf = WheelFile(wheelfile)
- namever = wf.parsed_filename.group('namever')
- destination = os.path.join(dest, namever)
- sys.stderr.write("Unpacking to: %s\n" % (destination))
- wf.zipfile.extractall(destination)
- wf.zipfile.close()
-
-def install(requirements, requirements_file=None,
- wheel_dirs=None, force=False, list_files=False,
- dry_run=False):
- """Install wheels.
-
- :param requirements: A list of requirements or wheel files to install.
- :param requirements_file: A file containing requirements to install.
- :param wheel_dirs: A list of directories to search for wheels.
- :param force: Install a wheel file even if it is not compatible.
- :param list_files: Only list the files to install, don't install them.
- :param dry_run: Do everything but the actual install.
- """
-
- # If no wheel directories specified, use the WHEELPATH environment
- # variable, or the current directory if that is not set.
- if not wheel_dirs:
- wheelpath = os.getenv("WHEELPATH")
- if wheelpath:
- wheel_dirs = wheelpath.split(os.pathsep)
- else:
- wheel_dirs = [ os.path.curdir ]
-
- # Get a list of all valid wheels in wheel_dirs
- all_wheels = []
- for d in wheel_dirs:
- for w in os.listdir(d):
- if w.endswith('.whl'):
- wf = WheelFile(os.path.join(d, w))
- if wf.compatible:
- all_wheels.append(wf)
-
- # If there is a requirements file, add it to the list of requirements
- if requirements_file:
- # If the file doesn't exist, search for it in wheel_dirs
- # This allows standard requirements files to be stored with the
- # wheels.
- if not os.path.exists(requirements_file):
- for d in wheel_dirs:
- name = os.path.join(d, requirements_file)
- if os.path.exists(name):
- requirements_file = name
- break
-
- with open(requirements_file) as fd:
- requirements.extend(fd)
-
- to_install = []
- for req in requirements:
- if req.endswith('.whl'):
- # Explicitly specified wheel filename
- if os.path.exists(req):
- wf = WheelFile(req)
- if wf.compatible or force:
- to_install.append(wf)
- else:
- msg = ("{0} is not compatible with this Python. "
- "--force to install anyway.".format(req))
- raise WheelError(msg)
- else:
- # We could search on wheel_dirs, but it's probably OK to
- # assume the user has made an error.
- raise WheelError("No such wheel file: {}".format(req))
- continue
-
- # We have a requirement spec
- # If we don't have pkg_resources, this will raise an exception
- matches = matches_requirement(req, all_wheels)
- if not matches:
- raise WheelError("No match for requirement {}".format(req))
- to_install.append(max(matches))
-
- # We now have a list of wheels to install
- if list_files:
- sys.stdout.write("Installing:\n")
-
- if dry_run:
- return
-
- for wf in to_install:
- if list_files:
- sys.stdout.write(" {0}\n".format(wf.filename))
- continue
- wf.install(force=force)
- wf.zipfile.close()
-
-def install_scripts(distributions):
- """
- Regenerate the entry_points console_scripts for the named distribution.
- """
- try:
- from setuptools.command import easy_install
- import pkg_resources
- except ImportError:
- raise RuntimeError("'wheel install_scripts' needs setuptools.")
-
- for dist in distributions:
- pkg_resources_dist = pkg_resources.get_distribution(dist)
- install = get_install_command(dist)
- command = easy_install.easy_install(install.distribution)
- command.args = ['wheel'] # dummy argument
- command.finalize_options()
- command.install_egg_scripts(pkg_resources_dist)
-
-def convert(installers, dest_dir, verbose):
- require_pkgresources('wheel convert')
-
- # Only support wheel convert if pkg_resources is present
- from ..wininst2wheel import bdist_wininst2wheel
- from ..egg2wheel import egg2wheel
-
- for pat in installers:
- for installer in iglob(pat):
- if os.path.splitext(installer)[1] == '.egg':
- conv = egg2wheel
- else:
- conv = bdist_wininst2wheel
- if verbose:
- sys.stdout.write("{0}... ".format(installer))
- sys.stdout.flush()
- conv(installer, dest_dir)
- if verbose:
- sys.stdout.write("OK\n")
-
-def parser():
- p = argparse.ArgumentParser()
- s = p.add_subparsers(help="commands")
-
- def keygen_f(args):
- keygen()
- keygen_parser = s.add_parser('keygen', help='Generate signing key')
- keygen_parser.set_defaults(func=keygen_f)
-
- def sign_f(args):
- sign(args.wheelfile)
- sign_parser = s.add_parser('sign', help='Sign wheel')
- sign_parser.add_argument('wheelfile', help='Wheel file')
- sign_parser.set_defaults(func=sign_f)
-
- def unsign_f(args):
- unsign(args.wheelfile)
- unsign_parser = s.add_parser('unsign', help=unsign.__doc__)
- unsign_parser.add_argument('wheelfile', help='Wheel file')
- unsign_parser.set_defaults(func=unsign_f)
-
- def verify_f(args):
- verify(args.wheelfile)
- verify_parser = s.add_parser('verify', help=verify.__doc__)
- verify_parser.add_argument('wheelfile', help='Wheel file')
- verify_parser.set_defaults(func=verify_f)
-
- def unpack_f(args):
- unpack(args.wheelfile, args.dest)
- unpack_parser = s.add_parser('unpack', help='Unpack wheel')
- unpack_parser.add_argument('--dest', '-d', help='Destination directory',
- default='.')
- unpack_parser.add_argument('wheelfile', help='Wheel file')
- unpack_parser.set_defaults(func=unpack_f)
-
- def install_f(args):
- install(args.requirements, args.requirements_file,
- args.wheel_dirs, args.force, args.list_files)
- install_parser = s.add_parser('install', help='Install wheels')
- install_parser.add_argument('requirements', nargs='*',
- help='Requirements to install.')
- install_parser.add_argument('--force', default=False,
- action='store_true',
- help='Install incompatible wheel files.')
- install_parser.add_argument('--wheel-dir', '-d', action='append',
- dest='wheel_dirs',
- help='Directories containing wheels.')
- install_parser.add_argument('--requirements-file', '-r',
- help="A file containing requirements to "
- "install.")
- install_parser.add_argument('--list', '-l', default=False,
- dest='list_files',
- action='store_true',
- help="List wheels which would be installed, "
- "but don't actually install anything.")
- install_parser.set_defaults(func=install_f)
-
- def install_scripts_f(args):
- install_scripts(args.distributions)
- install_scripts_parser = s.add_parser('install-scripts', help='Install console_scripts')
- install_scripts_parser.add_argument('distributions', nargs='*',
- help='Regenerate console_scripts for these distributions')
- install_scripts_parser.set_defaults(func=install_scripts_f)
-
- def convert_f(args):
- convert(args.installers, args.dest_dir, args.verbose)
- convert_parser = s.add_parser('convert', help='Convert egg or wininst to wheel')
- convert_parser.add_argument('installers', nargs='*', help='Installers to convert')
- convert_parser.add_argument('--dest-dir', '-d', default=os.path.curdir,
- help="Directory to store wheels (default %(default)s)")
- convert_parser.add_argument('--verbose', '-v', action='store_true')
- convert_parser.set_defaults(func=convert_f)
-
- def version_f(args):
- from .. import __version__
- sys.stdout.write("wheel %s\n" % __version__)
- version_parser = s.add_parser('version', help='Print version and exit')
- version_parser.set_defaults(func=version_f)
-
- def help_f(args):
- p.print_help()
- help_parser = s.add_parser('help', help='Show this help')
- help_parser.set_defaults(func=help_f)
-
- return p
-
-def main():
- p = parser()
- args = p.parse_args()
- if not hasattr(args, 'func'):
- p.print_help()
- else:
- # XXX on Python 3.3 we get 'args has no func' rather than short help.
- try:
- args.func(args)
- return 0
- except WheelError as e:
- sys.stderr.write(e.message + "\n")
- return 1