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)
Example #2
0
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"),
        ),
    ))
Example #3
0
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()),
            )),
        ),
    ))
Example #4
0
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()),
            )),
        ),
    ))
Example #5
0
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,
        ),
    ))
Example #6
0
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)
Example #7
0
 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)),
     ]
Example #8
0
 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)),
     ]
Example #9
0
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", ),
        ))
Example #10
0
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", ), ))
Example #11
0
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({
Example #13
0
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))),
    )
Example #14
0
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, )
Example #15
0
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: {
Example #16
0
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),
        ))
Example #17
0
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(
Example #18
0
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", ), ), ))
Example #19
0
    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",
            ),
        ), ))
Example #21
0
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",
            ),
        ), ))
Example #22
0
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"), ),
            ),
        ))
Example #23
0
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", ),
            ),
        ))
Example #24
0
    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),
Example #25
0
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,
    )
Example #26
0
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, )