Example #1
0
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
Example #2
0
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
Example #5
0
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