Source code for architxt.generator

"""Generator of instances."""

from collections.abc import Generator, Iterable

from architxt.schema import Schema
from architxt.tree import NodeLabel, NodeType, Tree

__all__ = ['gen_instance']

GROUP_SCHEMA = dict[str, tuple[str, ...]]
REL_SCHEMA = dict[str, tuple[str, str]]


[docs] def gen_group(schema: Schema, name: str) -> Tree: """ Generate a group tree structure with the given name and elements. :param schema: A schema to guide the tree structure. :param name: The name of the group. :return: The generated group tree. >>> from architxt.schema import Group >>> group = Group(name='Fruits', entities={'Apple', 'Banana', 'Cherry'}) >>> schema = Schema.from_description(groups={group}) >>> group_tree = gen_group(schema, 'Fruits') >>> print(group_tree) (GROUP::Fruits (ENT::Apple data) (ENT::Banana data) (ENT::Cherry data)) """ group = next(group for group in schema.groups if group.name == name) entities = [Tree(NodeLabel(NodeType.ENT, ent), ['data']) for ent in sorted(group.entities)] return Tree(NodeLabel(NodeType.GROUP, group.name), entities)
[docs] def gen_relation(schema: Schema, name: str) -> Tree: """ Generate a relation tree structure based on the given parameters. :param schema: A schema to guide the tree structure. :param name: The name of the relationship. :return: The generated relation tree. >>> from architxt.schema import Group, Relation >>> schema = Schema.from_description( ... groups={ ... Group(name='Fruits', entities={'Apple', 'Banana'}), ... Group(name='Colors', entities={'Red', 'Blue'}), ... }, ... relations={Relation(name='Preference', left='Fruits', right='Colors')} ... ) >>> relation_tree = gen_relation(schema, 'Preference') >>> print(relation_tree) (REL::Preference (GROUP::Fruits (ENT::Apple data) (ENT::Banana data)) (GROUP::Colors (ENT::Blue data) (ENT::Red data))) """ rel = next(rel for rel in schema.relations if rel.name == name) subject_tree = gen_group(schema, rel.left) object_tree = gen_group(schema, rel.right) return Tree(NodeLabel(NodeType.REL, rel.name), [subject_tree, object_tree])
[docs] def gen_collection(name: str, elements: Iterable[Tree]) -> Tree: """ Generate a collection tree. :param name: The name of the collection. :param elements: The list of trees that make up the collection. :return: A tree representing the collection. >>> from architxt.tree import Tree >>> elems = [Tree('Element1', []), Tree('Element2', [])] >>> collection_tree = gen_collection('Collection', elems) >>> print(collection_tree) (COLL::Collection (Element1 ) (Element2 )) """ label = NodeLabel(NodeType.COLL, name) return Tree(label, elements)
[docs] def gen_instance(schema: Schema, *, size: int = 200, generate_collections: bool = True) -> Generator[Tree, None, None]: """ Generate a database instance as a tree, based on the given groups and relations schema. :param schema: A schema to guide the tree structure. :param size: An integer specifying the size of the generated trees. :param generate_collections: A boolean indicating whether to generate collections or not. :return: A tree representing the generated instance. """ # Generate tree instances for each group for group in schema.groups: generated = (gen_group(schema, group.name) for _ in range(size)) if generate_collections: yield gen_collection(group.name, generated) else: yield from generated # Generate tree instances for each relation for relation in schema.relations: generated = (gen_relation(schema, relation.name) for _ in range(size)) if generate_collections: yield gen_collection(relation.name, generated) else: yield from generated