예제 #1
0
def test_record_option_type_errors():
    check_option_errors(
        [Option('lawing', Record[{'tingent': Integer}])],
        {'lawing': {'tingent': 123}},
        [],
    )
    check_option_errors(
        [Option('lawing', Record[{'tingent': Integer}])],
        {'lawing': Invalid()},
        ['Invalid value for option "{field}:lawing", '
         '"Invalid" instead of Record[{{\'tingent\': Integer}}]'],
    )
    check_option_errors(
        [Option('lawing', Record[{'tingent': Integer}])],
        {'lawing': {}},
        ['Invalid value for option "{field}:lawing", '
         'missing fields: tingent'],
    )
    check_option_errors(
        [Option('lawing', Record[{'tingent': Integer}])],
        {'lawing': {Invalid(): 1}},
        ['Invalid value for option "{field}:lawing", '
         'unknown fields: <invalid>'],
    )
    check_option_errors(
        [Option('lawing', Record[{'tingent': Integer}])],
        {'lawing': {'tingent': Invalid()}},
        ['Invalid value for option "{field}:lawing", '
         '"Invalid" instead of Integer'],
    )
예제 #2
0
def test_mutation_type():
    data_types = {
        'Foo': Record[{
            'bar': Integer,
        }],
    }
    query_graph = Graph([Root([
        Field('getFoo', Integer, _noop, options=[
            Option('getterArg', TypeRef['Foo']),
        ]),
    ])], data_types)
    mutation_graph = Graph(query_graph.nodes + [Root([
        Field('setFoo', Integer, _noop, options=[
            Option('setterArg', TypeRef['Foo']),
        ]),
    ])], data_types=query_graph.data_types)
    assert introspect(query_graph, mutation_graph) == _schema([
        _type('Query', 'OBJECT', fields=[
            _field('getFoo', _non_null(_INT), args=[
                _ival('getterArg', _non_null(_iobj('IOFoo'))),
            ]),
        ]),
        _type('Mutation', 'OBJECT', fields=[
            _field('setFoo', _non_null(_INT), args=[
                _ival('setterArg', _non_null(_iobj('IOFoo'))),
            ]),
        ]),
        _type('Foo', 'OBJECT', fields=[
            _field('bar', _non_null(_INT)),
        ]),
        _type('IOFoo', 'INPUT_OBJECT', inputFields=[
            _ival('bar', _non_null(_INT)),
        ]),
    ], with_mutation=True)
예제 #3
0
def test_introspection_query():
    graph = Graph([
        Node('flexed', [
            Field('yari',
                  Boolean,
                  _noop,
                  options=[
                      Option('membuka', Sequence[String], default=['frayed']),
                      Option('modist',
                             Optional[Integer],
                             default=None,
                             description='callow'),
                  ]),
        ]),
        Node('decian', [
            Field('dogme', Integer, _noop),
            Link('clarkia', Sequence[TypeRef['flexed']], _noop, requires=None),
        ]),
        Root([
            Field('_cowered', String, _noop),
            Field('entero', Float, _noop),
            Link('toma', Sequence[TypeRef['decian']], _noop, requires=None),
        ]),
    ])
    assert introspect(graph) == _schema([
        _type('flexed',
              'OBJECT',
              fields=[
                  _field('yari',
                         _non_null(_BOOL),
                         args=[
                             _ival('membuka',
                                   _seq_of(_STR),
                                   defaultValue='["frayed"]'),
                             _ival('modist',
                                   _INT,
                                   defaultValue='null',
                                   description='callow'),
                         ]),
              ]),
        _type('decian',
              'OBJECT',
              fields=[
                  _field('dogme', _non_null(_INT)),
                  _field('clarkia', _seq_of(_obj('flexed'))),
              ]),
        _type('Query',
              'OBJECT',
              fields=[
                  _field('entero', _non_null(_FLOAT)),
                  _field('toma', _seq_of(_obj('decian'))),
              ]),
    ])
예제 #4
0
def test_optional_option_type_errors():
    check_option_errors(
        [Option('lawing', Optional[Integer])],
        {'lawing': None},
        [],
    )
    check_option_errors(
        [Option('lawing', Optional[Integer])],
        {'lawing': Invalid()},
        ['Invalid value for option "{field}:lawing", '
         '"Invalid" instead of Integer'],
    )
예제 #5
0
def test_conflicting_fields():
    x_data = {'xN': {'a': 42}}

    @listify
    def x_fields(fields, ids):
        for i in ids:
            yield ['{}-{}'.format(x_data[i][f.name], f.options['k'])
                   for f in fields]

    graph = Graph([
        Node('X', [
            Field('a', None, x_fields, options=[Option('k', Integer)]),
        ]),
        Root([
            Link('x1', TypeRef['X'], lambda: 'xN', requires=None),
            Link('x2', TypeRef['X'], lambda: 'xN', requires=None),
        ]),
    ])

    result = execute(graph, q.Node([
        q.Link('x1', q.Node([q.Field('a', options={'k': 1})])),
        q.Link('x2', q.Node([q.Field('a', options={'k': 2})])),
    ]))
    check_result(result, {
        'x1': {'a': '42-1'},
        'x2': {'a': '42-2'},
    })
예제 #6
0
def test_sequence_option_type_errors():
    check_option_errors(
        [Option('lawing', Sequence[Integer])],
        {'lawing': [123]},
        [],
    )
    check_option_errors(
        [Option('lawing', Sequence[Integer])],
        {'lawing': Invalid()},
        ['Invalid value for option "{field}:lawing", '
         '"Invalid" instead of Sequence[Integer]'],
    )
    check_option_errors(
        [Option('lawing', Sequence[Integer])],
        {'lawing': [Invalid()]},
        ['Invalid value for option "{field}:lawing", '
         '"Invalid" instead of Integer'],
    )
예제 #7
0
def test_field_option_missing():
    graph = Graph([
        Root([
            Field('poofy', None, Mock(), options=[Option('mohism', None)]),
        ]),
    ])
    with pytest.raises(TypeError) as err:
        execute(graph, build([Q.poofy]))
    err.match('^Required option "mohism" for Field\(\'poofy\', '
              '(.*) was not provided$')
예제 #8
0
def test_missing_options():
    check_option_errors(
        [Option('lawing', Integer)],
        {},
        ['Required option "{field}:lawing" is not specified'],
    )
    check_option_errors(
        [Option('lawing', Integer, default=1)],
        {},
        [],
    )
    check_option_errors(
        [Option('lawing', Optional[Integer])],
        {},
        ['Required option "{field}:lawing" is not specified'],
    )
    check_option_errors(
        [Option('lawing', Optional[Integer], default=None)],
        {},
        [],
    )
예제 #9
0
def test_link_option_missing():
    graph = Graph([
        Node('slices', [
            Field('papeete', None, Mock()),
        ]),
        Root([
            Link('eclairs', Sequence[TypeRef['slices']], Mock(), requires=None,
                 options=[Option('nocks', None)]),
        ]),
    ])
    with pytest.raises(TypeError) as err:
        execute(graph, build([Q.eclairs[Q.papeete]]))
    err.match(r'^Required option "nocks" for Link\(\'eclairs\', '
              r'(.*) was not provided$')
예제 #10
0
def test_link_contain_invalid_types():
    check_errors(
        [
            Node('foo', []),
            Node('bar', [
                Field('id', None, _fields_func),
                Link('baz', Sequence[TypeRef['foo']],
                     _link_func, requires='id',
                     options=[Option('size', None), 1]),
            ]),
        ],
        [('Invalid types provided as link "bar.baz" options: {!r}'
          .format(int))],
    )
예제 #11
0
def test_unsupported_option():
    result = introspect(
        Graph([
            Root([
                Field('huke',
                      Integer,
                      field_func,
                      options=[Option('orel', Optional[Any])]),
                Field('terapin', Integer, field_func),
            ]),
        ]))

    assert result['__schema']['types'][-1]['name'] == 'Root'
    assert [f['name'] for f in result['__schema']['types'][-1]['fields']] == \
           ['terapin']
예제 #12
0
def test_any_in_option():
    graph = Graph([
        Root([
            Field('get', None, None, options=[
                Option('foo', Mapping[String, Any]),
            ]),
        ]),
    ])
    assert validate(graph, q.Node([
        q.Field('get', options={'foo': {u'key': 1}}),
    ])) == []
    assert validate(graph, q.Node([
        q.Field('get', options={'foo': 'bar'}),
    ])) == ['Invalid value for option "root.get:foo", '
            '"str" instead of Mapping[String, Any]']
예제 #13
0
def test_mapping_option_type_errors():
    check_option_errors(
        [Option('lawing', Mapping[Integer, String])],
        {'lawing': {123: u"oik"}},
        [],
    )
    check_option_errors(
        [Option('lawing', Mapping[Integer, String])],
        {'lawing': Invalid()},
        ['Invalid value for option "{field}:lawing", '
         '"Invalid" instead of Mapping[Integer, String]'],
    )
    check_option_errors(
        [Option('lawing', Mapping[Integer, String])],
        {'lawing': {Invalid(): u"oik"}},
        ['Invalid value for option "{field}:lawing", '
         '"Invalid" instead of Integer'],
    )
    check_option_errors(
        [Option('lawing', Mapping[Integer, String])],
        {'lawing': {123: Invalid()}},
        ['Invalid value for option "{field}:lawing", '
         '"Invalid" instead of String'],
    )
예제 #14
0
def test_unsupported_option_type():
    graph = Graph([
        Root([
            Field('huke', Integer, _noop,
                  options=[Option('orel', Optional[Any])]),
            Field('terapin', Integer, _noop),
        ]),
    ])
    assert introspect(graph) == _schema([
        _type('Query', 'OBJECT', fields=[
            _field('huke', _non_null(_INT), args=[
                _ival('orel', _ANY),
            ]),
            _field('terapin', _non_null(_INT)),
        ]),
    ])
예제 #15
0
def test_conflicting_links():
    data = {
        'yA': {'a': 1, 'b': 2},
        'yB': {'a': 3, 'b': 4},
        'yC': {'a': 5, 'b': 6},
    }
    x2y = {'xN': ['yA', 'yB', 'yC']}

    @listify
    def y_fields(fields, ids):
        for i in ids:
            yield [data[i][f.name] for f in fields]

    @listify
    def x_to_y_link(ids, options):
        for i in ids:
            yield [y for y in x2y[i] if y not in options['exclude']]

    graph = Graph([
        Node('Y', [
            Field('a', None, y_fields),
            Field('b', None, y_fields),
        ]),
        Node('X', [
            Field('id', None, id_field),
            Link('y', Sequence[TypeRef['Y']], x_to_y_link, requires='id',
                 options=[Option('exclude', None)]),
        ]),
        Root([
            Link('x1', TypeRef['X'], lambda: 'xN', requires=None),
            Link('x2', TypeRef['X'], lambda: 'xN', requires=None),
        ]),
    ])
    result = execute(graph, q.Node([
        q.Link('x1', q.Node([
            q.Link('y', q.Node([q.Field('a')]),
                   options={'exclude': ['yA']}),
        ])),
        q.Link('x2', q.Node([
            q.Link('y', q.Node([q.Field('b')]),
                   options={'exclude': ['yC']}),
        ])),
    ]))
    check_result(result, {
        'x1': {'y': [{'a': 3}, {'a': 5}]},
        'x2': {'y': [{'b': 2}, {'b': 4}]},
    })
예제 #16
0
def test_typeref_in_option():
    data_types = {
        'Foo': Record[{
            'key': Integer,
        }],
    }
    graph = Graph([
        Root([
            Field('get', None, None, options=[Option('foo', TypeRef['Foo'])]),
        ]),
    ], data_types=data_types)
    assert validate(graph, q.Node([
        q.Field('get', options={'foo': {'key': 1}}),
    ])) == []
    assert validate(graph, q.Node([
        q.Field('get', options={'foo': {'key': '1'}}),
    ])) == ['Invalid value for option "root.get:foo", "str" instead of Integer']
예제 #17
0
def test_distinct_by_options_links():
    graph = Graph([
        Node('X', [
            Field('a', None, None),
        ]),
        Root([
            Link('x', TypeRef['X'], None, requires=None,
                 options=[Option('e', Optional[Integer], default=None)]),
        ]),
    ])
    errors = validate(graph, q.Node([
        q.Link('x', q.Node([q.Field('a')])),
        q.Link('x', q.Node([q.Field('a')]), options={'e': 1}),
    ]))
    assert errors == [
        'Found distinct fields with the same resulting name "x" for the '
        'node "root"'
    ]
예제 #18
0
def test_invalid_names():
    graph = Graph([
        Node('Baz-Baz', [
            Field('bzz-bzz', Integer, _noop),
        ]),
        Root([
            Field('foo-foo', Integer, _noop,
                  options=[Option('bar-bar', Integer)]),
            Link('baz-baz', Sequence[TypeRef['Baz-Baz']], _noop,
                 requires='foo-foo'),
        ]),
    ])
    with pytest.raises(ValueError) as err:
        apply(graph, [GraphQLIntrospection(graph)])
    assert err.match('bzz-bzz')
    assert err.match('foo-foo')
    assert err.match('bar-bar')
    assert err.match('baz-baz')
    assert err.match('Baz-Baz')
예제 #19
0
def test_scalar_option_type_errors():
    check_option_errors([Option('lawing', Boolean)], {'lawing': True}, [])
    check_option_errors([Option('lawing', Boolean)], {'lawing': Invalid()}, [
        'Invalid value for option "{field}:lawing", '
        '"Invalid" instead of Boolean'
    ])
    check_option_errors([Option('lawing', Integer)], {'lawing': 123}, [])
    check_option_errors([Option('lawing', Integer)], {'lawing': Invalid()}, [
        'Invalid value for option "{field}:lawing", '
        '"Invalid" instead of Integer'
    ])
    check_option_errors([Option('lawing', String)], {'lawing': u"raundon"}, [])
    check_option_errors([Option('lawing', String)], {'lawing': Invalid()}, [
        'Invalid value for option "{field}:lawing", '
        '"Invalid" instead of String'
    ])
예제 #20
0
파일: utils.py 프로젝트: kindermax/hiku
        Field('id', Integer, cart_resolver),
        Field('status', TypeRef['Status'], cart_resolver),
        Link('items', Sequence[TypeRef['CartItem']], link_cart_items,
             requires='id')
    ], directives=[Key('id')]),
    Node('CartItem', [
        Field('id', Integer, cart_item_resolver),
        Field('cart_id', Integer, cart_item_resolver),
        Field(
            'name',
            String,
            cart_item_resolver,
            directives=[Deprecated('do not use')]
        ),
        Field('photo', Optional[String], lambda: None, options=[
            Option('width', Integer),
            Option('height', Integer),
        ]),
    ]),
    Root([
        Link(
            'cart',
            Optional[TypeRef['Cart']],
            ids_resolver,
            requires=None,
            options=[
                Option('id', Integer)
            ],
        ),
    ]),
], data_types=data_types)
예제 #21
0
from hiku.engine import Engine, pass_context, Context
from hiku.result import denormalize
from hiku.builder import build, Q
from hiku.executors.sync import SyncExecutor

from .base import check_result, ANY, Mock


@listify
def id_field(fields, ids):
    for i in ids:
        yield [i for _ in fields]


OPTION_BEHAVIOUR = [
    (Option('op', None), {'op': 1812}, {'op': 1812}),
    (Option('op', None, default=None), {}, {'op': None}),
    (Option('op', None, default=None), {'op': 2340}, {'op': 2340}),
    (Option('op', None, default=3914), {}, {'op': 3914}),
    (Option('op', None, default=4254), {'op': None}, {'op': None}),
    (Option('op', None, default=1527), {'op': 8361}, {'op': 8361}),
]


def execute(graph, query_, ctx=None):
    engine = Engine(SyncExecutor())
    return engine.execute(graph, query_, ctx=ctx)


def test_context():
    ctx = Context({'foo': 'bar'})
예제 #22
0
GRAPH = Graph([
    Node('hooted', []),
    Root([
        # simple
        Field('robby', None, _),
        # complex
        Field('wounded', Optional[Record[{'attr': Integer}]], _),
        Field('annuals', Record[{'attr': Integer}], _),
        Field('hialeah', Sequence[Record[{'attr': Integer}]], _),
        Field('val', Optional[TypeRef['Val']], _),

        # nested records
        Field('rlyeh', Record[{'cthulhu': Record[{'fhtagn': Integer}]}], _),

        # with options
        Field('motown', None, _, options=[Option('prine', None)]),
        Field('nyerere', None, _, options=[Option('epaule', None, default=1)]),
        Field('wreche', None, _, options=[Option('cierra', Integer)]),
        Field('hunter', None, _, options=[Option('fried', Integer, default=1)]),
        Field('tapioca', None, _,
              options=[Option('arbour', Optional[Integer], default=None)]),

        # simple
        Link('amyls', Sequence[TypeRef['hooted']], _, requires=None),
        # with options
        Link('ferrous', Sequence[TypeRef['hooted']], _, requires=None,
             options=[Option('cantab', None)]),
        Link('knesset', Sequence[TypeRef['hooted']], _, requires=None,
             options=[Option('ceases', None, default=1)]),
        Link('pouria', Sequence[TypeRef['hooted']], _, requires=None,
             options=[Option('flunk', Integer)]),
예제 #23
0
        Field('status', String, cart_resolver),
        Link('items',
             Sequence[TypeRef['CartItem']],
             link_cart_items,
             requires='id')
    ],
         directives=[Key('id')]),
    Node('CartItem', [
        Field('id', Integer, cart_item_resolver),
        Field('cart_id', Integer, cart_item_resolver),
        Field('name', String, cart_item_resolver),
        Field('photo',
              Optional[String],
              lambda: None,
              options=[
                  Option('width', Integer),
                  Option('height', Integer),
              ]),
    ]),
    Root([
        Link(
            'cart',
            Optional[TypeRef['Cart']],
            direct_link_id,
            requires=None,
            options=[Option('id', Integer)],
        ),
    ]),
])

app = Flask(__name__)
예제 #24
0
sg_y = SubGraph(_GRAPH, 'y')

# TODO: refactor
GRAPH = Graph([
    Node('x1', [
        Field('id', None, sg_x),
        Field('a', None, sg_x),
        Field('f', None, sg_x.c(S.f1)),
        Field('foo', None, sg_x.c(foo(S.this, S.this.y))),
        Field('bar', None, sg_x.c(bar(S.this))),
        Field('baz', None, sg_x.c(baz(S.this.y))),
        Field('buz',
              None,
              sg_x.c(buz(S.this, S.size)),
              options=[Option('size', None, default=None)]),
        Field('buz2',
              None,
              sg_x.c(buz(S.this, S.size)),
              options=[Option('size', None, default=100)]),
        Field('buz3',
              None,
              sg_x.c(buz(S.this, S.size)),
              options=[Option('size', None)]),
    ]),
    Node('y1', [
        Field('id', None, sg_y),
        Field('c', None, sg_y),
        Field('f', None, sg_y.c(S.f2)),
        Field('foo', None, sg_y.c(each(S.x, S.this.xs, foo(S.x, S.this)))),
        Field('bar', None, sg_y.c(each(S.x, S.this.xs, bar(S.x)))),
예제 #25
0
sg_y = SubGraph(_GRAPH, 'y')

# TODO: refactor
GRAPH = Graph([
    Node('x1', [
        Field('id', None, sg_x),
        Field('a', None, sg_x),
        Field('f', None, sg_x.c(S.f1)),
        Field('foo', None, sg_x.c(foo(S.this, S.this.y))),
        Field('bar', None, sg_x.c(bar(S.this))),
        Field('baz', None, sg_x.c(baz(S.this.y))),
        Field('buz',
              None,
              sg_x.c(buz(S.this, S.size)),
              options=[Option('size', None, default=None)]),
        Field('buz2',
              None,
              sg_x.c(buz(S.this, S.size)),
              options=[Option('size', None, default=100)]),
        Field('buz3',
              None,
              sg_x.c(buz(S.this, S.size)),
              options=[Option('size', None)]),
        Field('with_option', None, query_x1, options=[Option('opt', None)]),
    ]),
    Node('y1', [
        Field('id', None, sg_y),
        Field('c', None, sg_y),
        Field('f', None, sg_y.c(S.f2)),
        Field('foo', None, sg_y.c(each(S.x, S.this.xs, foo(S.x, S.this)))),
예제 #26
0
_GRAPH = Graph([
    Node('flexed', [
        Field('yari', Boolean, field_func),
    ]),
])

flexed_sg = SubGraph(_GRAPH, 'flexed')

GRAPH = Graph([
    Node('flexed', [
        Field('yari',
              Boolean,
              flexed_sg,
              options=[
                  Option('membuka', Sequence[String], default=['frayed']),
                  Option('modist',
                         Optional[Integer],
                         default=None,
                         description='callow'),
              ]),
    ]),
    Node('decian', [
        Field('dogme', Integer, field_func),
        Link('clarkia', Sequence[TypeRef['flexed']], link_func, requires=None),
    ]),
    Root([
        Field('cowered', String, field_func),
        Field('entero', Float, field_func),
        Link('toma', Sequence[TypeRef['decian']], link_func, requires=None),
    ]),
예제 #27
0
def test_field_option_unknown():
    test_field_option_valid(Option('inked', None), {
        'inked': 2340,
        'unknown': 8775
    }, {'inked': 2340})
예제 #28
0
import re

import pytest

from hiku import query
from hiku.graph import Graph, Node, Field, Link, Option, Root
from hiku.types import Record, Sequence, Integer, Optional, TypeRef
from hiku.engine import Engine, pass_context, Context
from hiku.builder import build, Q
from hiku.executors.sync import SyncExecutor

from .base import reqs_eq_patcher, check_result, ANY, Mock

OPTION_BEHAVIOUR = [
    (Option('op', None), {
        'op': 1812
    }, {
        'op': 1812
    }),
    (Option('op', None, default=None), {}, {
        'op': None
    }),
    (Option('op', None, default=None), {
        'op': 2340
    }, {
        'op': 2340
    }),
    (Option('op', None, default=3914), {}, {
        'op': 3914
    }),
    (Option('op', None, default=4254), {
예제 #29
0
def test_link_option_unknown():
    test_link_option_valid(Option('oleic', None), {
        'oleic': 2340,
        'unknown': 8775
    }, {'oleic': 2340})
예제 #30
0
    }],
    'Data': Record[{
        'point': TypeRef['Point'],
    }],
}

QUERY_GRAPH = Graph([
    Root([
        Field('value', String, value_func),
    ]),
], 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)


async def handle_graphql(request):
    data = await request.json()
    result = await request.app['graphql-endpoint'].dispatch(data)
    return web.json_response(result)


def main():
    logging.basicConfig()
    app = web.Application()
    app.add_routes([
        web.post('/graphql', handle_graphql),