pg.KeyPath

Accessible via pg.KeyPath, pg.object_utils.KeyPath.

class KeyPath(key_or_key_list=None, parent=None)[source]

Bases: pg.Formattable

Represents a path of keys from the root to a node in a tree.

KeyPath is an important concept in PyGlove, which is used for representing a symbolic object’s location (see pg.Symbolic) within its symbolic tree. For example:

@pg.members([
    ('x', pg.typing.Int()),
    ('y', pg.typing.Str())
])
class A(pg.Object):
  pass

@pg.members([
    ('z', pg.typing.Object(A))
])
class B(pg.Object):
  pass

a = A(x=1, y='foo')
b = B(z=a)
assert a.sym_path == 'z' # The path to object `a` is 'z'.
assert b.sym_path == ''  # The root object's KeyPath is empty.

Since each node in a tree has a unique location, given the root we shall be able to use a KeyPath object to locate the node. With the example above, we can query the member x of object a via:

pg.KeyPath.parse('z.x').query(b)  # Should return 1.

Similarly, we can modify a symbolic object’s sub-node based on a KeyPath object. See pg.Symbolic for modifying sub-nodes in a symbolic tree.

Attributes:

depth

The depth of this path.

is_root

Returns True if this path is the root of a tree.

key

The rightmost key of this path.

keys

A list of keys in this path.

parent

The KeyPath object for current node's parent.

path

JSONPath representation of current path.

Methods:

exists(src)

Returns whether current path exists in source object.

format(*args, **kwargs)

Format current path.

from_value(value)

Returns a KeyPath object from a KeyPath equivalence.

get(src[, default_value, use_inferred])

Gets the value of current path from an object with a default value.

parse(path_str[, parent])

Creates a KeyPath object from parsing a JSONPath-like string.

path_str([preserve_complex_keys])

Returns JSONPath representation of current path.

query(src[, use_inferred])

Query the value from the source object based on current path.

property depth: int[source]

The depth of this path.

exists(src)[source]

Returns whether current path exists in source object.

Return type:

bool

format(*args, **kwargs)[source]

Format current path.

classmethod from_value(value)[source]

Returns a KeyPath object from a KeyPath equivalence.

Return type:

pg.KeyPath

get(src, default_value=None, use_inferred=False)[source]

Gets the value of current path from an object with a default value.

Return type:

Any

property is_root: bool[source]

Returns True if this path is the root of a tree.

property key: Any[source]

The rightmost key of this path.

property keys: List[Any][source]

A list of keys in this path.

property parent: KeyPath[source]

The KeyPath object for current node’s parent.

Example:

path = pg.KeyPath.parse('a.b.c.')
assert path.parent == 'a.b'
Returns:

A KeyPath object for the parent of current node.

Raises:

KeyError – If current path is the root.

classmethod parse(path_str, parent=None)[source]

Creates a KeyPath object from parsing a JSONPath-like string.

The JSONPath (https://restfulapi.net/json-jsonpath/) like string is defined as following:

<path>        := <empty> | {<dict-key>[.<dict-key>]*}
<dict-key>     := <identifier>['[('<list-key>|<special-dict-key>)']']*
<list-key>    := <number>
<special-dict-key> := <string-with-delimiter-chars>
<delimiter_chars> := '[' | ']' | '.'

For example, following keys are valid path strings:

''               : An empty path representing the root of a path.
'a'              : A path that contains a dict key 'a'.
'a.b'            : A path that contains two dict keys 'a' and 'b'.
'a[0]'           : A path that contains a dict key 'a' and a list key 0.
'a.0.'           : A path that contains two dict keys 'a' and '0'.
'a[0][1]'        : A path that contains a dict key 'a' and two list keys
                   0 and 1 for a multi-dimension list.
'a[x.y].b'       : A path that contains three dict keys: 'a', 'x.y', 'b'.
                   Since 'x.y' has delimiter characters, it needs to be
                   enclosed in brackets.

TODO(daiyip): Support paring KeyPath from keys of complex types. Now this method only supports parsing KeyPath of string and int keys. That being said, format/parse are not symmetric, while format can convert a KeyPath that includes complex keys into a string, parse is not able to convert them back.

Return type:

pg.KeyPath

Parameters:
  • path_str – A JSON-path-like string.

  • parent – Parent KeyPath object.

Returns:

A KeyPath object.

Raises:

ValueError – Path string is in bad format.

property path: str[source]

JSONPath representation of current path.

path_str(preserve_complex_keys=True)[source]

Returns JSONPath representation of current path.

Return type:

str

Parameters:
  • preserve_complex_keys – if True, complex keys such as ‘x.y’ will be

  • brackets. (preserved by quoted in)

  • example (For) – KeyPath([‘a’, ‘x.y’, ‘b’]) will return ‘a[x.y].b’ when

  • True (preserve_complex_keys is)

  • when (and a.x.y.b)

  • False. (preserve_complex_keys is)

Returns:

Path string.

query(src, use_inferred=False)[source]

Query the value from the source object based on current path.

Example:

@pg.members([
    ('x', pg.typing.Int()),
    ('y', pg.typing.Str())
])
class A(pg.Object):
  pass

@pg.members([
    ('z', pg.typing.Object(A))
])
class B(pg.Object):
  pass

b = B(z=A(x=1, y='foo'))
assert pg.KeyPath.parse('z.x').query(b) == 1
Return type:

Any

Parameters:
  • src – Source value to query.

  • use_inferred – If True, infer pg.Inferential values. Otherwise returns their symbolic form. Applicable only for symbolic values.

Returns:

Value from src if path exists.

Raises:
  • KeyError – Path doesn’t exist in src.

  • RuntimeError – Called on a KeyPath that is considered as removed.