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_can_recursively_resolve(): Root = g.ObjectType( "Root", fields=lambda: [ g.field("books", type=g.ListType(Book)), ], ) Book = g.ObjectType( "Book", fields=lambda: [ g.field("title", type=g.String), ], ) @g.resolver(Root) def resolve_root(graph, query): return query.create_object(iterables.to_dict( (field_query.key, graph.resolve(field_query.type_query)) for field_query in query.field_queries )) @g.resolver(g.ListType(Book)) def resolve_book(graph, query): books = [ dict(title="Leave it to Psmith"), dict(title="Pericles, Prince of Tyre"), ] return [ query.element_query.create_object(iterables.to_dict( (field_query.key, book[field_query.field.name]) for field_query in query.element_query.field_queries )) for book in books ] resolvers = [resolve_root, resolve_book] query = Root( g.key("books", Root.fields.books( g.key("title", Book.fields.title()), )), ) result = g.create_graph(resolvers).resolve(query) assert_that(result, has_attrs( books=contains_exactly( has_attrs(title="Leave it to Psmith"), has_attrs(title="Pericles, Prince of Tyre"), ), ))
def test_can_request_fields_of_list(): Root = g.ObjectType( "Root", fields=lambda: ( g.field("one", type=g.ListType(One)), ), ) One = g.ObjectType( "One", fields=lambda: ( g.field("two", type=g.Int), ), ) graphql_query = """ query { one { two } } """ object_query = _document_text_to_graph_query(graphql_query, query_type=Root) assert_that(object_query, is_query( Root( g.key("one", Root.fields.one( g.key("two", One.fields.two()), )), ), ))
def test_fragment_can_be_spread_into_list_type(): User = g.ObjectType("User", fields=lambda: ( g.field("name", type=g.String), )) Root = g.ObjectType( "Root", fields=lambda: ( g.field("user", type=g.ListType(User)), ), ) graphql_query = """ query { user { ... on User { name } } } """ object_query = _document_text_to_graph_query(graphql_query, query_type=Root) assert_that(object_query, is_query( Root( g.key("user", Root.fields.user( g.key("name", User.fields.name()), )), ), ))
def test_when_field_value_in_input_object_in_list_is_not_set_then_default_is_used(): Input = schema.InputObjectType( "Input", fields=( schema.input_field("field0", type=schema.Int, default=42), ), ) Root = g.ObjectType( "Root", fields=( g.field("one", type=g.Int, params=[ g.param("arg", type=g.ListType(Input)), ]), ), ) graphql_query = """ query { one(arg: [{}]) } """ object_query = _document_text_to_graph_query(graphql_query, query_type=Root) assert_that(object_query.field_queries[0].args.arg, is_sequence( has_attrs( field0=42, ), ))
def _to_list_query(field_query): element_type = field_query.field.type type_query = field_query.type_query while isinstance(element_type, (g.ListType, g.NullableType)): element_type = element_type.element_type type_query = type_query.element_query return ListQuery(g.ListType(element_type), type_query)
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)), ]
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)), ]
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_fragment_fields_are_updated_to_fields_for_element_type(): Person = g.InterfaceType( "Person", fields=lambda: ( g.field("name", type=g.String), ), ) User = g.ObjectType( "User", fields=lambda: ( g.field("name", type=g.String), ), interfaces=lambda: (Person, ), ) Root = g.ObjectType( "Root", fields=lambda: ( g.field("users", type=g.ListType(g.NullableType(User))), ), ) graphql_query = """ query { users { ... on Person { name } } } """ object_query = _document_text_to_graph_query(graphql_query, query_type=Root) assert_that(object_query, is_query( Root( g.key("users", Root.fields.users( g.key("name", User.fields.name()), )), ), ))
book_resolver = gsql.sql_table_resolver( Book, BookRecord, fields={ Book.fields.title: gsql.expression(BookRecord.title), Book.fields.author: g.single(gsql.sql_join({ BookRecord.author_id: AuthorRecord.id, })), }, ) Root = g.ObjectType("Root", fields=lambda: (g.field("books", type=g.ListType(Book)), )) root_resolver = g.root_object_resolver(Root) @root_resolver.field(Root.fields.books) def root_resolve_books(graph, query, args): return graph.resolve(gsql.select(query)) resolvers = (author_resolver, book_resolver, root_resolver) graph_definition = g.define_graph(resolvers=resolvers) def execute_query(query, *, variables=None, session): graph = graph_definition.create_graph({
def test_list_type_is_converted_to_non_null_list_type(): assert_that( to_graphql_type(g.ListType(g.Boolean)), is_graphql_non_null(is_graphql_list(is_graphql_non_null(is_graphql_boolean))), )
import graphlayer as g import graphlayer.graphql from . import molecules Query = g.ObjectType( "Query", fields=lambda: ( g.field("molecules", type=g.ListType(molecules.Molecule)), molecules.molecules_connection.field("molecules_connection"), ), ) resolve_query = g.root_object_resolver(Query) @resolve_query.field(Query.fields.molecules) def query_resolve_molecules(graph, query, args): return graph.resolve(molecules.MoleculeQuery.select(query)) @resolve_query.field(Query.fields.molecules_connection) def query_resolve_molecules_connection(graph, query, args): return graph.resolve( molecules.molecules_connection.select_field(query, args=args)) resolvers = (resolve_query, )
import graphlayer as g import graphlayer.connections import graphlayer.sqlalchemy as gsql from .. import database Molecule = g.ObjectType( "Molecule", fields=lambda: ( g.field("pref_name", type=g.NullableType(g.String)), g.field("chembl_id", type=g.String), g.field("synonyms", type=g.ListType(MoleculeSynonym)), ), ) class MoleculeQuery(object): @staticmethod def select(query): return gsql.select(query) @staticmethod def select_by_molregno(query, molregnos): return gsql.select(query).by(database.Molecule.molregno, molregnos) resolve_molecule = gsql.sql_table_resolver( Molecule, database.Molecule, fields=lambda: {
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), ))
import graphlayer as g import graphlayer.sqlalchemy as gsql from .. import database from . import books Author = g.ObjectType("Author", fields=lambda: ( g.field("books", type=g.ListType(books.Book)), g.field("name", type=g.String), )) class AuthorQuery(object): @staticmethod def select(type_query): return gsql.select(type_query) @staticmethod def select_by_id(type_query, ids): return AuthorQuery.select(type_query).by(database.Author.id, ids) author_sql_resolver = gsql.sql_table_resolver( Author, database.Author, fields=lambda: { Author.fields.books: gsql.join( key=database.Author.id, resolve=lambda graph, field_query, ids: graph.resolve(
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", ), ), ))
spring = "SPRING" summer = "SUMMER" autumn = "AUTUMN" @pytest.mark.parametrize( "arg_type, arg_string, arg_value", [ (g.Boolean, "true", True), (g.Float, "4.2", 4.2), (g.Int, "42", 42), (g.String, '"value"', "value"), (g.EnumType(Season), '"WINTER"', Season.winter), (g.NullableType(g.Int), "42", 42), #~ (g.NullableType(g.Int), "null", None), (g.ListType(g.Int), "[]", []), (g.ListType(g.Int), "[1, 2, 3]", [1, 2, 3]), ( g.InputObjectType("User", fields=( g.input_field("id", type=g.Int), g.input_field("name", type=g.String), )), '{id: 42, name: "Bob"}', g.Object({ "id": 42, "name": "Bob" }), ), ]) def test_graphql_arg_values_are_converted(arg_type, arg_string, arg_value):
def test_can_recursively_resolve_selected_fields(): 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), ], ) @g.resolver(Root) def resolve_root(graph, query): return query.create_object( iterables.to_dict( (field_query.key, graph.resolve(field_query.type_query)) for field_query in query.fields)) books = [ dict(author_id="wodehouse", title="Leave it to Psmith"), dict(author_id="shakespeare", title="Pericles, Prince of Tyre"), ] def resolve_title(graph, book, query): return book["title"] class AuthorQuery(object): type = "author" def __init__(self, type_query, author_id): self.type_query = type_query self.author_id = author_id def resolve_author(graph, book, query): return graph.resolve(AuthorQuery(query, author_id=book["author_id"])) fields = { "title": resolve_title, "author": resolve_author, } def resolve_field(graph, book, field_query): return fields[field_query.field.name](graph, book, field_query.type_query) @g.resolver(g.ListType(Book)) def resolve_book(graph, query): return [ query.element_query.create_object( iterables.to_dict( (field_query.key, resolve_field(graph, book, field_query)) for field_query in query.element_query.fields)) for book in books ] authors = { "wodehouse": dict(name="PG Wodehouse"), "shakespeare": dict(name="William Shakespeare"), } @g.resolver(AuthorQuery.type) def resolve_author(graph, query): author = authors[query.author_id] return query.type_query.create_object( iterables.to_dict((field_query.key, author[field_query.field.name]) for field_query in query.type_query.fields)) resolvers = [resolve_root, resolve_book, resolve_author] 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()), )), ) result = g.create_graph(resolvers).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_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_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_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", ), ), ))
winter = "WINTER" spring = "SPRING" summer = "SUMMER" autumn = "AUTUMN" # TODO: deduplicate arg/variable tests @pytest.mark.parametrize("arg_type, arg_string, arg_value", [ (g.Boolean, "true", True), (g.Float, "4.2", 4.2), (g.Int, "42", 42), (g.String, '"value"', "value"), (g.EnumType(Season), 'WINTER', Season.winter), (g.NullableType(g.Int), "42", 42), (g.NullableType(g.Int), "null", None), (g.ListType(g.Int), "[]", []), (g.ListType(g.Int), "[1, 2, 3]", [1, 2, 3]), ( g.InputObjectType("User", fields=( g.input_field("id", type=g.Int), g.input_field("name", type=g.String), )), '{id: 42, name: "Bob"}', lambda input_type: input_type(id=42, name="Bob"), ), ( g.InputObjectType("Casing", fields=( g.input_field("field_zero", type=g.Int), )), '{fieldZero: 1}', lambda input_type: input_type(field_zero=1),
def forward_connection(*, connection_type_name, node_type, select_by_cursor, fetch_cursors, cursor_encoding): Connection = g.ObjectType( connection_type_name, fields=lambda: ( g.field("edges", type=g.ListType(Edge)), g.field("nodes", type=g.ListType(node_type)), g.field("page_info", type=PageInfo), ), ) Edge = g.ObjectType( node_type.name + "Edge", fields=lambda: ( g.field("cursor", type=g.String), g.field("node", type=node_type), ), ) class ConnectionQuery(object): @staticmethod def select_field(query, *, args): if args.first < 0: raise g.GraphError( "first must be non-negative integer, was {}".format( args.first)) else: return ConnectionQuery(type_query=query, first=args.first, after=args.after) def __init__(self, *, type_query, first, after): self.type = ConnectionQuery self.type_query = type_query self.first = first self.after = after @g.dependencies(injector=Injector) @g.resolver(ConnectionQuery) def resolve_connection(graph, query, *, injector): build_connection = g.create_object_builder(query.type_query) if query.after is None: after_cursor = None else: after_cursor = cursor_encoding.decode(query.after) edge_cursors = injector.call_with_dependencies( fetch_cursors, after_cursor=after_cursor, limit=query.first + 1) if len(edge_cursors) > query.first: edge_cursors = edge_cursors[:-1] has_next_page = True else: has_next_page = False @build_connection.field(Connection.fields.edges) def field_edges(field_query): build_edge = g.create_object_builder( field_query.type_query.element_query) @build_edge.getter(Edge.fields.cursor) def field_cursor(cursor): return cursor_encoding.encode(cursor) @build_edge.field(Edge.fields.node) def field_node(field_query): edges = graph.resolve( select_by_cursor(field_query.type_query, edge_cursors)) return lambda edge_cursor: edges[edge_cursor] return lambda _: [ build_edge(edge_cursor) for edge_cursor in edge_cursors ] @build_connection.field(Connection.fields.nodes) def field_nodes(field_query): nodes = graph.resolve( select_by_cursor(field_query.type_query.element_query, edge_cursors)) result = [nodes[edge_cursor] for edge_cursor in edge_cursors] return lambda _: result @build_connection.field(Connection.fields.page_info) def field_page_info(field_query): build_page_info = g.create_object_builder(field_query.type_query) @build_page_info.getter(PageInfo.fields.has_next_page) def field_has_next_page(_): return has_next_page @build_page_info.getter(PageInfo.fields.end_cursor) def field_end_cursor(_): if edge_cursors: return cursor_encoding.encode(edge_cursors[-1]) else: return None return lambda _: build_page_info(None) return build_connection(None) return ForwardConnection( Connection=Connection, Edge=Edge, resolver=resolve_connection, select_field=ConnectionQuery.select_field, )
import graphlayer as g from . import authors, books Root = g.ObjectType("Root", fields=( g.field("authors", g.ListType(authors.Author)), g.field("books", g.ListType(books.Book)), )) root_resolver = g.root_object_resolver(Root) @root_resolver.field(Root.fields.authors) def root_resolve_authors(graph, query, args): return graph.resolve(authors.AuthorQuery.select(query)) @root_resolver.field(Root.fields.books) def root_resolve_books(graph, query, args): return graph.resolve(books.BookQuery.select(query)) resolvers = (root_resolver, )