def test_root_link_alias(): data = { 'xN': {'a': 1, 'b': 2}, } @listify def x_fields(fields, ids): for i in ids: yield [data[i][f.name] for f in fields] graph = Graph([ Node('X', [ Field('a', None, x_fields), Field('b', None, x_fields), ]), Root([ Link('x', TypeRef['X'], lambda: 'xN', requires=None), ]), ]) result = execute(graph, q.Node([ q.Link('x', q.Node([q.Field('a')]), alias='x1'), q.Link('x', q.Node([q.Field('b')]), alias='x2'), ])) check_result(result, { 'x1': {'a': 1}, 'x2': {'b': 2}, })
def test_node_complex_fields(): f1 = Mock(return_value=[1]) f2 = Mock(return_value=[[{'f': 'marshes'}]]) f3 = Mock(return_value=[[{'g': 'colline'}]]) f4 = Mock(return_value=[[[{'h': 'magi'}]]]) graph = Graph([ Node('a', [ Field('b', Optional[Record[{'f': Integer}]], f2), Field('c', Record[{'g': Integer}], f3), Field('d', Sequence[Record[{'h': Integer}]], f4), ]), Root([ Link('e', Sequence[TypeRef['a']], f1, requires=None), ]), ]) check_result( execute(graph, build([Q.e[Q.b[Q.f], Q.c[Q.g], Q.d[Q.h]]])), {'e': [{'b': {'f': 'marshes'}, 'c': {'g': 'colline'}, 'd': [{'h': 'magi'}]}]}, ) f1.assert_called_once_with() f2.assert_called_once_with( [q.Link('b', q.Node([q.Field('f')]))], [1], ) f3.assert_called_once_with( [q.Link('c', q.Node([q.Field('g')]))], [1], ) f4.assert_called_once_with( [q.Link('d', q.Node([q.Field('h')]))], [1], )
def test_non_field(): check_errors(q.Node([q.Field('amyls')]), [ 'Trying to query "root.amyls" link as it was a field', ]) check_errors(q.Node([q.Field('decants')]), [ 'Trying to query "decants" node as it was a field', ])
def test_links(): fb = Mock(return_value=[1]) fc = Mock(return_value=[2]) fi = Mock(return_value=[3]) fd = Mock(return_value=[['boners']]) fe = Mock(return_value=[['julio']]) graph = Graph([ Node('a', [ Field('d', None, fd), Field('e', None, fe), ]), Root([ Field('i', None, fi), Link('b', Sequence[TypeRef['a']], fb, requires=None), Link('c', Sequence[TypeRef['a']], fc, requires='i'), ]), ]) result = execute(graph, build([Q.b[Q.d], Q.c[Q.e]])) check_result(result, {'b': [{'d': 'boners'}], 'c': [{'e': 'julio'}]}) fi.assert_called_once_with([q.Field('i')]) fb.assert_called_once_with() fc.assert_called_once_with(3) fd.assert_called_once_with([q.Field('d')], [1]) fe.assert_called_once_with([q.Field('e')], [2])
def test_links(): f1 = Mock(return_value=[1]) f2 = Mock(return_value=[2]) f3 = Mock(return_value=[['boners']]) f4 = Mock(return_value=[['julio']]) graph = Graph([ Node('a', [ Field('d', None, f3), Field('e', None, f4), ]), Root([ Link('b', Sequence[TypeRef['a']], f1, requires=None), Link('c', Sequence[TypeRef['a']], f2, requires=None), ]), ]) result = execute(graph, build([Q.b[Q.d], Q.c[Q.e]])) check_result(result, {'b': [{'d': 'boners'}], 'c': [{'e': 'julio'}]}) assert result.index == {'a': {1: {'d': 'boners'}, 2: {'e': 'julio'}}} f1.assert_called_once_with() f2.assert_called_once_with() with reqs_eq_patcher(): f3.assert_called_once_with([query.Field('d')], [1]) f4.assert_called_once_with([query.Field('e')], [2])
def test_with_pass_context(graph_name, sample_count): def root_fields1(fields): return [1 for _ in fields] @pass_context def root_fields2(ctx, fields): return [2 for _ in fields] graph = Graph([ Root([ Field('a', None, root_fields1), Field('b', None, root_fields2), ]), ]) graph = apply(graph, [GraphMetrics(graph_name)]) assert sample_count('Root', 'a') is None assert sample_count('Root', 'b') is None result = Engine(SyncExecutor()).execute( graph, q.Node([ q.Field('a'), q.Field('b'), ])) check_result(result, { 'a': 1, 'b': 2, }) assert sample_count('Root', 'a') == 1.0 assert sample_count('Root', 'b') == 1.0
def test_conflicting_fields(): x_data = {'xN': {'a': 42}} @listify def x_fields(fields, ids): for i in ids: yield ['{}-{}'.format(x_data[i][f.name], f.options['k']) for f in fields] graph = Graph([ Node('X', [ Field('a', None, x_fields, options=[Option('k', Integer)]), ]), Root([ Link('x1', TypeRef['X'], lambda: 'xN', requires=None), Link('x2', TypeRef['X'], lambda: 'xN', requires=None), ]), ]) result = execute(graph, q.Node([ q.Link('x1', q.Node([q.Field('a', options={'k': 1})])), q.Link('x2', q.Node([q.Field('a', options={'k': 2})])), ])) check_result(result, { 'x1': {'a': '42-1'}, 'x2': {'a': '42-2'}, })
async def test_simple_async(graph_name, sample_count): async def x_fields(fields, ids): return [[42 for _ in fields] for _ in ids] async def root_fields(fields): return [1 for _ in fields] async def x_link(): return 2 ll_graph = Graph([ Node('X', [ Field('id', None, x_fields), ]), ]) x_sg = SubGraph(ll_graph, 'X') hl_graph = Graph([ Node('X', [ Field('id', None, x_sg), ]), Root([ Field('a', None, root_fields), Link('x', TypeRef['X'], x_link, requires=None), ]), ]) hl_graph = apply(hl_graph, [AsyncGraphMetrics(graph_name)]) query = q.Node([ q.Field('a'), q.Link('x', q.Node([ q.Field('id'), ])), ]) engine = Engine(AsyncIOExecutor()) assert sample_count('Root', 'a') is None assert sample_count('Root', 'x') is None assert sample_count('X', 'id') is None result = await engine.execute(hl_graph, query) check_result(result, { 'a': 1, 'x': { 'id': 42, }, }) assert sample_count('Root', 'a') == 1.0 assert sample_count('Root', 'x') == 1.0 assert sample_count('X', 'id') == 1.0
def test_process_ordered_node(): ordering = [] def f1(fields): names = tuple(f.name for f in fields) ordering.append(names) return names def f2(fields): return f1(fields) def f3(): ordering.append('x1') return 'x1' @listify def f4(fields, ids): for i in ids: yield ['{}-e'.format(i) for _ in fields] graph = Graph([ Node('X', [ Field('e', None, f4), ]), Root([ Field('a', None, f1), Field('b', None, f1), Field('c', None, f2), Field('d', None, f2), Link('x', TypeRef['X'], f3, requires=None), ]), ]) query = q.Node([ q.Field('d'), q.Field('b'), q.Field('a'), q.Link('x', q.Node([ q.Field('e'), ])), q.Field('c'), ], ordered=True) engine = Engine(SyncExecutor()) result = engine.execute(graph, query) check_result(result, { 'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd', 'x': { 'e': 'x1-e', }, }) assert ordering == [('d',), ('b', 'a'), 'x1', ('c',)]
def test_field(): # field in the root node check_errors(q.Node([q.Field('invalid')]), [ 'Field "invalid" is not implemented in the "root" node', ]) # field in the linked node check_errors(q.Node([q.Link('amyls', q.Node([q.Field('invalid')]))]), [ 'Field "invalid" is not implemented in the "hooted" node', ]) # simple field as node check_errors(q.Node([q.Link('robby', q.Node([]))]), [ 'Trying to query "root.robby" simple field as node', ])
def test_any_in_option(): graph = Graph([ Root([ Field('get', None, None, options=[ Option('foo', Mapping[String, Any]), ]), ]), ]) assert validate(graph, q.Node([ q.Field('get', options={'foo': {u'key': 1}}), ])) == [] assert validate(graph, q.Node([ q.Field('get', options={'foo': 'bar'}), ])) == ['Invalid value for option "root.get:foo", ' '"str" instead of Mapping[String, Any]']
def test_nested_records(): query = q.Node([q.Link('rlyeh', q.Node([ q.Link('cthulhu', q.Node([q.Field('fhtagn')])) ]))]) check_errors(query, []) query = q.Node([q.Link('rlyeh', q.Node([q.Field('cthulhu')]))]) check_errors(query, ['Trying to query "cthulhu" link as it was a field']) query = q.Node([q.Link('rlyeh', q.Node([ q.Link('cthulhu', q.Node([ q.Link('fhtagn', q.Node([q.Field('error')])) ])) ]))]) check_errors(query, ['"fhtagn" is not a link'])
def test_falsy_link_result(): x_fields = Mock(return_value=[[42]]) graph = Graph([ Node('X', [ Field('a', None, x_fields), ]), Root([ Link('x', TypeRef['X'], lambda: 0, requires=None), ]), ]) result = execute(graph, q.Node([ q.Link('x', q.Node([q.Field('a')])), ])) assert denormalize(graph, result) == {'x': {'a': 42}} x_fields.assert_called_once_with([q.Field('a')], [0])
def test_pass_context_link(): f1 = pass_context(Mock(return_value=[1])) f2 = Mock(return_value=[['boners']]) graph = Graph([ Node('a', [ Field('b', None, f2), ]), Root([ Link('c', Sequence[TypeRef['a']], f1, requires=None), ]), ]) result = execute(graph, build([Q.c[Q.b]]), {'fibs': 'dossil'}) check_result(result, {'c': [{'b': 'boners'}]}) assert result.index == {'a': {1: {'b': 'boners'}}} f1.assert_called_once_with(ANY) with reqs_eq_patcher(): f2.assert_called_once_with([query.Field('b')], [1]) ctx = f1.call_args[0][0] assert isinstance(ctx, Context) assert ctx['fibs'] == 'dossil' with pytest.raises(KeyError) as err: _ = ctx['invalid'] # noqa err.match('is not specified in the query context')
def test_root_field_alias(): data = {'a': 42} def root_fields(fields): return [data[f.name] for f in fields] graph = Graph([ Root([ Field('a', None, root_fields), ]), ]) result = execute(graph, q.Node([ q.Field('a', alias='a1'), q.Field('a', alias='a2'), ])) check_result(result, {'a1': 42, 'a2': 42})
def test_root_fields(): f1 = Mock(return_value=['boiardo']) f2 = Mock(return_value=['isolde']) graph = Graph([ Root([ Field('a', None, f1), Field('b', None, f2), ]), ]) result = execute(graph, build([Q.a, Q.b])) check_result(result, {'a': 'boiardo', 'b': 'isolde'}) f1.assert_called_once_with([q.Field('a')]) f2.assert_called_once_with([q.Field('b')])
def test_conflicting_links(): data = { 'yA': {'a': 1, 'b': 2}, 'yB': {'a': 3, 'b': 4}, 'yC': {'a': 5, 'b': 6}, } x2y = {'xN': ['yA', 'yB', 'yC']} @listify def y_fields(fields, ids): for i in ids: yield [data[i][f.name] for f in fields] @listify def x_to_y_link(ids, options): for i in ids: yield [y for y in x2y[i] if y not in options['exclude']] graph = Graph([ Node('Y', [ Field('a', None, y_fields), Field('b', None, y_fields), ]), Node('X', [ Field('id', None, id_field), Link('y', Sequence[TypeRef['Y']], x_to_y_link, requires='id', options=[Option('exclude', None)]), ]), Root([ Link('x1', TypeRef['X'], lambda: 'xN', requires=None), Link('x2', TypeRef['X'], lambda: 'xN', requires=None), ]), ]) result = execute(graph, q.Node([ q.Link('x1', q.Node([ q.Link('y', q.Node([q.Field('a')]), options={'exclude': ['yA']}), ])), q.Link('x2', q.Node([ q.Link('y', q.Node([q.Field('b')]), options={'exclude': ['yC']}), ])), ])) check_result(result, { 'x1': {'y': [{'a': 3}, {'a': 5}]}, 'x2': {'y': [{'b': 2}, {'b': 4}]}, })
def test_typeref_in_option(): data_types = { 'Foo': Record[{ 'key': Integer, }], } graph = Graph([ Root([ Field('get', None, None, options=[Option('foo', TypeRef['Foo'])]), ]), ], data_types=data_types) assert validate(graph, q.Node([ q.Field('get', options={'foo': {'key': 1}}), ])) == [] assert validate(graph, q.Node([ q.Field('get', options={'foo': {'key': '1'}}), ])) == ['Invalid value for option "root.get:foo", "str" instead of Integer']
def test_distinct_by_name_links(): graph = Graph([ Node('X', [ Field('a', None, None), ]), Root([ Link('x1', TypeRef['X'], None, requires=None), Link('x2', TypeRef['X'], None, requires=None), ]), ]) errors = validate(graph, q.Node([ q.Link('x1', q.Node([q.Field('a')])), q.Link('x2', q.Node([q.Field('a')]), alias='x1'), ])) assert errors == [ 'Found distinct fields with the same resulting name "x1" for the ' 'node "root"' ]
def test_distinct_by_options_links(): graph = Graph([ Node('X', [ Field('a', None, None), ]), Root([ Link('x', TypeRef['X'], None, requires=None, options=[Option('e', Optional[Integer], default=None)]), ]), ]) errors = validate(graph, q.Node([ q.Link('x', q.Node([q.Field('a')])), q.Link('x', q.Node([q.Field('a')]), options={'e': 1}), ])) assert errors == [ 'Found distinct fields with the same resulting name "x" for the ' 'node "root"' ]
def test_denormalize_with_alias(): index = Index() index.root.update({ 'x': Reference('X', 'xN'), }) index['X']['xN'].update({ 'a': 1, 'b': 2, }) index.finish() graph = Graph([ Node('X', [ Field('a', None, None), Field('b', None, None), ]), Root([ Link('x', TypeRef['X'], lambda: 'xN', requires=None), ]), ]) query = hiku_query.Node([ hiku_query.Link('x', hiku_query.Node([ hiku_query.Field('a', alias='a1'), ]), alias='x1'), hiku_query.Link('x', hiku_query.Node([ hiku_query.Field('b', alias='b1'), ]), alias='x2'), ]) result = Proxy(index, ROOT, query) assert denormalize(graph, result) == { 'x1': { 'a1': 1 }, 'x2': { 'b1': 2 }, }
def test_root_node_fields(): f1 = Mock(return_value=['khios']) f2 = Mock(return_value=['cambay']) graph = Graph([ Root([ Node('a', [ Field('b', None, f1), Field('c', None, f2), ]), ]), ]) result = execute(graph, build([Q.a[Q.b, Q.c]])) check_result(result, {'a': {'b': 'khios', 'c': 'cambay'}}) with reqs_eq_patcher(): f1.assert_called_once_with([query.Field('b')]) f2.assert_called_once_with([query.Field('c')])
def test_field_option_valid(option, args, result): f = Mock(return_value=['baking']) graph = Graph([ Root([ Field('auslese', None, f, options=[option]), ]), ]) check_result(execute(graph, build([Q.auslese(**args)])), {'auslese': 'baking'}) f.assert_called_once_with([q.Field('auslese', options=result)])
def test_missing_object(): index = Index() index.finish() ref = Reference('SomeNode', 'unknown') proxy = Proxy(index, ref, hiku_query.Node([hiku_query.Field('foo')])) with pytest.raises(AssertionError) as err: proxy.foo err.match(r"Object SomeNode\[u?'unknown'\] is missing in the index")
def test_missing_field(): index = Index() index['SomeNode'][42].update({}) index.finish() ref = Reference('SomeNode', 42) proxy = Proxy(index, ref, hiku_query.Node([hiku_query.Field('foo')])) with pytest.raises(AssertionError) as err: proxy.foo err.match(r"Field SomeNode\[42\]\.foo is missing in the index")
def test_node_fields(): f1 = Mock(return_value=[1]) f2 = Mock(return_value=[['harkis']]) f3 = Mock(return_value=[['slits']]) graph = Graph([ Node('a', [ Field('b', None, f2), Field('c', None, f3), ]), Root([ Link('d', Sequence[TypeRef['a']], f1, requires=None), ]), ]) result = execute(graph, build([Q.d[Q.b, Q.c]])) check_result(result, {'d': [{'b': 'harkis', 'c': 'slits'}]}) f1.assert_called_once_with() f2.assert_called_once_with([q.Field('b')], [1]) f3.assert_called_once_with([q.Field('c')], [1])
def test_non_requested_field_attr(): index = Index() index['SomeNode'][42]['foo'] = 'bar' index.finish() ref = Reference('SomeNode', 42) proxy = Proxy(index, ref, hiku_query.Node([hiku_query.Field('foo')])) assert proxy.foo == 'bar' with pytest.raises(AttributeError) as err: proxy.unknown err.match(r"Field u?'unknown' wasn't requested in the query")
def test_denormalize_non_merged_query(): index = Index() index.root.update({ 'x': Reference('X', 'xN'), }) index['X']['xN'].update({ 'a': 1, 'b': 2, }) index.finish() graph = Graph([ Node('X', [ Field('a', None, None), Field('b', None, None), ]), Root([ Link('x', TypeRef['X'], lambda: 'xN', requires=None), ]), ]) non_merged_query = hiku_query.Node([ hiku_query.Link('x', hiku_query.Node([ hiku_query.Field('a'), ])), hiku_query.Link('x', hiku_query.Node([ hiku_query.Field('b'), ])), ]) with pytest.raises(KeyError) as err: denormalize(graph, Proxy(index, ROOT, non_merged_query)) err.match("Field u?'a' wasn't requested in the query") merged_query = merge([non_merged_query]) assert denormalize(graph, Proxy(index, ROOT, merged_query)) == { 'x': { 'a': 1, 'b': 2 }, }
def test_node_link_alias(): data = { 'yN': {'a': 1, 'b': 2}, } x2y = {'xN': 'yN'} @listify def y_fields(fields, ids): for i in ids: yield [data[i][f.name] for f in fields] graph = Graph([ Node('Y', [ Field('a', None, y_fields), Field('b', None, y_fields), ]), Node('X', [ Field('id', None, id_field), Link('y', TypeRef['Y'], lambda ids: [x2y[i] for i in ids], requires='id'), ]), Root([ Link('x', TypeRef['X'], lambda: 'xN', requires=None), ]), ]) result = execute(graph, q.Node([ q.Link('x', q.Node([ q.Link('y', q.Node([q.Field('a')]), alias='y1'), q.Link('y', q.Node([q.Field('b')]), alias='y2'), ])), ])) check_result(result, { 'x': { 'y1': {'a': 1}, 'y2': {'b': 2}, } })
def test_node_field_alias(): data = {'x1': {'a': 42}} @listify def x_fields(fields, ids): for i in ids: yield [data[i][f.name] for f in fields] graph = Graph([ Node('X', [ Field('a', None, x_fields), ]), Root([ Link('x', TypeRef['X'], lambda: 'x1', requires=None), ]), ]) result = execute(graph, q.Node([ q.Link('x', q.Node([ q.Field('a', alias='a1'), q.Field('a', alias='a2'), ])), ])) check_result(result, {'x': {'a1': 42, 'a2': 42}})