def _all_default(d, default, seen=None):
    """
    ANY VALUE NOT SET WILL BE SET BY THE default
    THIS IS RECURSIVE
    """
    if default is None:
        return
    if _get(default, CLASS) is Data:
        default = object.__getattribute__(default,
                                          SLOT)  # REACH IN AND GET THE dict
        # Log = _late_import()
        # Log.error("strictly dict (or object) allowed: got {{type}}", type=_get(default, CLASS).__name__)

    for k, default_value in default.items():
        default_value = unwrap(
            default_value
        )  # TWO DIFFERENT Dicts CAN SHARE id() BECAUSE THEY ARE SHORT LIVED
        if is_data(d):
            existing_value = d.get(k)
        else:
            existing_value = _get_attr(d, [k])

        if existing_value == None:
            if default_value != None:
                if _get(default_value, CLASS) in data_types:
                    df = seen.get(id(default_value))
                    if df is not None:
                        _set_attr(d, [k], df)
                    else:
                        copy_dict = {}
                        seen[id(default_value)] = copy_dict
                        _set_attr(d, [k], copy_dict)
                        _all_default(copy_dict, default_value, seen)
                else:
                    # ASSUME PRIMITIVE (OR LIST, WHICH WE DO NOT COPY)
                    try:
                        _set_attr(d, [k], default_value)
                    except Exception as e:
                        if PATH_NOT_FOUND not in e:
                            get_logger().error(
                                "Can not set attribute {{name}}",
                                name=k,
                                cause=e)
        elif is_list(existing_value) or is_list(default_value):
            _set_attr(d, [k], None)
            _set_attr(d, [k],
                      listwrap(existing_value) + listwrap(default_value))
        elif (hasattr(existing_value, "__setattr__")
              or _get(existing_value, CLASS) in data_types) and _get(
                  default_value, CLASS) in data_types:
            df = seen.get(id(default_value))
            if df is not None:
                _set_attr(d, [k], df)
            else:
                seen[id(default_value)] = existing_value
                _all_default(existing_value, default_value, seen)
Esempio n. 2
0
def _iadd(self, other):
    """
    RECURSIVE ADDITION OF DATA PROPERTIES
    * LISTS ARE CONCATENATED
    * SETS ARE UNIONED
    * NUMBERS ARE ADDED
    """

    if not _get(other, CLASS) in data_types:
        get_logger().error("Expecting Data")
    d = from_data(self)
    for ok, ov in other.items():
        sv = d.get(ok)
        if sv == None:
            d[ok] = deepcopy(ov)
        elif isinstance(ov, (Decimal, float, long, int)):
            if _get(sv, CLASS) in data_types:
                get_logger().error(
                    "can not add {{stype}} with {{otype}",
                    stype=_get(sv, CLASS).__name__,
                    otype=_get(ov, CLASS).__name__,
                )
            elif is_list(sv):
                d[ok].append(ov)
            else:
                d[ok] = sv + ov
        elif is_list(ov):
            d[ok] = listwrap(sv) + ov
        elif _get(ov, CLASS) in data_types:
            if _get(sv, CLASS) in data_types:
                _iadd(sv, ov)
            elif is_list(sv):
                d[ok].append(ov)
            else:
                get_logger().error(
                    "can not add {{stype}} with {{otype}",
                    stype=_get(sv, CLASS).__name__,
                    otype=_get(ov, CLASS).__name__,
                )
        else:
            if _get(sv, CLASS) in data_types:
                get_logger().error(
                    "can not add {{stype}} with {{otype}",
                    stype=_get(sv, CLASS).__name__,
                    otype=_get(ov, CLASS).__name__,
                )
            else:
                d[ok].append(ov)
    return self
Esempio n. 3
0
    def __getitem__(self, key):
        if key == None:
            return Null
        if key == ".":
            output = self._internal_dict
            if _get(output, CLASS) in data_types:
                return self
            else:
                return output

        key = text(key)
        d = self._internal_dict

        if key.find(".") >= 0:
            seq = _split_field(key)
            for n in seq:
                if _get(d, CLASS) is NullType:
                    d = NullType(
                        d, n)  # OH DEAR, Null TREATS n AS PATH, NOT LITERAL
                elif is_list(d):
                    d = [_getdefault(dd, n) for dd in d]
                else:
                    d = _getdefault(d,
                                    n)  # EVERYTHING ELSE TREATS n AS LITERAL

            return wrap(d)
        else:
            o = d.get(key)

        if o == None:
            return NullType(d, key)
        return wrap(o)
Esempio n. 4
0
    def __getitem__(self, key):
        if key == None:
            return Null
        if key == ".":
            output = self._internal_dict
            if _get(output, CLASS) in data_types:
                return self
            else:
                return output

        key = text_type(key)
        d = self._internal_dict

        if key.find(".") >= 0:
            seq = _split_field(key)
            for n in seq:
                if _get(d, CLASS) is NullType:
                    d = NullType(d, n)  # OH DEAR, Null TREATS n AS PATH, NOT LITERAL
                elif is_list(d):
                    d = [_getdefault(dd, n) for dd in d]
                else:
                    d = _getdefault(d, n)  # EVERYTHING ELSE TREATS n AS LITERAL

            return wrap(d)
        else:
            o = d.get(key)

        if o == None:
            return NullType(d, key)
        return wrap(o)
Esempio n. 5
0
    def pop(self, key, default=Null):
        if key == None:
            return Null
        if key == ".":
            raise NotImplemented()

        key = text(key)
        d = self._internal_dict

        if key.find(".") >= 0:
            seq = _split_field(key)
            for n in seq[:-1]:
                if _get(d, CLASS) is NullType:
                    d = NullType(
                        d, n)  # OH DEAR, Null TREATS n AS PATH, NOT LITERAL
                elif is_list(d):
                    d = [_getdefault(dd, n) for dd in d]
                else:
                    d = _getdefault(d,
                                    n)  # EVERYTHING ELSE TREATS n AS LITERAL
            key = seq[-1]

        o = d.get(key)
        if o == None:
            if default is Null:
                return NullType(d, key)
            return default

        d[key] = None
        return to_data(o)
Esempio n. 6
0
def _all_default(d, default, seen=None):
    """
    ANY VALUE NOT SET WILL BE SET BY THE default
    THIS IS RECURSIVE
    """
    if default is None:
        return
    if _get(default, CLASS) is Data:
        default = object.__getattribute__(default, SLOT)  # REACH IN AND GET THE dict
        # Log = _late_import()
        # Log.error("strictly dict (or object) allowed: got {{type}}", type=_get(default, CLASS).__name__)

    for k, default_value in default.items():
        default_value = unwrap(default_value)  # TWO DIFFERENT Dicts CAN SHARE id() BECAUSE THEY ARE SHORT LIVED
        existing_value = _get_attr(d, [k])

        if existing_value == None:
            if default_value != None:
                if _get(default_value, CLASS) in data_types:
                    df = seen.get(id(default_value))
                    if df is not None:
                        _set_attr(d, [k], df)
                    else:
                        copy_dict = {}
                        seen[id(default_value)] = copy_dict
                        _set_attr(d, [k], copy_dict)
                        _all_default(copy_dict, default_value, seen)
                else:
                    # ASSUME PRIMITIVE (OR LIST, WHICH WE DO NOT COPY)
                    try:
                        _set_attr(d, [k], default_value)
                    except Exception as e:
                        if PATH_NOT_FOUND not in e:
                            get_logger().error("Can not set attribute {{name}}", name=k, cause=e)
        elif is_list(existing_value) or is_list(default_value):
            _set_attr(d, [k], None)
            _set_attr(d, [k], listwrap(existing_value) + listwrap(default_value))
        elif (hasattr(existing_value, "__setattr__") or _get(existing_value, CLASS) in data_types) and _get(default_value, CLASS) in data_types:
            df = seen.get(id(default_value))
            if df is not None:
                _set_attr(d, [k], df)
            else:
                seen[id(default_value)] = existing_value
                _all_default(existing_value, default_value, seen)
Esempio n. 7
0
def _iadd(self, other):
    if not _get(other, CLASS) in data_types:
        get_logger().error("Expecting a Mapping")
    d = unwrap(self)
    for ok, ov in other.items():
        sv = d.get(ok)
        if sv == None:
            d[ok] = deepcopy(ov)
        elif isinstance(ov, (Decimal, float, long, int)):
            if _get(sv, CLASS) in data_types:
                get_logger().error(
                    "can not add {{stype}} with {{otype}",
                    stype=_get(sv, CLASS).__name__,
                    otype=_get(ov, CLASS).__name__
                )
            elif is_list(sv):
                d[ok].append(ov)
            else:
                d[ok] = sv + ov
        elif is_list(ov):
            d[ok] = listwrap(sv) + ov
        elif _get(ov, CLASS) in data_types:
            if _get(sv, CLASS) in data_types:
                _iadd(sv, ov)
            elif is_list(sv):
                d[ok].append(ov)
            else:
                get_logger().error(
                    "can not add {{stype}} with {{otype}",
                    stype=_get(sv, CLASS).__name__,
                    otype=_get(ov, CLASS).__name__
                )
        else:
            if _get(sv, CLASS) in data_types:
                get_logger().error(
                    "can not add {{stype}} with {{otype}",
                    stype=_get(sv, CLASS).__name__,
                    otype=_get(ov, CLASS).__name__
                )
            else:
                d[ok].append(ov)
    return self
def unwraplist(v):
    """
    LISTS WITH ZERO AND ONE element MAP TO None AND element RESPECTIVELY
    """
    if is_list(v):
        if len(v) == 0:
            return None
        elif len(v) == 1:
            return unwrap(v[0])
        else:
            return unwrap(v)
    else:
        return unwrap(v)
Esempio n. 9
0
def unwraplist(v):
    """
    LISTS WITH ZERO AND ONE element MAP TO None AND element RESPECTIVELY
    """
    if is_list(v):
        if len(v) == 0:
            return None
        elif len(v) == 1:
            return unwrap(v[0])
        else:
            return unwrap(v)
    else:
        return unwrap(v)
Esempio n. 10
0
def _str(value, depth):
    """
    FOR DEBUGGING POSSIBLY RECURSIVE STRUCTURES
    """
    output = []
    if depth > 0 and _get(value, CLASS) in data_types:
        for k, v in value.items():
            output.append(str(k) + "=" + _str(v, depth - 1))
        return "{" + ",\n".join(output) + "}"
    elif depth > 0 and is_list(value):
        for v in value:
            output.append(_str(v, depth - 1))
        return "[" + ",\n".join(output) + "]"
    else:
        return str(type(value))
Esempio n. 11
0
def _str(value, depth):
    """
    FOR DEBUGGING POSSIBLY RECURSIVE STRUCTURES
    """
    output = []
    if depth >0 and _get(value, CLASS) in data_types:
        for k, v in value.items():
            output.append(str(k) + "=" + _str(v, depth - 1))
        return "{" + ",\n".join(output) + "}"
    elif depth >0 and is_list(value):
        for v in value:
            output.append(_str(v, depth-1))
        return "[" + ",\n".join(output) + "]"
    else:
        return str(type(value))
Esempio n. 12
0
def listwrap(value):
    """
    PERFORMS THE FOLLOWING TRANSLATION
    None -> []
    value -> [value]
    [...] -> [...]  (unchanged list)

    ## MOTIVATION ##
    OFTEN IT IS NICE TO ALLOW FUNCTION PARAMETERS TO BE ASSIGNED A VALUE,
    OR A list-OF-VALUES, OR NULL.  CHECKING FOR WHICH THE CALLER USED IS
    TEDIOUS.  INSTEAD WE CAST FROM THOSE THREE CASES TO THE SINGLE CASE
    OF A LIST

    # BEFORE
    def do_it(a):
        if a is None:
            return
        if not isinstance(a, list):
            a=[a]
        for x in a:
            # do something

    # AFTER
    def do_it(a):
        for x in listwrap(a):
            # do something

    """
    if value == None:
        return FlatList()
    elif is_list(value):
        if isinstance(value, list):
            return list_to_data(value)
        else:
            return value
    elif is_many(value):
        return list_to_data(list(value))
    else:
        return list_to_data([from_data(value)])
Esempio n. 13
0
def listwrap(value):
    """
    PERFORMS THE FOLLOWING TRANSLATION
    None -> []
    value -> [value]
    [...] -> [...]  (unchanged list)

    ##MOTIVATION##
    OFTEN IT IS NICE TO ALLOW FUNCTION PARAMETERS TO BE ASSIGNED A VALUE,
    OR A list-OF-VALUES, OR NULL.  CHECKING FOR WHICH THE CALLER USED IS
    TEDIOUS.  INSTEAD WE CAST FROM THOSE THREE CASES TO THE SINGLE CASE
    OF A LIST

    # BEFORE
    def do_it(a):
        if a is None:
            return
        if not isinstance(a, list):
            a=[a]
        for x in a:
            # do something

    # AFTER
    def do_it(a):
        for x in listwrap(a):
            # do something

    """
    if value == None:
        return FlatList()
    elif is_list(value):
        return wrap(value)
    elif isinstance(value, set):
        return wrap(list(value))
    else:
        return wrap([unwrap(value)])