Merge branch 'master' into feature/django

This commit is contained in:
Adam Charnock 2015-12-05 09:10:38 +00:00
commit afd7aa8d72
8 changed files with 102 additions and 8 deletions

View File

@ -1,6 +1,9 @@
import six import six
from django.db import models from django.db import models
from django.db.models.manager import Manager from django.db.models.manager import Manager
from django.db.models.query import QuerySet
from graphene.utils import LazyList
from graphene import Argument, String from graphene import Argument, String
@ -24,9 +27,20 @@ def get_reverse_fields(model):
yield related yield related
class WrappedQueryset(LazyList):
def __len__(self):
# Dont calculate the length using len(queryset), as this will
# evaluate the whole queryset and return it's length.
# Use .count() instead
return self._origin.count()
def maybe_queryset(value): def maybe_queryset(value):
if isinstance(value, Manager): if isinstance(value, Manager):
value = value.get_queryset() value = value.get_queryset()
if isinstance(value, QuerySet):
return WrappedQueryset(value)
return value return value

View File

@ -1,5 +1,6 @@
import copy import copy
import inspect import inspect
from functools import partial
from collections import OrderedDict from collections import OrderedDict
import six import six
@ -48,8 +49,8 @@ class ClassTypeMeta(type):
if not cls._meta.abstract: if not cls._meta.abstract:
from ..types import List, NonNull from ..types import List, NonNull
setattr(cls, 'NonNull', NonNull(cls)) setattr(cls, 'NonNull', partial(NonNull, cls))
setattr(cls, 'List', List(cls)) setattr(cls, 'List', partial(List, cls))
return cls return cls

View File

@ -23,15 +23,26 @@ def test_classtype_advanced():
def test_classtype_definition_list(): def test_classtype_definition_list():
class Character(ClassType): class Character(ClassType):
'''Character description''' '''Character description'''
assert isinstance(Character.List, List) assert isinstance(Character.List(), List)
assert Character.List.of_type == Character assert Character.List().of_type == Character
def test_classtype_definition_nonnull(): def test_classtype_definition_nonnull():
class Character(ClassType): class Character(ClassType):
'''Character description''' '''Character description'''
assert isinstance(Character.NonNull, NonNull) assert isinstance(Character.NonNull(), NonNull)
assert Character.NonNull.of_type == Character assert Character.NonNull().of_type == Character
def test_fieldsclasstype_definition_order():
class Character(ClassType):
'''Character description'''
class Query(FieldsClassType):
name = String()
char = Character.NonNull()
assert list(Query._meta.fields_map.keys()) == ['name', 'char']
def test_fieldsclasstype(): def test_fieldsclasstype():

View File

@ -4,6 +4,7 @@ from collections import Iterable
from functools import wraps from functools import wraps
import six import six
from graphql_relay.connection.arrayconnection import connection_from_list from graphql_relay.connection.arrayconnection import connection_from_list
from graphql_relay.node.node import to_global_id from graphql_relay.node.node import to_global_id

View File

@ -3,8 +3,9 @@ from .proxy_snake_dict import ProxySnakeDict
from .caching import cached_property, memoize from .caching import cached_property, memoize
from .misc import enum_to_graphql_enum from .misc import enum_to_graphql_enum
from .resolve_only_args import resolve_only_args from .resolve_only_args import resolve_only_args
from .lazylist import LazyList
__all__ = ['to_camel_case', 'to_snake_case', 'ProxySnakeDict', __all__ = ['to_camel_case', 'to_snake_case', 'ProxySnakeDict',
'cached_property', 'memoize', 'enum_to_graphql_enum', 'cached_property', 'memoize', 'enum_to_graphql_enum',
'resolve_only_args'] 'resolve_only_args', 'LazyList']

View File

@ -0,0 +1,43 @@
class LazyList(object):
def __init__(self, origin, state=None):
self._origin = origin
self._state = state or []
self._origin_iter = None
self._finished = False
def __iter__(self):
return self if not self._finished else iter(self._state)
def iter(self):
return self.__iter__()
def __len__(self):
return self._origin.__len__()
def __next__(self):
try:
if not self._origin_iter:
self._origin_iter = self._origin.__iter__()
n = next(self._origin_iter)
except StopIteration as e:
self._finished = True
raise e
else:
self._state.append(n)
return n
def next(self):
return self.__next__()
def __getitem__(self, key):
item = self._origin[key]
if isinstance(key, slice):
return self.__class__(item)
return item
def __getattr__(self, name):
return getattr(self._origin, name)
def __repr__(self):
return "<{} {}>".format(self.__class__.__name__, repr(self._origin))

View File

@ -0,0 +1,23 @@
from py.test import raises
from ..lazylist import LazyList
def test_lazymap():
data = list(range(10))
lm = LazyList(data)
assert len(lm) == 10
assert lm[1] == 1
assert isinstance(lm[1:4], LazyList)
assert lm.append == data.append
assert repr(lm) == '<LazyList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>'
def test_lazymap_iter():
data = list(range(2))
lm = LazyList(data)
iter_lm = iter(lm)
assert iter_lm.next() == 0
assert iter_lm.next() == 1
with raises(StopIteration):
iter_lm.next()

View File

@ -24,7 +24,7 @@ class PyTest(TestCommand):
setup( setup(
name='graphene', name='graphene',
version='0.4.2', version='0.4.3',
description='Graphene: Python DSL for GraphQL', description='Graphene: Python DSL for GraphQL',
long_description=open('README.rst').read(), long_description=open('README.rst').read(),