def test_union_recursive_1(root_parser: RootParser): """ Tests that you can parse infinitely-nested dictionaries from a folder using forward references """ class A: def __init__(self, foo: str): self.foo = foo # First (preferred) way InfiniteRecursiveDictOfA = Dict[str, Union[A, 'InfiniteRecursiveDictOfA']] items = root_parser.parse_item(get_path('test2'), InfiniteRecursiveDictOfA) assert type(items['a']['a']['a']) == A assert type(items['a']['a']['b']) == A assert type(items['a']['b']) == A assert type(items['b']) == A # Less preferred way, but check that it works too InfiniteRecursiveDictOfA2 = Union[A, Dict[str, 'InfiniteRecursiveDictOfA2']] items = root_parser.parse_collection(get_path('test2'), InfiniteRecursiveDictOfA2) assert type(items['a']['a']['a']) == A assert type(items['a']['a']['b']) == A assert type(items['a']['b']) == A assert type(items['b']) == A # This is a forward reference that is equivalent to 'A'. # It should be handled correctly by parsyfiles so as not to lead to infinite recursiong InfiniteRecursiveDictOfA3 = Union[A, 'InfiniteRecursiveDictOfA3'] item = root_parser.parse_item(get_path('test2', 'b'), InfiniteRecursiveDictOfA3) assert type(item) == A
def test_union_1(root_parser: RootParser): """ Tests that parsing a Union works """ class A: def __init__(self, foo: str): self.foo = foo class B: def __init__(self, bar: float): self.bar = bar item = root_parser.parse_item(get_path('test1', 'a'), Union[A, B]) assert type(item) == A
def test_typevars_3(root_parser: RootParser): """ Tests that a TypeVar with 'constraints' may be used as a desired Type -> it will be a Union """ class A: def __init__(self, foo: str): self.foo = foo class B: def __init__(self, bar: float): self.bar = bar TV = TypeVar('TV', A, B) item = root_parser.parse_item(get_path('test2', 'a'), TV) assert type(item) == A item = root_parser.parse_item(get_path('test2', 'b'), TV) assert type(item) == B items = root_parser.parse_collection(get_path('test2'), TV) assert len(items) == 2 assert type(items['a']) == A assert type(items['b']) == B
def test_typevars_2(root_parser: RootParser): """ Tests that a TypeVar with 'bound' may be used as a desired Type directly -> it will be replaced with the bound type """ class A: def __init__(self, foo: str): self.foo = foo class B(A): def __init__(self, bar: float): super(B, self).__init__(foo=str(bar)) TV = TypeVar('TV', bound=A) item = root_parser.parse_item(get_path('test2', 'a'), TV) assert type(item) == A item = root_parser.parse_item(get_path('test2', 'b'), TV) assert type(item) == B items = root_parser.parse_collection(get_path('test2'), TV) assert len(items) == 2 assert type(items['a']) == A assert type(items['b']) == B
def test_custom_parser_ok_for_subclasses(): """ Tests that if you register a custom parser for a subclass of A, it gets correctly used to parse A (in non-strict mode, which is the default) :return: """ root_parser = RootParser() class A: def __init__(self, txt): self.txt = txt class B(A): """ a subclass of A """ pass def read_B_from_txt(desired_type: Type[dict], file_object: TextIOBase, logger: Logger, *args, **kwargs) -> str: # read the entire stream into a string str_io = StringIO() shutil.copyfileobj(file_object, str_io) # only return the first character return B(str_io.getvalue()[0]) # before registering a parser for B, only generic parsers are able to parse a A before_capa = root_parser.get_capabilities_for_type(A)['.txt'] assert list(before_capa.keys()) == ['3_generic'] # register a parser for B root_parser.register_parser( SingleFileParserFunction(parser_function=read_B_from_txt, streaming_mode=True, supported_exts={'.txt'}, supported_types={B})) # after registering the new parser appears in the list able to parse A after_capa = root_parser.get_capabilities_for_type(A)['.txt'] assert str(after_capa['2_approx_match'][0]) == '<read_B_from_txt>' a = root_parser.parse_item(get_path('b64pickle-float-1.0=True'), A) # check that the custom parser was used, not the generic 'construct from string' assert len(a.txt) == 1 assert a.txt == 'g'
def parse_with_new_instance(): rp = RootParser() result = rp.parse_item( os.path.join(THIS_DIR, 'test_data/b64pickle-float-1.0=True'), bool) assert result == True