Beispiel #1
0
def flatten_prototype(prototype, validate=False):
    """
    Produce a 'flattened' prototype, where all prototype parents in the inheritance tree have been
    merged into a final prototype.

    Args:
        prototype (dict): Prototype to flatten. Its `prototype_parent` field will be parsed.
        validate (bool, optional): Validate for valid keys etc.

    Returns:
        flattened (dict): The final, flattened prototype.

    """

    if prototype:
        prototype = protlib.homogenize_prototype(prototype)
        protparents = {
            prot['prototype_key'].lower(): prot
            for prot in protlib.search_prototype()
        }
        protlib.validate_prototype(prototype,
                                   None,
                                   protparents,
                                   is_prototype_base=validate,
                                   strict=validate)
        return _get_prototype(
            prototype,
            protparents,
            uninherited={"prototype_key": prototype.get("prototype_key")})
    return {}
Beispiel #2
0
def flatten_prototype(prototype, validate=False):
    """
    Produce a 'flattened' prototype, where all prototype parents in the inheritance tree have been
    merged into a final prototype.

    Args:
        prototype (dict): Prototype to flatten. Its `prototype_parent` field will be parsed.
        validate (bool, optional): Validate for valid keys etc.

    Returns:
        flattened (dict): The final, flattened prototype.

    """

    if prototype:
        prototype = protlib.homogenize_prototype(prototype)
        protparents = {prot['prototype_key'].lower(): prot for prot in protlib.search_prototype()}
        protlib.validate_prototype(prototype, None, protparents,
                                   is_prototype_base=validate, strict=validate)
        return _get_prototype(prototype, protparents,
                              uninherited={"prototype_key": prototype.get("prototype_key")})
    return {}
Beispiel #3
0
def spawn(*prototypes, **kwargs):
    """
    Spawn a number of prototyped objects.

    Args:
        prototypes (dict): Each argument should be a prototype
            dictionary.
    Kwargs:
        prototype_modules (str or list): A python-path to a prototype
            module, or a list of such paths. These will be used to build
            the global protparents dictionary accessible by the input
            prototypes. If not given, it will instead look for modules
            defined by settings.PROTOTYPE_MODULES.
        prototype_parents (dict): A dictionary holding a custom
            prototype-parent dictionary. Will overload same-named
            prototypes from prototype_modules.
        return_parents (bool): Only return a dict of the
            prototype-parents (no object creation happens)
        only_validate (bool): Only run validation of prototype/parents
            (no object creation) and return the create-kwargs.

    Returns:
        object (Object, dict or list): Spawned object(s). If `only_validate` is given, return
            a list of the creation kwargs to build the object(s) without actually creating it. If
            `return_parents` is set, instead return dict of prototype parents.

    """
    # get available protparents
    protparents = {
        prot['prototype_key'].lower(): prot
        for prot in protlib.search_prototype()
    }

    if not kwargs.get("only_validate"):
        # homogenization to be more lenient about prototype format when entering the prototype manually
        prototypes = [
            protlib.homogenize_prototype(prot) for prot in prototypes
        ]

    # overload module's protparents with specifically given protparents
    # we allow prototype_key to be the key of the protparent dict, to allow for module-level
    # prototype imports. We need to insert prototype_key in this case
    for key, protparent in kwargs.get("prototype_parents", {}).items():
        key = str(key).lower()
        protparent['prototype_key'] = str(protparent.get("prototype_key",
                                                         key)).lower()
        protparents[key] = protparent

    if "return_parents" in kwargs:
        # only return the parents
        return copy.deepcopy(protparents)

    objsparams = []
    for prototype in prototypes:

        protlib.validate_prototype(prototype,
                                   None,
                                   protparents,
                                   is_prototype_base=True)
        prot = _get_prototype(
            prototype,
            protparents,
            uninherited={"prototype_key": prototype.get("prototype_key")})
        if not prot:
            continue

        # extract the keyword args we need to create the object itself. If we get a callable,
        # call that to get the value (don't catch errors)
        create_kwargs = {}
        # we must always add a key, so if not given we use a shortened md5 hash. There is a (small)
        # chance this is not unique but it should usually not be a problem.
        val = prot.pop(
            "key",
            "Spawned-{}".format(hashlib.md5(str(time.time())).hexdigest()[:6]))
        create_kwargs["db_key"] = init_spawn_value(val, str)

        val = prot.pop("location", None)
        create_kwargs["db_location"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("home", settings.DEFAULT_HOME)
        create_kwargs["db_home"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("destination", None)
        create_kwargs["db_destination"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("typeclass", settings.BASE_OBJECT_TYPECLASS)
        create_kwargs["db_typeclass_path"] = init_spawn_value(val, str)

        # extract calls to handlers
        val = prot.pop("permissions", [])
        permission_string = init_spawn_value(val, make_iter)
        val = prot.pop("locks", "")
        lock_string = init_spawn_value(val, str)
        val = prot.pop("aliases", [])
        alias_string = init_spawn_value(val, make_iter)

        val = prot.pop("tags", [])
        tags = []
        for (tag, category, data) in val:
            tags.append((init_spawn_value(tag, str), category, data))

        prototype_key = prototype.get('prototype_key', None)
        if prototype_key:
            # we make sure to add a tag identifying which prototype created this object
            tags.append((prototype_key, _PROTOTYPE_TAG_CATEGORY))

        val = prot.pop("exec", "")
        execs = init_spawn_value(val, make_iter)

        # extract ndb assignments
        nattributes = dict(
            (key.split("_", 1)[1], init_spawn_value(val, value_to_obj))
            for key, val in prot.items() if key.startswith("ndb_"))

        # the rest are attribute tuples (attrname, value, category, locks)
        val = make_iter(prot.pop("attrs", []))
        attributes = []
        for (attrname, value, category, locks) in val:
            attributes.append(
                (attrname, init_spawn_value(value), category, locks))

        simple_attributes = []
        for key, value in ((key, value) for key, value in prot.items()
                           if not (key.startswith("ndb_"))):
            # we don't support categories, nor locks for simple attributes
            if key in _PROTOTYPE_META_NAMES:
                continue
            else:
                simple_attributes.append(
                    (key, init_spawn_value(value,
                                           value_to_obj_or_any), None, None))

        attributes = attributes + simple_attributes
        attributes = [
            tup for tup in attributes if not tup[0] in _NON_CREATE_KWARGS
        ]

        # pack for call into _batch_create_object
        objsparams.append((create_kwargs, permission_string, lock_string,
                           alias_string, nattributes, attributes, tags, execs))

    if kwargs.get("only_validate"):
        return objsparams
    return batch_create_object(*objsparams)
Beispiel #4
0
def spawn(*prototypes, **kwargs):
    """
    Spawn a number of prototyped objects.

    Args:
        prototypes (dict): Each argument should be a prototype
            dictionary.
    Kwargs:
        prototype_modules (str or list): A python-path to a prototype
            module, or a list of such paths. These will be used to build
            the global protparents dictionary accessible by the input
            prototypes. If not given, it will instead look for modules
            defined by settings.PROTOTYPE_MODULES.
        prototype_parents (dict): A dictionary holding a custom
            prototype-parent dictionary. Will overload same-named
            prototypes from prototype_modules.
        return_parents (bool): Only return a dict of the
            prototype-parents (no object creation happens)
        only_validate (bool): Only run validation of prototype/parents
            (no object creation) and return the create-kwargs.

    Returns:
        object (Object, dict or list): Spawned object(s). If `only_validate` is given, return
            a list of the creation kwargs to build the object(s) without actually creating it. If
            `return_parents` is set, instead return dict of prototype parents.

    """
    # get available protparents
    protparents = {prot['prototype_key'].lower(): prot for prot in protlib.search_prototype()}

    # overload module's protparents with specifically given protparents
    # we allow prototype_key to be the key of the protparent dict, to allow for module-level
    # prototype imports. We need to insert prototype_key in this case
    for key, protparent in kwargs.get("prototype_parents", {}).items():
        key = str(key).lower()
        protparent['prototype_key'] = str(protparent.get("prototype_key", key)).lower()
        protparents[key] = protparent

    if "return_parents" in kwargs:
        # only return the parents
        return copy.deepcopy(protparents)

    objsparams = []
    for prototype in prototypes:

        protlib.validate_prototype(prototype, None, protparents, is_prototype_base=True)
        prot = _get_prototype(prototype, protparents,
                              uninherited={"prototype_key": prototype.get("prototype_key")})
        if not prot:
            continue

        # extract the keyword args we need to create the object itself. If we get a callable,
        # call that to get the value (don't catch errors)
        create_kwargs = {}
        # we must always add a key, so if not given we use a shortened md5 hash. There is a (small)
        # chance this is not unique but it should usually not be a problem.
        val = prot.pop("key", "Spawned-{}".format(
            hashlib.md5(str(time.time())).hexdigest()[:6]))
        create_kwargs["db_key"] = init_spawn_value(val, str)

        val = prot.pop("location", None)
        create_kwargs["db_location"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("home", settings.DEFAULT_HOME)
        create_kwargs["db_home"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("destination", None)
        create_kwargs["db_destination"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("typeclass", settings.BASE_OBJECT_TYPECLASS)
        create_kwargs["db_typeclass_path"] = init_spawn_value(val, str)

        # extract calls to handlers
        val = prot.pop("permissions", [])
        permission_string = init_spawn_value(val, make_iter)
        val = prot.pop("locks", "")
        lock_string = init_spawn_value(val, str)
        val = prot.pop("aliases", [])
        alias_string = init_spawn_value(val, make_iter)

        val = prot.pop("tags", [])
        tags = []
        for (tag, category, data) in tags:
            tags.append((init_spawn_value(val, str), category, data))

        prototype_key = prototype.get('prototype_key', None)
        if prototype_key:
            # we make sure to add a tag identifying which prototype created this object
            tags.append((prototype_key, _PROTOTYPE_TAG_CATEGORY))

        val = prot.pop("exec", "")
        execs = init_spawn_value(val, make_iter)

        # extract ndb assignments
        nattributes = dict((key.split("_", 1)[1], init_spawn_value(val, value_to_obj))
                           for key, val in prot.items() if key.startswith("ndb_"))

        # the rest are attribute tuples (attrname, value, category, locks)
        val = make_iter(prot.pop("attrs", []))
        attributes = []
        for (attrname, value, category, locks) in val:
            attributes.append((attrname, init_spawn_value(val), category, locks))

        simple_attributes = []
        for key, value in ((key, value) for key, value in prot.items()
                           if not (key.startswith("ndb_"))):
            # we don't support categories, nor locks for simple attributes
            if key in _PROTOTYPE_META_NAMES:
                continue
            else:
                simple_attributes.append(
                    (key, init_spawn_value(value, value_to_obj_or_any), None, None))

        attributes = attributes + simple_attributes
        attributes = [tup for tup in attributes if not tup[0] in _NON_CREATE_KWARGS]

        # pack for call into _batch_create_object
        objsparams.append((create_kwargs, permission_string, lock_string,
                           alias_string, nattributes, attributes, tags, execs))

    if kwargs.get("only_validate"):
        return objsparams
    return batch_create_object(*objsparams)