def testSubQuery(self): thread_pool = ThreadPoolExecutor(2) e = Engine(ThreadsExecutor(thread_pool)) def query_a(fields, ids): data = {1: {'f': 2}} return [[data[i][f] for f in fields] for i in ids] r = graph.Edge(None, [ graph.Edge('a', [ graph.Field('f', query_a), ]), ]) # ---------------------------------------------- @define('[[:f]]', _name='inc_f') def inc_f(obj): return obj['f'] + 1 r1 = graph.Edge(None, [ graph.Edge('a1', subquery_fields(r, 'a', { 'f1': inc_f(S.this), })), graph.Link('la1', None, 'a1', lambda: [1], True), ]) self.assertEqual(e.execute(r1, read('[{:la1 [:f1]}]'))['la1'], [{'f1': 3}])
def testSubQuery(self): thread_pool = ThreadPoolExecutor(2) e = Engine(ThreadsExecutor(thread_pool)) def query_a(fields, ids): data = {1: {'f': 2}} return [[data[i][f] for f in fields] for i in ids] r = graph.Edge(None, [ graph.Edge('a', [ graph.Field('f', query_a), ]), ]) # ---------------------------------------------- @define('[[:f]]', _name='inc_f') def inc_f(obj): return obj['f'] + 1 r1 = graph.Edge(None, [ graph.Edge('a1', subquery_fields(r, 'a', { 'f1': inc_f(S.this), })), graph.Link('la1', None, 'a1', lambda: [1], True), ]) self.assertEqual( e.execute(r1, read('[{:la1 [:f1]}]'))['la1'], [{ 'f1': 3 }])
def setUp(self): sa_engine = create_engine( 'sqlite://', connect_args={'check_same_thread': False}, poolclass=StaticPool, ) metadata.create_all(sa_engine) session.configure(bind=sa_engine) def bar_insert(r): return sa_engine.execute(bar_table.insert(), r).lastrowid self.bar_ids = list(map(bar_insert, [ {'name': 'bar1', 'type': 1}, {'name': 'bar2', 'type': 2}, {'name': 'bar3', 'type': 3}, ])) def foo_insert(r): return sa_engine.execute(foo_table.insert(), r).lastrowid list(map(foo_insert, [ {'name': 'foo1', 'count': 5, 'bar_id': self.bar_ids[0]}, {'name': 'foo2', 'count': 10, 'bar_id': self.bar_ids[1]}, {'name': 'foo3', 'count': 15, 'bar_id': self.bar_ids[2]}, ])) self.engine = Engine(ThreadsExecutor(thread_pool))
def test_complex_field(): engine = Engine(SyncExecutor()) def get_a(fields, ids): return [[{'s': 'bar'} for _ in fields] for _ in ids] ll_graph = Graph([ Node('Foo', [ Field('a', Record[{ 's': String }], get_a), ]), ]) foo_sg = SubGraph(ll_graph, 'Foo') hl_graph = Graph([ Node('Foo', [ Field('a', Record[{ 's': String }], foo_sg), ]), Root([ Link('foo', TypeRef['Foo'], lambda: 1, requires=None), ]), ]) result = engine.execute(hl_graph, build([Q.foo[Q.a[Q.s]]])) check_result(result, {'foo': {'a': {'s': 'bar'}}})
def _check(self, src, value, event_loop): sa_engine = yield from aiopg.sa.create_engine(self.db_dsn, minsize=0, loop=event_loop) try: engine = Engine(AsyncIOExecutor(event_loop)) result = yield from engine.execute(self.graph, read(src), {SA_ENGINE_KEY: sa_engine}) check_result(result, value) finally: sa_engine.close() yield from sa_engine.wait_closed()
def introspect(graph): engine = Engine(SyncExecutor()) graph = apply(graph, [GraphQLIntrospection()]) query = read(QUERY) errors = validate(graph, query) assert not errors norm_result = engine.execute(graph, query) return denormalize(graph, norm_result, query)
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 check(self, src, value): sa_engine = create_engine( 'sqlite://', connect_args={'check_same_thread': False}, poolclass=StaticPool, ) setup_db(sa_engine) engine = Engine(ThreadsExecutor(thread_pool)) result = engine.execute(self.graph, read(src), {SA_ENGINE_KEY: sa_engine}) check_result(result, value)
def introspect(query_graph, mutation_graph=None): engine = Engine(SyncExecutor()) query_graph = apply(query_graph, [ GraphQLIntrospection(query_graph, mutation_graph), ]) query = read(QUERY) errors = validate(query_graph, query) assert not errors norm_result = engine.execute(query_graph, query) return denormalize(query_graph, norm_result)
async def test_async_batch_endpoint(async_graph): endpoint = AsyncBatchGraphQLEndpoint(Engine(AsyncIOExecutor()), async_graph) assert await endpoint.dispatch([]) == [] result = await endpoint.dispatch({'query': '{answer}'}) assert result == {'data': {'answer': '42'}} batch_result = await endpoint.dispatch([ { 'query': '{answer}' }, { 'query': '{__typename}' }, ]) assert batch_result == [ { 'data': { 'answer': '42' } }, { 'data': { '__typename': 'Query' } }, ]
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
class TestSourceGraph(TestCase): def setUp(self): self.engine = Engine(ThreadsExecutor(ThreadPoolExecutor(2))) def testField(self): result = self.engine.execute(HIGH_ENV, read("[{:xs1 [:a]}]")) self.assertResult(result, {"xs1": [{"a": "a1"}, {"a": "a2"}, {"a": "a3"}]})
def test_batch_endpoint(sync_graph): endpoint = BatchGraphQLEndpoint(Engine(SyncExecutor()), sync_graph) assert endpoint.dispatch([]) == [] result = endpoint.dispatch({'query': '{answer}'}) assert result == {'data': {'answer': '42'}} batch_result = endpoint.dispatch([ { 'query': '{answer}' }, { 'query': '{__typename}' }, ]) assert batch_result == [ { 'data': { 'answer': '42' } }, { 'data': { '__typename': 'Query' } }, ]
class TestSourceGraph(TestCase): def setUp(self): self.engine = Engine(ThreadsExecutor(ThreadPoolExecutor(2))) def testField(self): result = self.engine.execute(GRAPH, read('[{:x1s [:a :f]}]')) self.assertResult(result, {'x1s': [ {'a': 'a1', 'f': 7}, {'a': 'a3', 'f': 7}, {'a': 'a2', 'f': 7}, ]}) def testFieldOptions(self): result = self.engine.execute(GRAPH, read('[{:x1s [(:buz {:size "100"})]}]')) self.assertResult(result, {'x1s': [ {'buz': 'a1 - 100'}, {'buz': 'a3 - 100'}, {'buz': 'a2 - 100'}, ]}) def testFieldWithoutOptions(self): result = self.engine.execute(GRAPH, read('[{:x1s [:buz]}]')) self.assertResult(result, {'x1s': [ {'buz': 'a1 - None'}, {'buz': 'a3 - None'}, {'buz': 'a2 - None'}, ]}) def testFieldOptionDefaults(self): result = self.engine.execute(GRAPH, read('[{:x1s [:buz2]}]')) self.assertResult(result, {'x1s': [ {'buz2': 'a1 - 100'}, {'buz2': 'a3 - 100'}, {'buz2': 'a2 - 100'}, ]}) result = self.engine.execute(GRAPH, read('[{:x1s [(:buz2 {:size 200})]}]')) self.assertResult(result, {'x1s': [ {'buz2': 'a1 - 200'}, {'buz2': 'a3 - 200'}, {'buz2': 'a2 - 200'}, ]}) def testSequenceInArgType(self): result = self.engine.execute(GRAPH, read('[{:x1s [:baz]}]')) self.assertResult(result, {'x1s': [ {'baz': 'D3 [B1]'}, {'baz': 'D1 [B3]'}, {'baz': 'D2 [B2]'}, ]}) result = self.engine.execute(GRAPH, read('[{:y1s [:baz]}]')) self.assertResult(result, {'y1s': [ {'baz': 'D3 [B1]'}, {'baz': 'D1 [B3]'}, {'baz': 'D2 [B2]'}, ]})
async def _check(self, src, value): sa_engine = create_async_engine(self.db_dsn) engine = Engine(AsyncIOExecutor()) try: result = await engine.execute(self.graph, read(src), {SA_ENGINE_KEY: sa_engine}) check_result(result, value) finally: await greenlet_spawn(sa_engine.sync_engine.dispose)
async def _check(self, src, value): sa_engine = await aiopg.sa.create_engine(self.db_dsn, minsize=0) engine = Engine(AsyncIOExecutor()) try: result = await engine.execute(self.graph, read(src), {SA_ENGINE_KEY: sa_engine}) check_result(result, value) finally: sa_engine.close() await sa_engine.wait_closed()
def main(): logging.basicConfig() app = web.Application() app.add_routes([ web.post('/graphql', handle_graphql), ]) app['graphql-endpoint'] = AsyncGraphQLEndpoint( Engine(AsyncIOExecutor()), QUERY_GRAPH, MUTATION_GRAPH, ) web.run_app(app)
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
class TestEngine(TestCase): def setUp(self): self.engine = Engine(ThreadsExecutor(thread_pool)) def execute(self, query): return self.engine.execute(TEST_ENV, read(query)) def testFields(self): with _patch(query_fields1) as qf1, _patch(query_fields2) as qf2: qf1.return_value = ['a1'] qf2.return_value = ['b1'] self.assertResult(self.execute('[:a :b]'), {'a': 'a1', 'b': 'b1'}) qf1.assert_called_once_with(['a']) qf2.assert_called_once_with(['b']) def testEdgeFields(self): with _patch(query_fields1) as qf1, _patch(query_fields2) as qf2: qf1.return_value = ['d1'] qf2.return_value = ['e1'] self.assertResult(self.execute('[{:c [:d :e]}]'), {'c': {'d': 'd1', 'e': 'e1'}}) qf1.assert_called_once_with(['d']) qf2.assert_called_once_with(['e']) def testLinkFields(self): with _patch(query_fields1) as qf1, _patch(query_fields2) as qf2,\ _patch(query_link1) as ql1: ql1.return_value = [1] qf1.return_value = [['d1']] qf2.return_value = [['e1']] result = self.execute('[{:f [:d :e]}]') self.assertResult(result, {'f': [{'d': 'd1', 'e': 'e1'}]}) self.assertEqual(result.idx, {'c': {1: {'d': 'd1', 'e': 'e1'}}}) ql1.assert_called_once_with() qf1.assert_called_once_with(['d'], [1]) qf2.assert_called_once_with(['e'], [1]) def testLinks(self): with _patch(query_fields1) as qf1, _patch(query_fields2) as qf2,\ _patch(query_link1) as ql1, _patch(query_link2) as ql2: ql1.return_value = [1] qf1.return_value = [['d1']] ql2.return_value = [2] qf2.return_value = [['e1']] result = self.execute('[{:f [:d]} {:g [:e]}]') self.assertResult(result, {'f': [{'d': 'd1'}], 'g': [{'e': 'e1'}]}) self.assertEqual(result.idx, {'c': {1: {'d': 'd1'}, 2: {'e': 'e1'}}}) ql1.assert_called_once_with() qf1.assert_called_once_with(['d'], [1]) ql2.assert_called_once_with() qf2.assert_called_once_with(['e'], [2])
class TestSourceGraph(TestCase): def setUp(self): self.engine = Engine(ThreadsExecutor(ThreadPoolExecutor(2))) def testField(self): result = self.engine.execute(HIGH_ENV, read('[{:xs1 [:a]}]')) self.assertResult(result, {'xs1': [ {'a': 'a1'}, {'a': 'a2'}, {'a': 'a3'}, ]})
def test(): for query in [query_graphql(), query_simple(), query_python()]: hiku_engine = Engine(SyncExecutor()) result = hiku_engine.execute(GRAPH, query) result = denormalize(GRAPH, result, query) assert result == \ { "characters": [ { "name": "James T. Kirk", "species": "Human" }, { "name": "Spock", "species": "Vulcan/Human" }, { "name": "Leonard McCoy", "species": "Human" } ] }
async def test_async_introspection(event_loop): from hiku.executors.asyncio import AsyncIOExecutor from hiku.introspection.graphql import MakeAsync graph = MakeAsync().visit(GRAPH) async_hiku_engine = Engine(AsyncIOExecutor(event_loop)) from hiku.graph import apply from hiku.introspection.graphql import AsyncGraphQLIntrospection graph = apply(graph, [AsyncGraphQLIntrospection()]) query = read('{ __typename }') result = await async_hiku_engine.execute(graph, query) simple_result = denormalize(graph, result, query) assert simple_result == {'__typename': 'Root'}
async def test_actor_to_character(db_dsn, event_loop): hiku_engine = Engine(AsyncIOExecutor(event_loop)) async with aiopg.sa.create_engine(db_dsn, loop=event_loop) as sa_engine: result = await execute(hiku_engine, sa_engine, GRAPH, '[{:actors [:name {:character [:name]}]}]') assert result == { 'actors': [ { 'name': 'William Shatner', 'character': { 'name': 'James T. Kirk' }, }, { 'name': 'Leonard Nimoy', 'character': { 'name': 'Spock' }, }, { 'name': 'DeForest Kelley', 'character': { 'name': 'Leonard McCoy' }, }, { 'name': 'Chris Pine', 'character': { 'name': 'James T. Kirk' }, }, { 'name': 'Zachary Quinto', 'character': { 'name': 'Spock' }, }, { 'name': 'Karl Urban', 'character': { 'name': 'Leonard McCoy' }, }, ], }
data_types=DATA_TYPES) MUTATION_GRAPH = Graph(QUERY_GRAPH.nodes + [ Root([ Field('action', Boolean, action_func, options=[Option('data', TypeRef['Data'])]), ]), ], data_types=DATA_TYPES) app = Flask(__name__) graphql_endpoint = GraphQLEndpoint( Engine(SyncExecutor()), QUERY_GRAPH, MUTATION_GRAPH, ) @app.route('/graphql', methods={'POST'}) def handle_graphql(): data = request.get_json() result = graphql_endpoint.dispatch(data) return jsonify(result) def main(): logging.basicConfig() app.run(port=5000)
def _engine(): return Engine(ThreadsExecutor(ThreadPoolExecutor(2)))
GRAPH = Graph([ Root([ Field('foo', String, foo_field_func), ]), ]) async def handler(request): hiku_engine = request.app['HIKU_ENGINE'] data = await request.json() try: query = read(data['query'], data.get('variables')) errors = validate(request.app['GRAPH'], query) if errors: result = {'errors': [{'message': e} for e in errors]} else: result = await hiku_engine.execute(request.app['GRAPH'], query) result = {'data': denormalize(request.app['GRAPH'], result, query)} except Exception as err: result = {'errors': [{'message': repr(err)}]} return web.json_response(result) if __name__ == "__main__": app = web.Application() app.router.add_post('/', handler) app['HIKU_ENGINE'] = Engine(AsyncIOExecutor(asyncio.get_event_loop())) app['GRAPH'] = apply(GRAPH, [AsyncGraphQLIntrospection()]) web.run_app(app)
def setUp(self): self.engine = Engine(ThreadsExecutor(ThreadPoolExecutor(2)))
class TestSourceSQL(TestCase): def setUp(self): sa_engine = create_engine( 'sqlite://', connect_args={'check_same_thread': False}, poolclass=StaticPool, ) metadata.create_all(sa_engine) session.configure(bind=sa_engine) def bar_insert(r): return sa_engine.execute(bar_table.insert(), r).lastrowid self.bar_ids = list(map(bar_insert, [ {'name': 'bar1', 'type': 1}, {'name': 'bar2', 'type': 2}, {'name': 'bar3', 'type': 3}, ])) def foo_insert(r): return sa_engine.execute(foo_table.insert(), r).lastrowid list(map(foo_insert, [ {'name': 'foo1', 'count': 5, 'bar_id': self.bar_ids[0]}, {'name': 'foo2', 'count': 10, 'bar_id': self.bar_ids[1]}, {'name': 'foo3', 'count': 15, 'bar_id': self.bar_ids[2]}, ])) self.engine = Engine(ThreadsExecutor(thread_pool)) def tearDown(self): session.remove() def assertExecute(self, src, result): result = self.engine.execute(ENV, read(src)) self.assertResult(result, result) def testManyToOne(self): self.assertExecute( '[{:foo-list [:name :count {:bar [:name :type]}]}]', {'foo-list': [ {'name': 'foo3', 'count': 15, 'bar_id': 3, 'bar': {'name': 'bar3', 'type': 3}}, {'name': 'foo2', 'count': 10, 'bar_id': 2, 'bar': {'name': 'bar2', 'type': 2}}, {'name': 'foo1', 'count': 5, 'bar_id': 1, 'bar': {'name': 'bar1', 'type': 1}}, ]} ) def testOneToMany(self): self.assertExecute( '[{:bar-list [:name :type {:foo-s [:name :count]}]}]', {'bar-list': [ {'id': 3, 'name': 'bar3', 'type': 3, 'foo-s': [ {'name': 'foo3', 'count': 15}, ]}, {'id': 2, 'name': 'bar2', 'type': 2, 'foo-s': [ {'name': 'foo2', 'count': 10}, ]}, {'id': 1, 'name': 'bar1', 'type': 1, 'foo-s': [ {'name': 'foo1', 'count': 5}, ]}, ]}, ) def testNotFound(self): self.assertExecute( '[{:not-found-one [:name :type]}' ' {:not-found-list [:name :type]}]', { 'not-found-one': {'name': None, 'type': None}, 'not-found-list': [ {'name': 'bar3', 'type': 3}, {'name': None, 'type': None}, {'name': 'bar1', 'type': 1}, ], }, )
try: query = read(data['query'], data.get('variables')) errors = validate(app.config['GRAPH'], query) if errors: result = {'errors': [{'message': e} for e in errors]} else: result = hiku_engine.execute(app.config['GRAPH'], query, ctx=app.config['HIKU_CTX']) result = {'data': denormalize(app.config['GRAPH'], result, query)} except Exception as err: result = {'errors': [{'message': repr(err)}]} return jsonify(result) if __name__ == "__main__": sa_engine = create_engine('sqlite://', connect_args={'check_same_thread': False}, poolclass=StaticPool) setup_db(sa_engine) app.config['HIKU_ENGINE'] = Engine(SyncExecutor()) app.config['HIKU_CTX'] = {SA_ENGINE_KEY: sa_engine} graph = get_graph(get_queries(hiku.sources.sqlalchemy, SA_ENGINE_KEY, SyncQueries)) graph = apply(graph, [GraphQLIntrospection()]) app.config['GRAPH'] = graph app.run()
def test_endpoint(sync_graph): endpoint = GraphQLEndpoint(Engine(SyncExecutor()), sync_graph) result = endpoint.dispatch({'query': '{answer}'}) assert result == {'data': {'answer': '42'}}
def setUp(self): self.engine = Engine(ThreadsExecutor(thread_pool))
async def test_async_endpoint(async_graph): endpoint = AsyncGraphQLEndpoint(Engine(AsyncIOExecutor()), async_graph) result = await endpoint.dispatch({'query': '{answer}'}) assert result == {'data': {'answer': '42'}}
def execute(graph, query_, ctx=None): engine = Engine(SyncExecutor()) return engine.execute(graph, query_, ctx=ctx)
GRAPH = Graph([ Node('Character', [ Field('name', None, character_data), Field('species', None, character_data), ]), Root([ Link('characters', Sequence[TypeRef['Character']], to_characters_link, requires=None), ]), ]) # test hiku_engine = Engine(SyncExecutor()) def execute(graph, query_string): query = read(query_string) result = hiku_engine.execute(graph, query) return denormalize(graph, result) def test(): result = execute(GRAPH, '[{:characters [:name :species]}]') assert result == { "characters": [ { "species": "Human", "name": "James T. Kirk",
def execute(query_, ctx=None): engine = Engine(ThreadsExecutor(thread_pool)) return engine.execute(get_graph(), read(query_), ctx=ctx)