Exemplo n.º 1
0
def apply_from_argparse(args, traits=None, target: HasTraits = None) -> dict:
    """
    Applies arguments added via add_traits_to_argparse to
    a target object which implements HasTraits. If a target
    is not known, a dict of traits may be passed instead.
    Will throw TraitError if validation fails.

    :param args: Parsed args from argparse
    :param traits: Dictionary of traits (optional)
    :param target: Target object (optional)
    :return: Dict of the arguments which actually changed
    """
    # apply the traits to an empty object, which will run
    # the validators on the client
    if isinstance(traits, HasTraits):
        traits = traits.traits()

    traits = traits.copy()
    for k, v in traits.items():
        if not isinstance(v, TraitType):
            if isinstance(v, dict):
                k[v] = dict_as_trait(v)
            else:
                raise TypeError("A dict or trait object must be supplied")

    if target is None:
        if traits is None:
            raise ValueError("Either traits or target must be specified")
        target = HasTraits()
        target.add_traits(**traits)

    # determine what should actually be changed
    argkeys = [k for k, v in vars(args).items() if v is not None]
    intersect = set(target.traits().keys()).intersection(set(argkeys))

    # apply the argparse flags to the target object
    for key in intersect:
        if target.traits()[key].get_metadata('config') is not True:
            raise ValueError("Trait is not marked as configurable: %s" % key)

        setattr(target, key, getattr(args, key))

    # if all validators passed, return a dict of the changed args
    changed = {}
    for key in intersect:
        changed[key] = target._trait_values[key]

    return changed
Exemplo n.º 2
0
def class_traits_as_dict(obj: HasTraits, values: dict = None) -> dict:
    """
    Create a dict which represents all traits of the given object.
    This dict itself can be inspected in a generic API, or it
    may be converted back to a (stub) instance of HasTraits. This
    facilitates the sending of configurable object properties over
    an interface such as D-Bus.

    :param obj: an instance of HasTraits
    :param value: optional dict of trait values (pulled from obj by default)
    :return: dict representing all traits in obj
    """
    cls_dt = {}
    if isinstance(obj, type) and hasattr(obj, 'class_traits'):
        traits = obj.class_traits()
    elif isinstance(obj, dict):
        traits = obj
    elif isinstance(obj, HasTraits):
        traits = obj.traits()
        values = obj._trait_values
    else:
        raise TypeError("Object does not support traits")

    for k, v in traits.items():
        dt = trait_as_dict(v)
        if dt is None:
            continue
        if values is not None and k in values:
            dt['__value__'] = values[k]
        cls_dt[k] = dt
    return cls_dt
Exemplo n.º 3
0
def add_traits_to_argparse(obj: HasTraits,
                           parser: ArgumentParser,
                           prefix: str = None):
    """
    Add all traits from the given object to the argparse context.

    :param obj: an instance of HasTraits
    :param parser: argparse parser
    :param prefix: string to prefix keys with
    """
    for key, trait in obj.traits().items():
        if trait.get_metadata('config') is not True:
            continue

        argname = '--%s' % key
        if prefix is not None:
            argname = '--%s.%s' % (prefix, key)

        if isinstance(trait, Container):
            parser.add_argument(argname, nargs='+', help=trait.info_text)
        elif isinstance(trait, Enum):
            parser.add_argument(argname,
                                type=str.lower,
                                choices=[x.lower() for x in trait.values],
                                help=trait.info_text)
        else:
            argtype = str
            if hasattr(trait, 'default_value'):
                argtype = type(trait.default_value)
            parser.add_argument(argname, type=argtype, help=trait.info_text)
Exemplo n.º 4
0
def get_args_dict(obj: HasTraits, incl_all=False):
    """
    Return a dict of user-configurable traits for an object

    :param obj: an instance of HasTraits
    :param incl_all: If all items should be included, regardless of RO status
    :return: dict of arguments
    """
    argsdict = ArgsDict()
    for k in sorted(obj._trait_values.keys()):
        v = obj._trait_values[k]
        trait = obj.traits()[k]
        if incl_all or (not trait.get_metadata('hidden') and is_trait_writable(trait)):
            argsdict[k] = v
    return argsdict