Ejemplo n.º 1
0
def find_subclasses(locations, base_cls, exclude_hidden=True):
    """Finds subclass types in the given locations.

    This will examines the given locations for types which are subclasses of
    the base class type provided and returns the found subclasses (or fails
    with exceptions if this introspection can not be accomplished).

    If a string is provided as one of the locations it will be imported and
    examined if it is a subclass of the base class. If a module is given,
    all of its members will be examined for attributes which are subclasses of
    the base class. If a type itself is given it will be examined for being a
    subclass of the base class.
    """
    derived = set()
    for item in locations:
        module = None
        if isinstance(item, six.string_types):
            try:
                pkg, cls = item.split(':')
            except ValueError:
                module = importutils.import_module(item)
            else:
                obj = importutils.import_class('%s.%s' % (pkg, cls))
                if not reflection.is_subclass(obj, base_cls):
                    raise TypeError("Object '%s' (%s) is not a '%s' subclass"
                                    % (item, type(item), base_cls))
                derived.add(obj)
        elif isinstance(item, types.ModuleType):
            module = item
        elif reflection.is_subclass(item, base_cls):
            derived.add(item)
        else:
            raise TypeError("Object '%s' (%s) is an unexpected type" %
                            (item, type(item)))
        # If it's a module derive objects from it if we can.
        if module is not None:
            for (name, obj) in inspect.getmembers(module):
                if name.startswith("_") and exclude_hidden:
                    continue
                if reflection.is_subclass(obj, base_cls):
                    derived.add(obj)
    return derived
Ejemplo n.º 2
0
def find_subclasses(locations, base_cls, exclude_hidden=True):
    """Finds subclass types in the given locations.

    This will examines the given locations for types which are subclasses of
    the base class type provided and returns the found subclasses (or fails
    with exceptions if this introspection can not be accomplished).

    If a string is provided as one of the locations it will be imported and
    examined if it is a subclass of the base class. If a module is given,
    all of its members will be examined for attributes which are subclasses of
    the base class. If a type itself is given it will be examined for being a
    subclass of the base class.
    """
    derived = set()
    for item in locations:
        module = None
        if isinstance(item, six.string_types):
            try:
                pkg, cls = item.split(':')
            except ValueError:
                module = importutils.import_module(item)
            else:
                obj = importutils.import_class('%s.%s' % (pkg, cls))
                if not reflection.is_subclass(obj, base_cls):
                    raise TypeError("Object '%s' (%s) is not a '%s' subclass"
                                    % (item, type(item), base_cls))
                derived.add(obj)
        elif isinstance(item, types.ModuleType):
            module = item
        elif reflection.is_subclass(item, base_cls):
            derived.add(item)
        else:
            raise TypeError("Object '%s' (%s) is an unexpected type" %
                            (item, type(item)))
        # If it's a module derive objects from it if we can.
        if module is not None:
            for (name, obj) in inspect.getmembers(module):
                if name.startswith("_") and exclude_hidden:
                    continue
                if reflection.is_subclass(obj, base_cls):
                    derived.add(obj)
    return derived
Ejemplo n.º 3
0
def extract_flow_kwargs(flow_factory, factory_args=None, store=None):
    """Extract required flow_factory arguments from a job store.

    Given a flow_factory function or class, a list of positional arguments,
    and a store dict, extract the remaining arguments for the flow_factory
    from the store.

    Throws KeyError if a required argument is not provided.
    """
    if factory_args is None:
        factory_args = []

    if store is None:
        store = {}

    kwargs = {}

    _name, factory_fun = fetch_validate_factory(flow_factory)

    if reflection.is_subclass(factory_fun, ff_type.FlowFactory):
        factory_fun = factory_fun.generate

    sig = reflection.get_signature(factory_fun)

    for param_name, p in six.iteritems(sig.parameters):
        if param_name == 'self':
            continue

        if p.kind is reflection.Parameter.VAR_POSITIONAL and factory_args:
            factory_args.popleft()

        value = store.get(param_name, p.default)
        if value is reflection.Parameter.empty:
            msg_tmpl = ('The flow {flow_factory} is missing a required '
                        'parameter: {param_name}')
            msg = msg_tmpl.format(flow_factory=flow_factory.__name__,
                                  param_name=param_name)

            raise KeyError(msg)

        kwargs[param_name] = value

    return kwargs