def test_is_one_of_false_hierarchy(self): t_liquid = RxType("liquid") t_water = RxType("water", t_liquid) t_lake = RxType("lake", t_water) type_set = RxTypeSet() type_set._types = {"liquid": t_liquid} self.assertFalse(type_set.is_one_of("liquid", ["water", "lake"]))
def test_is_one_of_true(self): t_liquid = RxType("liquid") t_solid = RxType("solid") t_gas = RxType("gas") t_water = RxType("water", t_liquid) type_set = RxTypeSet() type_set._types = {"water": t_water} self.assertTrue(type_set.is_one_of("water", ["liquid", "solid", "gas"]))
def test_is_one_of_false_unrelated(self): t_liquid = RxType("liquid") t_solid = RxType("solid") t_gas = RxType("gas") t_plasma = RxType("plasma") type_set = RxTypeSet() type_set._types = {"plasma": t_plasma} self.assertFalse( type_set.is_one_of("plasma", ["liquid", "solid", "gas"]))
class RxNodeFactory: def __init__(self, printable_subset: Optional[Iterable[str]] = None) -> None: self.omit_types: Set[str] = set() self.omit_wrappers: Set[str] = set() self._rxtypes = RxTypeSet() self._char_sets = CharSets(self._rxtypes) self._rxwrappers = RxWrapperSet(self._char_sets, printable_subset) def set_omit( self, types: Optional[Union[str, Iterable[str]]] = None, wrappers: Optional[Union[str, Iterable[str]]] = None, ) -> None: if types and not isinstance(types, set): types = set(types) self.omit_types = types or set() if wrappers and not isinstance(wrappers, set): wrappers = set(wrappers) self.omit_wrappers = wrappers or set() def clear_omit(self, types: bool = False, wrappers: bool = False) -> None: if not (types and wrappers): self.clear_omit(types=True, wrappers=True) if types: self.omit_types.clear() if wrappers: self.omit_wrappers.clear() def parse_rxspec(self, rxspec: RxSpec) -> NodeSpec: if not isinstance(rxspec, list): rxspec = [rxspec] node_spec = {"rw_name": rxspec[0]} for spec in rxspec[1:]: if self._rxwrappers.wrapper_is_type(first_nested(spec), "mod"): node_spec["modifier"] = self.parse_rxspec(spec) else: node_spec["children"] = [ self.parse_rxspec(child) for child in spec ] return node_spec def make_node( self, rw_name: Optional[str] = None, children: Union[List[NodeSpec], int] = RAND, modifier: Optional[Union[NodeSpec, int]] = None, rxwrapper: Optional[RxWrapper] = None, is_child: bool = False, strict_type_match: bool = False, ) -> RxNode: """ children format: [{'rw_name': regex_wrapper_name, 'children': [<children>]})] modifier format: {'rw_name': <modifier_name>, 'children': <children>, 'modifier': <modifier>} """ if not rxwrapper: if not rw_name: raise ValueError("must provide regex wrapper object or name") rxwrapper = self._rxwrappers[rw_name] child_nodes: List[RxNode] = [] if rxwrapper.child_count != 0: if children == RAND: child_types: List[str] = list( filter( lambda type_name: not self._rxtypes.is_one_of( type_name, self.omit_types), rxwrapper.child_types, )) if rxwrapper.uniform_child_types: child_types = sample(rxwrapper.child_types, 1) child_nodes = [ self.make_random_node(choice(child_types), is_child=True) for i in range(rxwrapper.get_child_count()) ] else: for child in children: child_nodes.append(self.make_node(**child, is_child=True)) node: RxNode = RxNode(self._char_sets, rxwrapper, child_nodes, is_child) if rxwrapper.is_modifiable: if modifier == RAND: # print("- ", node.name) # print("- ", rxwrapper.name) # print("- ", rxwrapper.rxtype) # print("- ", rxwrapper.rxtype.is_type_name("mod")) # if wrapper is not a modifier, build a modifier. Otherwise, build mod-modifier. mod_type: str = ("mmod" if rxwrapper.rxtype.is_type_name("mod") else "mod") # print("- ", mod_type) # if mod_type (to make) is mod, then don't build an mmod # omit_types += ["mmod"] if mod_type == "mod" else [] # print(">> ", omit_types) if mod_type not in self.omit_types: modifier_node: RxNode = self.make_random_node( mod_type, strict_typing=True) node.set_modifier(modifier_node) # print("-- ", modifier) elif modifier: modifier_node = self.make_node(**modifier) node.set_modifier(modifier_node) return node def make_random_node( self, type_name: str = "re", is_child: bool = False, prob_modifier: float = P_MODIFIER, strict_typing: bool = False, ) -> RxNode: rxtype: RxType = self._rxtypes[type_name] # filter RxWrapper.wrappers with items that match rxtype filtered_wrappers: List[RxWrapper] = list( filter( lambda rxwrapper: rxwrapper.rxtype.is_type( rxtype, strict=strict_typing), self._rxwrappers.all(), )) # filter out types specified for omission in node generation for omit in self.omit_types: omit_type: RxType = self._rxtypes[omit] filtered_wrappers = list( filter( lambda rxwrapper: not rxwrapper.rxtype.is_type(omit_type), filtered_wrappers, )) # filter out characters if is root node and suppression parameter specified if not is_child and SUPPRESS_ROOT_CHARS: filtered_wrappers = list( filter( lambda rxwrapper: not rxwrapper.rxtype.is_type( self._rxtypes["printable"]), filtered_wrappers, )) # filter out wrappers specified for omission in node generation for omit in self.omit_wrappers: filtered_wrappers = list( filter(lambda rxwrapper: rxwrapper.name != omit, filtered_wrappers)) rxwrapper: RxWrapper = choice(filtered_wrappers) modifier: Optional[int] = None if rxwrapper.is_modifiable and random() < prob_modifier: modifier = RAND return self.make_node( rxwrapper=rxwrapper, modifier=modifier, is_child=is_child, )