API

delimited.path

This module defines Path objects which are used to define paths to nested data using one or more path segments.

Path

class Path(value=None)

The abstract base class for Path objects.

_encode(value)

Abstract method. Encode value to collapsed path format and return.

Parameters:value (list) – The value to encode
Returns:Encoded value
Return type:Value in collapsed path format.
_decode(value)

Abstract method. Decode value in collapsed path format format to a list and return.

Parameters:value – The value to decode
Returns:Decoded value
Return type:list

DelimitedStrPath

class DelimitedStrPath(value=None)

This class implements delimited string path notation as its collapsed path format.

"key1.key2.key3"
segments

A list where this instances path segments are stored.

_encode(value)

Encode value to collapsed path format and return.

Parameters:value (list) – The value to encode
Returns:Encoded value
Return type:Value in collapsed path format
mypath = DelimitedStrPath()
mypath._encode(["key1", "key2", "key3"])
# returns "key1.key2.key3"
_decode(value)

Decode value in collapsed path format to list and return.

Parameters:value – The value to decode
Returns:Decoded value
Return type:list
mypath = DelimitedStrPath()
mypath._decode("key1.key2.key3")
# returns ["key1", "key2", "key3"]
append(value)

Add value to the end of segments. Accepts a path segment.

Parameters:value – The value to append
mypath = DelimitedStrPath("key1.key2")
mypath.append("key3")
print(mypath)
# prints "key1.key2.key3"
extend(values)

Add each item of values to the end of segments. Accepts an instance of self or a encoded group of path segments.

Parameters:value – The values to extend with
mypath = DelimitedStrPath("key1.key2")
mypath.extend("key3.key4")
print(mypath)
# prints "key1.key2.key3.key4"
insert(i, value)

Insert value at index i in segments.

Parameters:
  • value – The value to insert
  • i (int) – The index at which to insert
mypath = DelimitedStrPath("key1.key3")
mypath.insert(1, "key2")
print(mypath)
# prints "key1.key2.key3"
remove(value)

Remove the first item from segments that is equal to value. Raise an exception if value is not found.

Parameters:value – The value to remove
Raises:AttributeError
mypath = DelimitedStrPath("root.key1.key2.key3")
mypath.remove("root")
print(mypath)
# prints "key1.key2.key3"
pop(*args)

Remove the item at index i from segments and return.

Parameters:i (int) – The index from which to remove
Returns:Value at index i in segments
mypath = DelimitedStrPath("key1.key2.key3")
mypath.pop(1)
# returns "key2"

print(mypath)
# prints "key1.key3"

If i is not given, remove and return the first value from segments.

mypath = DelimitedStrPath("key1.key2.key3")
mypath.pop()
# returns "key1"

print(mypath)
# prints "key2.key3"
Returns:First value from segments
clear()

Remove all values from segments.

mypath = DelimitedStrPath("key1.key2.key3")
mypath.clear()
print(mypath)
# prints ""
index(value)

Return the index of the first item that is equal to value in segments. Raise an exception if value is not found.

Parameters:value – The value to search for
Returns:The index at which the value was found
Return type:int
Raises:AttributeError
mypath = DelimitedStrPath("key1.key2.key3")
mypath.index("key2")
# returns 1
count(value)

Return the number of times value appears in segments.

Parameters:value – The value to count for
Returns:The count of value from segments
Return type:int
mypath = DelimitedStrPath("key1.key2.key3")
mypath.index("key1")
# returns 1
reverse()

Reverse segments in place.

mypath = DelimitedStrPath("key1.key2.key3")
mypath.reverse()
print(mypath)
# prints "key3.key3.key1"
copy()

Return an instance of DelimitedStrPath with its segments set to a copy of this instances segments.

mypath = DelimitedStrPath("key1.key2.key3")
mypath.copy()
# returns instance of DelimitedStrPath
clone()

Return an isntance of DelimitedStrPath with its segments set to a reference to this instances segments.

mypath1 = DelimitedStrPath("key1.key2.key3")
mypath2 = mypath1.clone()
mypath2[1] = "foo"
print(mypath1)

# returns "key1.foo.key3"
encode()

Call _encode() with segments as the values keyword argument and return.

mypath = DelimitedStrPath("key1.key2.key3")
mypath.encode()
# returns "key1.key2.key3"

TuplePath

class TuplePath(value)

This class implements tuple path notation as its collapsed path format.

("key1", "key2", "key3")

TuplePaths can handle any hashable type as a path segment. All methods except for _encode() and _decode() are the same as DelimitedStrPath as they both inherit from Path.

_encode(value)

Encode a list to collapsed path format and return.

TuplePath._encode(["key1", "key2", "key3"])
# returns ("key1", "key2", "key3")
Parameters:value (list) – The value to encode
Returns:Encoded value
Return type:Value in collapsed path format.
_decode(value)

Decode collapsed path format format to a list and return.

TuplePath._encode(("key1", "key2", "key3"))
# returns ["key1", "key2", "key3"]
Parameters:value – The value to decode
Returns:Decoded value
Return type:list

delimited.container

This module defines NestedContainer objects. A NestedContainer object implements an interface through which nested data can be accessed and modified.

NestedContainer

class NestedContainer(data=None)

The abstract base class for NestedContainer objects. The path and container attributes must be overridden when subclassing.

path

The Path class used by this NestedContainer.

container

The container type that this NestedContainer emulates.

DelimitedDict

class DelimitedDict(data=None)

This class implements delimited string path notation in use with the dict container type.

path

Set to DelimitedStrPath

container

Set to dict

data

Instance data

_merge(a, b)

Recursively merge container a into a copy of container b, overwriting values from b if conflicts are found.

Parameters:
  • a (dict) – Container to merge from
  • b (dict) – Container to merge into
Returns:

Merged data

Return type:

boolean

data_1 = {
  "key1": "value1",
  "key2": "value1" # conflict
}

data_2 = {
  "key2": "value2", # conflict
  "key3": "value2",
}

mycontainer = DelimitedDict()
mycontainer._merge(data_2, data_1)

# returns {
#   "key1": "value1",
#   "key2": "value2",
#   "key3": "value2"
# }
_expand(data)

Recursively expand collapsed nested data and return.

Parameters:data (dict) – The data to expand
Returns:Expanded data
Return type:dict
data = {
  "key1.key2": {
    "key3": "value"
  }
}

mycontainer = DelimitedDict()
mycontainer._expand(data)

# returns {
#   "key1": {
#     "key2": {
#       "key3": "value"
#     }
#   }
# }
_collapse()

Recursively collapse nested data and return. The param func should accept two params, key and value which will be the key of the current level of nested data being collapsed and the value of that key respectively.

Parameters:
  • data (dict) – The nested data to collapse
  • func (function) – A function used to determine whether to collapse a level of nested data
Returns:

Collapsed data

Return type:

dict

data = {
  "key1": {
    "key2": {
      "key3": "value"
    }
  }
}

mycontainer = DelimitedDict()
mycontainer._collapse(data)

# returns {
#   "key1.key2.key3": "value"
# }

def should_collapse(path, value):
  if path == "key3":
    return False
  return True

mycontainer._collapse(data, func=should_collapse)

# returns {
#   "key1.key2": {
#     "key3": "value"
#   }
# }
items()

Yield key, value tuple for values in data

keys()

Yield keys for keys in data

values()

Yield values for values in data

ref(path=None, create=False)

Return a reference to nested data at path. If create is True and missing key(s) are encountered while trying to resolve path, create the missing key(s) using an instance of self.container as the value.

Parameters:
  • path (str) – The path to resolve
  • create (boolean) – If True, create missing key(s)
data = {
  "key1": {
    "key2": {
      "key3": "value"
    }
  }
}

mycontainer = DelimitedDict(data)
mycontainer.ref("key1.key2")

# returns {
#   "key3": "value"
# }
get(path=None, *args)

Return a copy of nested data at path. First value of args is considered the default value, and if the internal ref() call raises a KeyError, the default value will be returned.

Parameters:
  • path (str) – The path to resolve
  • args[0] – Default value
data = {
  "key1": {
    "key2": {
      "key3": "value"
    }
  }
}

mycontainer = DelimitedDict(data)
mycontainer.ref("key1.key2")

# returns {
#   "key3": "value"
# }
has(path=None)

Return True if path can be resolved in data else False.

Parameters:path (str) – The path to resolve
Return type:boolean
data = {
  "key1": {
    "key2": {
      "key3": "value"
    }
  }
}

mycontainer = DelimitedDict(data)
mycontainer.has("key1.key2")
# returns True

mycontainer.has("foo")
# returns False
copy(path=None)

Return a new instance of self with its data set to a deep copy of this instances data.

Parameters:path (str) – The path to resolve
Returns:New instance with copied data
Return type:DelimitedDict
mycontainer = DelimitedDict({"key": "value"})
mycontainer.copy()

# returns instance of DelimitedDict
clone()

Return a new instance of self with its data set to a reference of this instances data.

Return type:instance of DelimitedDict
mycontainer = DelimitedDict({"key": "value"})
mycontainer.clone()

# returns instance of DelimitedDict
merge(data, path=None)

Merge data with a copy of data at path and return merged data. Will accept instance of DelimitedDict or instance of container.

Parameters:
  • data (dict) – The data to merge
  • path (str) – The path at which to merge the data
Returns:

The merged data

Return type:

dict

mycontainer = DelimitedDict({"key1": "value"})
mycontainer.merge({"key2": "value"})

# returns {
#   "key1": "value",
#   "key2": "value"
# }
collapse(path=None, func=None)

Collapse data at path and return. Use func to determine if a level of nested data should be collapsed.

Parameters:
  • path (str) – The path to resolve
  • func (callable) – The callable to use
Returns:

The collapsed data

Return type:

dict

data = {
  "key1": {
    "key2": {
      "key3": "value"
    }
  }
}

mycontainer = DelimitedDict(data)
mycontainer.collapse("key1")

# returns {
#   "key2.key3": "value"
# }
update(data, path=None)

Update data at path with data.

Parameters:
  • data (dict) – The data to use
  • path (str) – The path at which to update
mycontainer = DelimitedDict({"key1": "value"})
mycontainer.update({"key2": "value"})
mycontainer.get()

# returns {
#   "key1": "value",
#   "key2": "value"
# }
set(path, value, create=True)

Set value at path in data. If create is True, create missing keys while trying to resolve path.

Parameters:
  • path (str) – The path to resolve
  • value – The value to set
  • create (boolean) – If True, create keys while resolving path
mycontainer = DelimitedDict()
mycontainer.set("key", "value")
mycontainer.get()

# returns {"key": "value"}
push(path, value, create=True)

Push value to list at path in data. If create is True and key for final path segment is not set, create key and create value as empty list and append value to list. If create is True and key for final path segment is wrong type, create value as list with existing value and append value to list.

Parameters:
  • path (str) – The path to resolve
  • value – The value to append
  • create (boolean) – If True, create list and append
mycontainer = DelimitedDict({"key": []})
mycontainer.push("key", "value")
mycontainer.get()

# returns {"key": ["value"]}
pull(path, value, cleanup=False)

Remove value from list at path in data. If cleanup is True and removal of value results in an empty list, remove list and key.

Parameters:
  • path (str) – The path to resolve
  • value – The value to pull
  • cleanup (boolean) – If True, remove empty list and key
mycontainer = DelimitedDict({"key": ["value"]})
mycontainer.push("key", "value")
mycontainer.get()

# returns {"key": []}
unset(path, cleanup=False)

Remove value and last key at path. If cleanup is True and key removal results in empty container, recursively remove empty containers in reverse order of path.

Parameters:
  • path (str) – The path to resolve
  • cleanup (boolean) – If True, recursively remove empty containers
mycontainer = DelimitedDict({"key": "value"})
mycontainer.unset("key")
mycontainer.get()

# returns {}

DelimitedOrderedDict

class DelimitedOrderedDict(data=None)

This class implements delimited string path notation in use with the OrderedDict container type.

NestedDict

class NestedDict(data=None)

This class implements tuple path notation in use with the dict container type.

NestedOrderedDict

class NestedOrderedDict(data=None)

This class implements tuple path notation in use with the OrderedDict container type.