Source code for horetu.interfaces.django

import subprocess
from argparse import RawDescriptionHelpFormatter
from collections import ChainMap, OrderedDict
from triedict import triedict
from . import _bind
from . import _util
from ..annotations import Flag
from .. import exceptions
from ..program import Program

[docs]def django(program, handlers=None, freedesktop=False): ''' Produce a django management command to be assigned to ``<project>.management.commands.Command``. :type program: Program, callable, list, or dict :param program: The program for which to produce the interface :param dict handlers: Mapping from content type to handler program :param bool freedesktop: Fall back to xdg-open if a handler is not available ''' try: from django.core.management.base import BaseCommand, CommandError except ImportError: logger.error('Django is not installed; run this: pip install horetu[all]') sys.exit(1) if not handlers: handlers = {} if not isinstance(program, Program): program = Program(program) if set(program) == {()}: function = program[()] else: raise ValueError('Subcommands are not allowed in the argparse/django interface.') parser_hack = [] class Command(BaseCommand): def add_arguments(self, parser): parser_hack.append(parser) parser.formatter_class=RawDescriptionHelpFormatter parser.description = function.description one(parser, function) def handle(self, *args, **options): if args != (): raise NotImplementedError('I don\'t know what to do with args.: ' + repr(args)) inputs = parse_options(function, options) fp = self.stdout try: raw_output = function.run('raw', inputs) rt = function.return_type if rt and (freedesktop or (rt.parsed in handlers)): handler = handlers.get(rt.parsed, XDG_OPEN) if isinstance(raw_output, bytes): stream = [raw_output] else: stream = raw_output p = subprocess.Popen(handler, stdin=subprocess.PIPE, stderr=stderr) for element in stream: if isinstance(element, bytes): p.stdin.write(element) else: raise ValueError('When you set a content type, the function must return either bytes or an iterable of bytes.') p.stdin.close() p.wait() else: for line in _util.stream(raw_output): self.stdout.buffer.write(line + b'\n') self.stdout.flush() # except exceptions.CouldNotParse as e: # parser_hack[0].error('') except exceptions.Error as e: raise CommandError(e.message) # It is a bug if other horetu exceptions are raised return Command
def parse_options(function, kwargs): arguments = OrderedDict() params = triedict({param.name: param for param in function.all_parameters()}) for key, value in kwargs.items(): if key in params: p = params[key] if isinstance(p, Flag): value = Flag.YES if not p.name in arguments: arguments[p.name] = [] arguments[p.name].append(value) return arguments def one(parser, f): def kw(param, **kwargs): def Type(x): return param.loads('raw', x) Type.__name__ = param.__name__ kwargs.update({ 'type': Type, 'default': param.default, 'help': param.description, }) if kwargs['action'] in {'store_true', 'store_false', 'count'}: del(kwargs['nargs']) return kwargs for param in f.positional: parser.add_argument(param.name, **kw(param, action='store')) for param in f.keyword1: parser.add_argument(param.name, **kw(param, nargs='?')) for param in f.var_positional: parser.add_argument(param.name, **kw(param, nargs='*', action='store')) for param in f.keyword2: if isinstance(param, Flag): action = 'store_true' elif param.is_list_type: action = 'append' else: action = 'store' parser.add_argument('--'+param.name, **kw(param, action=action))