pg.Schema¶
Accessible via pg.Schema
, pg.typing.Schema
.
- class Schema(fields, name=None, base_schema_list=None, description=None, *, allow_nonconst_keys=False, metadata=None)[source]¶
Bases:
pg.Formattable
,pg.JSONConvertible
Class that represents a schema.
PyGlove’s runtime type system is based on the concept of
Schema
( classpg.Schema
), which defines what symbolic attributes are held by a symbolic type (e.g. a symbolic dict, a symbolic list or a symbolic class) and what values each attribute accepts. ASchema
object consists of a list ofField
(classpg.Field
), which define the acceptable keys and their values for these attributes. ASchema
object is usually created automatically and associated with a symbolic type upon its declaration, through decorators such aspg.members
,pg.symbolize
orpg.functor
. For example:@pg.members([ ('x', pg.typing.Int(default=1)), ('y', pg.typing.Float().noneable()) ]) class A(pg.Object): pass print(A.__schema__) @pg.symbolize([ ('a', pg.typing.Int()), ('b', pg.typing.Float()) ]) def foo(a, b): return a + b print(foo.__schema__)
Implementation-wise it holds an ordered dictionary of a field key (
pg.KeySpec
) to its field definition (pg.Field
). The key specification describes what keys/attributes are acceptable for the field, and value specification within theField
describes the value type of the field and their validation rules, default values, and etc.Symbolic attributes can be inherited during subclassing. Accordingly, the schema that defines a symbolic class’ attributes can be inherited too by its subclasses. The fields from the bases’ schema will be carried over into the subclasses’ schema, while the subclass can override, by redefining that field with the same key. The subclass cannot override its base classes’ field with arbitrary value specs, it must be overriding non-frozen fields with more restrictive validation rules of the same type, or change their default values. See
pg.ValueSpec
for more details.The code snippet below illustrates schema inheritance during subclassing:
@pg.members([ ('x', pg.typing.Int(min_value=1)), ('y', pg.typing.Float()), ]) class A(pg.Object): pass @pg.members([ # Further restrict inherited 'x' by specifying the max value, as well # as providing a default value. ('x', pg.typing.Int(max_value=5, default=2)), ('z', pg.typing.Str('foo').freeze()) ]) class B(A): pass assert B.schema.fields.keys() == ['x', 'y', 'z'] @pg.members([ # Raises: 'z' is frozen in class B and cannot be extended further. ('z', pg.typing.Str()) ]) class C(B): pass
With a schema, an input dict can be validated and completed by the schema via
apply
. If required a field is missing from the schema, and the object’s allow_partial is set to False, aKeyError
will raise. Otherwise a partially validated/transformed dict will be returned. Missing values in the object will be placeheld bypg.MISSING_VALUE
.Attributes:
Returns whether to allow non-const keys.
Returns the description for the schema.
Returns the field that matches multiple keys if any.
Returns fields of this schema.
Returns metadata of this schema.
Name of this schema.
Methods:
apply
(dict_obj[, allow_partial, ...])Apply this schema to a dict object, validate and transform it.
extend
(base)Extend current schema based on a base schema.
format
([compact, verbose, root_indent, ...])Format current Schema into nicely printed string.
get
(key[, default])Returns field by key with default value if not found.
get_field
(key)Get field definition (Field) for a key.
is_compatible
(other)Returns whether current schema is compatible with the other schema.
items
()Returns an iterable of (KeySpec, Field) tuple in declaration order.
keys
()Return an iteratable of KeySpecs in declaration order.
merge
(schema_list[, name, description])Merge multiple schemas into one.
resolve
(keys)Resolve keys by grouping them by their matched fields.
set_description
(description)Sets the description for the schema.
set_name
(name)Sets the name of this schema.
to_json
(**kwargs)Returns a plain Python value as a representation for this object.
validate
(dict_obj[, allow_partial, root_path])Validates whether dict object is conformed with the schema.
values
()Returns an iterable of Field in declaration order.
- apply(dict_obj, allow_partial=False, child_transform=None, root_path=None)[source]¶
Apply this schema to a dict object, validate and transform it.
- Return type:
- Parameters:
dict_obj – JSON dict type that (maybe) conform to the schema.
allow_partial – Whether allow partial object to be created.
child_transform –
Function to transform child node values in dict_obj into their final values. Transform function is called on leaf nodes first, then on their containers, recursively. The signature of transform_fn is: (path, field, value) -> new_value Argument path is a KeyPath object to the field. Argument field is on which Field the value should apply. Argument value is the value from input that matches a Field from the schema, with child fields already transformed by this function. There are possible values for these two arguments:
------------------------------------------------------------ | field | value ------------------------------------------------------------ The value with | | applicable Field is | Not None | Not MISSING_VALUE found in schema. | | value. | | ------------------------------------------------------------ The value is | | not present for a | Not None | MISSING_VALUE key defined in schema. | | ------------------------------------------------------------
Return value will be inserted to the parent dict under path, unless return value is MISSING_VALUE.
root_path – KeyPath of root element of dict_obj.
- Returns:
A dict filled by the schema with transformed values.
- Raises:
KeyError – Key is not allowed in schema.
TypeError – Type of dict values are not aligned with schema.
ValueError – Value of dict values are not aligned with schema.
- format(compact=False, verbose=True, root_indent=0, *, markdown=False, cls_name=None, bracket_type=BracketType.ROUND, **kwargs)[source]¶
Format current Schema into nicely printed string.
- Return type:
- is_compatible(other)[source]¶
Returns whether current schema is compatible with the other schema.
NOTE(daiyip): schema A is compatible with schema B when: schema A and schema B have the same keys, with compatible values specs.
- classmethod merge(schema_list, name=None, description=None)[source]¶
Merge multiple schemas into one.
For fields shared by multiple schemas, the first appeared onces will be used in the merged schema.
- Return type:
- Parameters:
schema_list – A list of schemas to merge.
name – (Optional) name of the merged schema.
description – (Optinoal) description of the schema.
- Returns:
The merged schema.
- to_json(**kwargs)[source]¶
Returns a plain Python value as a representation for this object.
A plain Python value are basic python types that can be serialized into JSON, e.g:
bool
,int
,float
,str
,dict
(with string keys),list
,tuple
where the container types should have plain Python values as their values.