Source code for piwheels.add

# The piwheels project
#   Copyright (c) 2017 Ben Nuttall <https://github.com/bennuttall>
#   Copyright (c) 2017 Dave Jones <dave@waveform.org.uk>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the copyright holder nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

"""
Contains the functions that implement the :program:`piw-add` script.

.. autofunction:: main

.. autofunction:: do_add
"""

from datetime import datetime, timezone
import sys
import logging

import requests

from .. import __version__, terminal, const, transport, protocols
from ..format import canonicalize_name
from ..pypi import pypi_package_description


UTC = timezone.utc


[docs]def main(args=None): """ This is the main function for the :program:`piw-add` script. It uses :class:`~.mr_chase.MrChase` to add mew packages and versions to the system. """ sys.excepthook = terminal.error_handler terminal.error_handler[RuntimeError] = ( terminal.error_handler.exc_message, 1) logging.getLogger().name = 'import' parser = terminal.configure_parser("""\ The piw-add script is used to manually add new packages and versions to the system. This script must be run on the same node as the piw-master script. """) parser.add_argument( 'package', help="The name of the package to add") parser.add_argument( 'version', nargs='?', help="The version of the package to add; if omitted, adds the package " "only") parser.add_argument( '-y', '--yes', action='store_true', help="Run non-interactively; never prompt during operation") parser.add_argument( '-s', '--skip', action='store', default='', metavar='REASON', help="Mark the package or version with a skip reason to prevent build " "attempts") parser.add_argument( '--unskip', action='store_true', help="Remove a skip reason for the package or version to enable build " "attempts") parser.add_argument( '-d', '--description', metavar='TEXT', help="The package description; defaults to retrieving the description " "from PyPI") parser.add_argument( '-a', '--alias', dest='aliases', metavar='NAME', default=[], action='append', help="A package aliaseto use; may be specified multiple times") parser.add_argument( '-r', '--released', metavar='TIMESTAMP', default=datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'), help="The version's release date (can only be provided for a new " "version, cannot be updated); defaults to now") parser.add_argument( '--yank', action='store_true', help="Mark the version as yanked (can only be applied to a new " "version - use piw-remove to yank a known version") parser.add_argument( '--unyank', action='store_true', help="Mark a known version as not yanked") parser.add_argument( '--import-queue', metavar='ADDR', default=const.IMPORT_QUEUE, help="The address of the queue used by piw-add (default: " "%(default)s); this should always be an ipc address") config = parser.parse_args(args) package = canonicalize_name(config.package) terminal.configure_logging(config.log_level, config.log_file) logging.info("PiWheels Adder version %s", __version__) if not config.yes: if config.version is None: logging.warning("Preparing to add/update %s", config.package) else: logging.warning("Preparing to add/update %s %s", config.package, config.version) if not terminal.yes_no_prompt('Proceed?'): logging.warning('User aborted addition') return 2 logging.info('Connecting to master at %s', config.import_queue) config.released = datetime.strptime( config.released, '%Y-%m-%d %H:%M:%S').replace(tzinfo=UTC) if config.version is None and config.description is None: config.description = pypi_package_description(package) for alias in config.aliases: if canonicalize_name(alias) != package: raise RuntimeError("Alias {} does not match canon: {}".format( alias, package)) do_add(config) return 0
[docs]def do_add(config): """ Handles constructing and sending the ADDPKG/ADDVER message to :class:`~.mr_chase.MrChase`. :param config: The configuration obtained from parsing the command line. """ ctx = transport.Context() queue = ctx.socket(transport.REQ, protocol=reversed(protocols.mr_chase)) queue.hwm = 10 queue.connect(config.import_queue) try: if config.version is None: queue.send_msg('ADDPKG', [ config.package, config.description, config.skip, config.unskip, config.aliases, ]) else: queue.send_msg('ADDVER', [ config.package, config.version, config.skip, config.unskip, config.released, config.yank, config.unyank, config.aliases, ]) msg, data = queue.recv_msg() if msg == 'ERROR': if data == 'NOPKG': raise RuntimeError( 'Package {} does not exist - add it with piw-add ' 'first'.format(config.package)) elif data == 'SKIPPKG': raise RuntimeError( 'Cannot skip a known package with piw-add - use ' 'piw-remove instead') elif data == 'SKIPVER': raise RuntimeError( 'Cannot skip a known version with piw-add - use ' 'piw-remove instead') elif data == 'YANKVER': raise RuntimeError( 'Cannot yank a known version with piw-add - use ' 'piw-remove instead') else: assert False, 'invalid data from master' elif msg == 'DONE': if data == 'NEWPKG': logging.info('Added package successfully') elif data == 'UPDPKG': logging.info('Updated package successfully') elif data == 'NEWVER': logging.info('Added version successfully') elif data == 'UPDVER': logging.info('Updated version successfully') else: assert False, 'invalid operation from master' else: assert False, 'invalid response from master' finally: queue.close() ctx.close()