def test_variables_can_be_used_in_schema_query(): Root = g.ObjectType("Root", fields=(g.field("value", g.String), )) graph_definition = g.define_graph(resolvers=()) graph = graph_definition.create_graph({}) query = """ query ($f: Boolean!, $t: Boolean!) { included: __schema @include(if: $t) { queryType { name } } excluded: __schema @include(if: $f) { queryType { name } } } """ variables = {"t": True, "f": False} result = graphql.execute(graph=graph, document_text=query, query_type=Root, variables=variables) assert_that( result, is_success(data=equal_to({ "included": { "queryType": { "name": "Root", }, }, })))
def test_when_resolution_raises_graph_error_then_result_is_invalid(): Root = g.ObjectType("Root", fields=( g.field("value", g.String), )) root_resolver = g.root_object_resolver(Root) @root_resolver.field(Root.fields.value) def root_resolve_value(graph, query, args): raise g.GraphError("BAD") graph_definition = g.define_graph(resolvers=(root_resolver, )) graph = graph_definition.create_graph({}) query = """ query { value } """ result = graphql.execute(graph=graph, document_text=query, query_type=Root) assert_that(result, is_invalid(errors=contains_exactly( all_of( is_instance(GraphQLError), has_str("BAD"), ), )))
def test_can_query_schema_with_other_data(): Root = g.ObjectType("Root", fields=(g.field("value", g.String), )) root_resolver = g.root_object_resolver(Root) @root_resolver.field(Root.fields.value) def root_resolve_value(graph, query, args): return "resolved" graph_definition = g.define_graph(resolvers=(root_resolver, )) graph = graph_definition.create_graph({}) query = """ query { value __schema { queryType { name } } } """ result = graphql.execute(graph=graph, document_text=query, query_type=Root) assert_that( result, is_success(data=equal_to({ "value": "resolved", "__schema": { "queryType": { "name": "Root", }, }, })))
def graphlayer_performance(): import graphlayer as g from graphlayer import graphql User = g.ObjectType("User", fields=( g.field("id", type=g.Int), g.field("name", type=g.String), )) Query = g.ObjectType("Query", fields=(g.field("users", type=g.ListType(User)), )) root_resolver = g.root_object_resolver(Query) @root_resolver.field(Query.fields.users) def root_resolve_users(graph, query, args): return graph.resolve(query) @g.resolver(g.ListType(User)) def resolve_users(graph, query): return [ query.element_query.create_object( dict((field_query.key, getattr(user, field_query.field.name)) for field_query in query.element_query.fields)) for user in users ] resolvers = (root_resolver, resolve_users) graph_definition = g.define_graph(resolvers=resolvers) graph = graph_definition.create_graph({}) return lambda document_text: graphql.execute( graph=graph, document_text=document_text, query_type=Query)
def test_typename(): Root = g.ObjectType("Root", fields=(g.field("value", g.String), )) root_resolver = g.root_object_resolver(Root) @root_resolver.field(Root.fields.value) def root_resolve_value(graph, query, args): return "resolved" graph_definition = g.define_graph(resolvers=(root_resolver, )) graph = graph_definition.create_graph({}) query = """ query { __typename value typename: __typename } """ result = graphql.execute(graph=graph, document_text=query, query_type=Root) assert_that( result, is_success(data=equal_to({ "__typename": "Root", "value": "resolved", "typename": "Root" })))
def test_can_query_schema(): Root = g.ObjectType("Root", fields=(g.field("value", g.String), )) graph_definition = g.define_graph(resolvers=()) graph = graph_definition.create_graph({}) query = """ query { __schema { queryType { name } } } """ result = graphql.execute(graph=graph, document_text=query, query_type=Root) assert_that( result, is_success(data=equal_to({ "__schema": { "queryType": { "name": "Root", }, }, })))
def test_can_get_fields_backed_by_expressions(): Base = sqlalchemy.ext.declarative.declarative_base() class BookRow(Base): __tablename__ = "book" c_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_title = sqlalchemy.Column(sqlalchemy.Unicode, nullable=False) engine = sqlalchemy.create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = sqlalchemy.orm.Session(engine) session.add(BookRow(c_title="Leave it to Psmith")) session.add(BookRow(c_title="Pericles, Prince of Tyre")) session.commit() Book = g.ObjectType( "Book", fields=lambda: [ g.field("title", type=g.String), ], ) book_resolver = gsql.sql_table_resolver( Book, BookRow, fields={ Book.fields.title: gsql.expression(BookRow.c_title), }, ) resolvers = [book_resolver] query = gsql.select( g.ListType(Book)(g.key("title", Book.fields.title()), )) graph_definition = g.define_graph(resolvers) graph = graph_definition.create_graph({ sqlalchemy.orm.Session: session, }) result = graph.resolve(query) assert_that( result, contains_exactly( has_attrs(title="Leave it to Psmith", ), has_attrs(title="Pericles, Prince of Tyre", ), ))
def test_can_pass_arguments_to_expression(): Base = sqlalchemy.ext.declarative.declarative_base() class BookRow(Base): __tablename__ = "book" c_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_title = sqlalchemy.Column(sqlalchemy.Unicode, nullable=False) engine = sqlalchemy.create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = sqlalchemy.orm.Session(engine) session.add(BookRow(c_title="Leave it to Psmith")) session.commit() Book = g.ObjectType( "Book", fields=lambda: [ g.field( "title", type=g.String, params=[ g.param("truncate", g.Int), ]), ], ) book_resolver = gsql.sql_table_resolver( Book, BookRow, fields={ Book.fields.title: lambda args: gsql.expression( sqlalchemy.func.substr(BookRow.c_title, 1, args.truncate)), }, ) resolvers = [book_resolver] query = gsql.select( g.ListType(Book)(g.key( "title", Book.fields.title(Book.fields.title.params.truncate(8))), )) graph_definition = g.define_graph(resolvers) graph = graph_definition.create_graph({sqlalchemy.orm.Session: session}) result = graph.resolve(query) assert_that(result, contains_exactly(has_attrs(title="Leave it", ), ))
def test_query_is_validated(): Root = g.ObjectType("Root", fields=( g.field("value", g.String), )) graph_definition = g.define_graph(resolvers=()) graph = graph_definition.create_graph({}) query = """ { x } """ error = pytest.raises(GraphQLError, lambda: graphql.execute(graph=graph, document_text=query, query_type=Root)) assert_that(str(error.value), equal_to(('Cannot query field "x" on type "Root".')))
def test_root_object_resolver_can_resolve_fields_with_dependencies(self): Root = g.ObjectType("Root", fields=(g.field("value", type=g.Int), )) resolve_root = g.root_object_resolver(Root) value_key = object() @resolve_root.field(Root.fields.value) @g.dependencies(value=value_key) def root_resolve_value(graph, query, args, *, value): return value graph_definition = g.define_graph(resolvers=(resolve_root, )) graph = graph_definition.create_graph({value_key: 42}) query = Root(g.key("value", Root.fields.value()), ) assert_that(graph.resolve(query), has_attrs(value=42))
def test_when_query_is_invalid_then_result_is_invalid(): Root = g.ObjectType("Root", fields=(g.field("value", g.String), )) graph_definition = g.define_graph(resolvers=()) graph = graph_definition.create_graph({}) query = """ query { bad } """ result = graphql.execute(graph=graph, document_text=query, query_type=Root) assert_that( result, is_invalid(errors=contains_exactly( has_attrs(message="Cannot query field 'bad' on type 'Root'."), )))
def test_root_object_resolver_passes_arguments_to_field_resolvers(self): Root = g.ObjectType("Root", fields=(g.field("value", type=g.Int, params=(g.param("answer", type=g.Int), )), )) resolve_root = g.root_object_resolver(Root) @resolve_root.field(Root.fields.value) def root_resolve_value(graph, query, args): return args.answer graph_definition = g.define_graph(resolvers=(resolve_root, )) graph = graph_definition.create_graph({}) query = Root( g.key("value", Root.fields.value(Root.fields.value.params.answer(42))), ) assert_that(graph.resolve(query), has_attrs(value=42))
import graphlayer as g import sqlalchemy.orm from . import authors, books, root resolvers = ( authors.resolvers, books.resolvers, root.resolvers, ) _graph_definition = g.define_graph(resolvers=resolvers) def create_graph(*, session): return _graph_definition.create_graph({ sqlalchemy.orm.Session: session, }) Root = root.Root
def test_can_join_tables_using_multi_column_key(): Base = sqlalchemy.ext.declarative.declarative_base() class LeftRow(Base): __tablename__ = "left" c_id_1 = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_id_2 = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_value = sqlalchemy.Column(sqlalchemy.Unicode) class RightRow(Base): __tablename__ = "right" c_id_1 = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_id_2 = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_value = sqlalchemy.Column(sqlalchemy.Unicode) engine = sqlalchemy.create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = sqlalchemy.orm.Session(engine) session.add(LeftRow(c_id_1=1, c_id_2=2, c_value="one")) session.add(RightRow(c_id_1=1, c_id_2=2, c_value="two")) session.add(LeftRow(c_id_1=1, c_id_2=3, c_value="three")) session.add(RightRow(c_id_1=1, c_id_2=3, c_value="four")) session.commit() Left = g.ObjectType( "Left", fields=lambda: [ g.field("value", type=g.String), g.field("right", type=Right), ], ) Right = g.ObjectType( "Right", fields=lambda: [ g.field("value", type=g.String), ], ) left_resolver = gsql.sql_table_resolver( Left, LeftRow, fields={ Left.fields.value: gsql.expression(LeftRow.c_value), Left.fields.right: g.single( gsql.sql_join({ LeftRow.c_id_1: RightRow.c_id_1, LeftRow.c_id_2: RightRow.c_id_2, })), }, ) right_resolver = gsql.sql_table_resolver( Right, RightRow, fields={ Right.fields.value: gsql.expression(RightRow.c_value), }, ) resolvers = [left_resolver, right_resolver] query = gsql.select( g.ListType(Left)( g.key("value", Left.fields.value()), g.key("right", Left.fields.right(g.key("value", Right.fields.value()), )), )) graph_definition = g.define_graph(resolvers) graph = graph_definition.create_graph({sqlalchemy.orm.Session: session}) result = graph.resolve(query) assert_that( result, contains_exactly( has_attrs( value="one", right=has_attrs(value="two", ), ), has_attrs( value="three", right=has_attrs(value="four", ), ), ))
def test_can_resolve_join_through_association_table(): Base = sqlalchemy.ext.declarative.declarative_base() class LeftRow(Base): __tablename__ = "left" c_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_value = sqlalchemy.Column(sqlalchemy.Unicode) class AssociationRow(Base): __tablename__ = "association" c_left_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_right_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) class RightRow(Base): __tablename__ = "right" c_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_value = sqlalchemy.Column(sqlalchemy.Unicode) engine = sqlalchemy.create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = sqlalchemy.orm.Session(engine) session.add(LeftRow(c_id=1, c_value="left 1")) session.add(RightRow(c_id=101, c_value="right 1a")) session.add(RightRow(c_id=102, c_value="right 1b")) session.add(AssociationRow(c_left_id=1, c_right_id=101)) session.add(AssociationRow(c_left_id=1, c_right_id=102)) session.add(LeftRow(c_id=2, c_value="left 2")) session.add(LeftRow(c_id=3, c_value="left 3")) session.add(RightRow(c_id=103, c_value="right 3")) session.add(AssociationRow(c_left_id=3, c_right_id=103)) session.commit() Left = g.ObjectType( "Left", fields=lambda: [ g.field("value", type=g.String), g.field("rights", type=g.ListType(Right)), ], ) Right = g.ObjectType( "Right", fields=lambda: [ g.field("value", type=g.String), ], ) left_resolver = gsql.sql_table_resolver( Left, LeftRow, fields={ Left.fields.value: gsql.expression(LeftRow.c_value), Left.fields.rights: g.many( gsql.sql_join( {LeftRow.c_id: AssociationRow.c_left_id}, AssociationRow, {AssociationRow.c_right_id: RightRow.c_id}, )), }, ) right_resolver = gsql.sql_table_resolver( Right, RightRow, fields={ Right.fields.value: gsql.expression(RightRow.c_value), }, ) resolvers = [left_resolver, right_resolver] query = gsql.select( g.ListType(Left)( g.key("value", Left.fields.value()), g.key("rights", Left.fields.rights(g.key("value", Right.fields.value()), )), )) graph_definition = g.define_graph(resolvers) graph = graph_definition.create_graph({sqlalchemy.orm.Session: session}) result = graph.resolve(query) assert_that( result, contains_exactly( has_attrs( value="left 1", rights=contains_exactly( has_attrs(value="right 1a"), has_attrs(value="right 1b"), ), ), has_attrs( value="left 2", rights=contains_exactly(), ), has_attrs( value="left 3", rights=contains_exactly(has_attrs(value="right 3"), ), ), ))
def test_can_recursively_resolve_selected_fields(): Base = sqlalchemy.ext.declarative.declarative_base() class AuthorRow(Base): __tablename__ = "author" c_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_name = sqlalchemy.Column(sqlalchemy.Unicode, nullable=False) class BookRow(Base): __tablename__ = "book" c_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_title = sqlalchemy.Column(sqlalchemy.Unicode, nullable=False) c_author_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey(AuthorRow.c_id)) engine = sqlalchemy.create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = sqlalchemy.orm.Session(engine) session.add(AuthorRow(c_id=1, c_name="PG Wodehouse")) session.add(AuthorRow(c_id=2, c_name="William Shakespeare")) session.add(BookRow(c_title="Leave it to Psmith", c_author_id=1)) session.add(BookRow(c_title="Pericles, Prince of Tyre", c_author_id=2)) session.commit() Root = g.ObjectType( "Root", fields=lambda: [ g.field("books", type=g.ListType(Book)), ], ) Book = g.ObjectType( "Book", fields=lambda: [ g.field("author", type=Author), g.field("title", type=g.String), ], ) Author = g.ObjectType( "Author", fields=lambda: [ g.field("name", type=g.String), ], ) resolve_root = root_object_resolver(Root) @resolve_root.field(Root.fields.books) def resolve_root_field_books(graph, query, args): return graph.resolve(gsql.select(query)) book_resolver = gsql.sql_table_resolver( Book, BookRow, fields={ Book.fields.title: gsql.expression(BookRow.c_title), Book.fields.author: g.single(gsql.sql_join({ BookRow.c_author_id: AuthorRow.c_id, })), }, ) author_resolver = gsql.sql_table_resolver( Author, AuthorRow, fields={ Author.fields.name: gsql.expression(AuthorRow.c_name), }, ) resolvers = [resolve_root, book_resolver, author_resolver] query = Root( g.key( "books", Root.fields.books( g.key( "author", Book.fields.author(g.key("name", Author.fields.name()), )), g.key("title", Book.fields.title()), )), ) graph_definition = g.define_graph(resolvers) graph = graph_definition.create_graph({sqlalchemy.orm.Session: session}) result = graph.resolve(query) assert_that( result, has_attrs(books=contains_exactly( has_attrs( author=has_attrs(name="PG Wodehouse"), title="Leave it to Psmith", ), has_attrs( author=has_attrs(name="William Shakespeare"), title="Pericles, Prince of Tyre", ), ), ))
def test_can_pass_arguments_from_root(): Base = sqlalchemy.ext.declarative.declarative_base() class BookRow(Base): __tablename__ = "book" c_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_title = sqlalchemy.Column(sqlalchemy.Unicode, nullable=False) engine = sqlalchemy.create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = sqlalchemy.orm.Session(engine) session.add(BookRow(c_id=1, c_title="Leave it to Psmith")) session.add(BookRow(c_id=2, c_title="Pericles, Prince of Tyre")) session.commit() Root = g.ObjectType( "Root", fields=lambda: [ g.field("books", type=g.ListType(Book), params=[ g.param("id", g.Int), ]), ], ) Book = g.ObjectType( "Book", fields=lambda: [ g.field("title", type=g.String), ], ) resolve_root = root_object_resolver(Root) @resolve_root.field(Root.fields.books) def root_books_args(graph, query, args): return graph.resolve( BookQuery.select(query).where(BookQuery.id(args.id))) book_resolver = gsql.sql_table_resolver( Book, BookRow, fields={ Book.fields.title: gsql.expression(BookRow.c_title), }, ) class BookQuery(object): select = gsql.select @staticmethod def id(id): return BookRow.c_id == id resolvers = [resolve_root, book_resolver] query = Root( g.key( "books", Root.fields.books( Root.fields.books.params.id(1), g.key("title", Book.fields.title()), )), ) graph_definition = g.define_graph(resolvers) graph = graph_definition.create_graph({sqlalchemy.orm.Session: session}) result = graph.resolve(query) assert_that( result, has_attrs(books=contains_exactly( has_attrs(title="Leave it to Psmith", ), ), ))
def test_can_select_unions(): Person = g.InterfaceType( "Person", fields=lambda: (g.field("name", type=g.String), ), ) Author = g.ObjectType( "Author", fields=lambda: ( g.field("name", type=g.String), g.field("books_written", type=g.Int), ), interfaces=lambda: (Person, ), ) Reader = g.ObjectType( "Reader", fields=lambda: ( g.field("name", type=g.String), g.field("books_read", type=g.Int), ), interfaces=lambda: (Person, ), ) @g.resolver(g.ListType(Author)) def resolve_author(graph, query): assert_that( query, is_query( g.ListType(Author)( g.key("name", Author.fields.name()), g.key("books_written", Author.fields.books_written()), ))) return [ g.Object(dict(name="<author 1>", books_written=1)), g.Object(dict(name="<author 2>", books_written=2)), ] @g.resolver(g.ListType(Reader)) def resolve_reader(graph, query): assert_that( query, is_query( g.ListType(Reader)( g.key("name", Reader.fields.name()), g.key("books_read", Reader.fields.books_read()), ))) return [ g.Object(dict(name="<reader 3>", books_read=3)), g.Object(dict(name="<reader 4>", books_read=4)), ] resolvers = ( unions.resolver, resolve_author, resolve_reader, ) graph_definition = g.define_graph(resolvers) graph = graph_definition.create_graph({}) query = unions.select( g.ListType(Person)( g.key("name", Person.fields.name()), g.key("books_read", Reader.fields.books_read()), g.key("books_written", Author.fields.books_written()), ), ( # TODO: Make sure select is called (Author, lambda author_query: author_query), (Reader, lambda reader_query: reader_query), ), merge=flatten, ) result = graph.resolve(query) assert_that( result, contains_exactly( has_attrs(name="<author 1>", books_written=1), has_attrs(name="<author 2>", books_written=2), has_attrs(name="<reader 3>", books_read=3), has_attrs(name="<reader 4>", books_read=4), ))