mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 20:54:16 +03:00
Merge branch 'refs/heads/master' into features/django-fields
Conflicts: graphene/contrib/django/converter.py graphene/core/classtypes/enum.py
This commit is contained in:
commit
1b39992dbe
|
@ -14,10 +14,10 @@ Graphene comes with a management command for Django to dump your schema data to
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Include `graphene.django.contrib` to `INSTALLED_APPS` in you project settings:
|
Include `graphene.contrib.django` to `INSTALLED_APPS` in you project settings:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
INSTALLED_APPS += ('graphene.django.contrib')
|
INSTALLED_APPS += ('graphene.contrib.django')
|
||||||
```
|
```
|
||||||
|
|
||||||
Assuming your Graphene schema is at `tutorial.quickstart.schema`, run the command:
|
Assuming your Graphene schema is at `tutorial.quickstart.schema`, run the command:
|
||||||
|
|
|
@ -4,6 +4,7 @@ from ...core.classtypes.enum import Enum
|
||||||
from ...core.types.custom_scalars import DateTime, JSONString
|
from ...core.types.custom_scalars import DateTime, JSONString
|
||||||
from ...core.types.definitions import List
|
from ...core.types.definitions import List
|
||||||
from ...core.types.scalars import ID, Boolean, Float, Int, String
|
from ...core.types.scalars import ID, Boolean, Float, Int, String
|
||||||
|
from ...utils import to_const
|
||||||
from .compat import (ArrayField, HStoreField, JSONField, RangeField,
|
from .compat import (ArrayField, HStoreField, JSONField, RangeField,
|
||||||
RelatedObject, UUIDField)
|
RelatedObject, UUIDField)
|
||||||
from .utils import get_related_model, import_single_dispatch
|
from .utils import get_related_model, import_single_dispatch
|
||||||
|
@ -11,12 +12,17 @@ from .utils import get_related_model, import_single_dispatch
|
||||||
singledispatch = import_single_dispatch()
|
singledispatch = import_single_dispatch()
|
||||||
|
|
||||||
|
|
||||||
|
def convert_choices(choices):
|
||||||
|
for value, name in choices:
|
||||||
|
yield to_const(name), value
|
||||||
|
|
||||||
|
|
||||||
def convert_django_field_with_choices(field):
|
def convert_django_field_with_choices(field):
|
||||||
choices = getattr(field, 'choices', None)
|
choices = getattr(field, 'choices', None)
|
||||||
if choices:
|
if choices:
|
||||||
meta = field.model._meta
|
meta = field.model._meta
|
||||||
name = '{}_{}_{}'.format(meta.app_label, meta.object_name, field.name)
|
name = '{}_{}_{}'.format(meta.app_label, meta.object_name, field.name)
|
||||||
return Enum(name.upper(), choices, description=field.help_text)
|
return Enum(name.upper(), list(convert_choices(choices)), description=field.help_text)
|
||||||
return convert_django_field(field)
|
return convert_django_field(field)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ class Article(models.Model):
|
||||||
('es', 'Spanish'),
|
('es', 'Spanish'),
|
||||||
('en', 'English')
|
('en', 'English')
|
||||||
], default='es')
|
], default='es')
|
||||||
|
importance = models.IntegerField('Importance', null=True, blank=True,
|
||||||
|
choices=[(1, u'Very important'), (2, u'Not as important')])
|
||||||
|
|
||||||
def __str__(self): # __unicode__ on Python 2
|
def __str__(self): # __unicode__ on Python 2
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
|
@ -113,8 +113,8 @@ def test_field_with_choices_convert_enum():
|
||||||
assert issubclass(graphene_type, graphene.Enum)
|
assert issubclass(graphene_type, graphene.Enum)
|
||||||
assert graphene_type._meta.type_name == 'TEST_TRANSLATEDMODEL_LANGUAGE'
|
assert graphene_type._meta.type_name == 'TEST_TRANSLATEDMODEL_LANGUAGE'
|
||||||
assert graphene_type._meta.description == 'Language'
|
assert graphene_type._meta.description == 'Language'
|
||||||
assert graphene_type.__enum__.__members__['es'].value == 'Spanish'
|
assert graphene_type.__enum__.__members__['SPANISH'].value == 'es'
|
||||||
assert graphene_type.__enum__.__members__['en'].value == 'English'
|
assert graphene_type.__enum__.__members__['ENGLISH'].value == 'en'
|
||||||
|
|
||||||
|
|
||||||
def test_should_float_convert_float():
|
def test_should_float_convert_float():
|
||||||
|
|
|
@ -13,7 +13,6 @@ except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def convert_sqlalchemy_relationship(relationship):
|
def convert_sqlalchemy_relationship(relationship):
|
||||||
direction = relationship.direction
|
direction = relationship.direction
|
||||||
model = relationship.mapper.entity
|
model = relationship.mapper.entity
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import six
|
import six
|
||||||
from graphql.core.type import GraphQLEnumType, GraphQLEnumValue
|
from graphql.core.type import GraphQLEnumType, GraphQLEnumValue
|
||||||
|
|
||||||
|
from .base import ClassTypeMeta, ClassType
|
||||||
|
from ..types.base import MountedType
|
||||||
from ...utils.enum import Enum as PyEnum
|
from ...utils.enum import Enum as PyEnum
|
||||||
from .base import ClassType, ClassTypeMeta
|
|
||||||
|
|
||||||
|
|
||||||
class EnumMeta(ClassTypeMeta):
|
class EnumMeta(ClassTypeMeta):
|
||||||
|
@ -17,7 +18,12 @@ class EnumMeta(ClassTypeMeta):
|
||||||
attrs[k] = v.value
|
attrs[k] = v.value
|
||||||
return super(EnumMeta, cls).construct(bases, attrs)
|
return super(EnumMeta, cls).construct(bases, attrs)
|
||||||
|
|
||||||
def __call__(cls, name, names=None, description=None):
|
def __call__(cls, *args, **kwargs):
|
||||||
|
if cls is Enum:
|
||||||
|
return cls.create_enum(*args, **kwargs)
|
||||||
|
return super(EnumMeta, cls).__call__(*args, **kwargs)
|
||||||
|
|
||||||
|
def create_enum(cls, name, names=None, description=None):
|
||||||
attrs = {
|
attrs = {
|
||||||
'__enum__': PyEnum(name, names)
|
'__enum__': PyEnum(name, names)
|
||||||
}
|
}
|
||||||
|
@ -26,7 +32,7 @@ class EnumMeta(ClassTypeMeta):
|
||||||
return type(name, (Enum,), attrs)
|
return type(name, (Enum,), attrs)
|
||||||
|
|
||||||
|
|
||||||
class Enum(six.with_metaclass(EnumMeta, ClassType)):
|
class Enum(six.with_metaclass(EnumMeta, ClassType, MountedType)):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
|
@ -3,6 +3,7 @@ from graphql.core.type import GraphQLEnumType
|
||||||
from graphene.core.schema import Schema
|
from graphene.core.schema import Schema
|
||||||
|
|
||||||
from ..enum import Enum
|
from ..enum import Enum
|
||||||
|
from ..objecttype import ObjectType
|
||||||
|
|
||||||
|
|
||||||
def test_enum():
|
def test_enum():
|
||||||
|
@ -35,3 +36,14 @@ def test_enum_values():
|
||||||
assert RGB.RED == 0
|
assert RGB.RED == 0
|
||||||
assert RGB.GREEN == 1
|
assert RGB.GREEN == 1
|
||||||
assert RGB.BLUE == 2
|
assert RGB.BLUE == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_enum_instance():
|
||||||
|
RGB = Enum('RGB', dict(RED=0, GREEN=1, BLUE=2))
|
||||||
|
RGB_field = RGB(description='RGB enum description')
|
||||||
|
|
||||||
|
class ObjectWithColor(ObjectType):
|
||||||
|
color = RGB_field
|
||||||
|
|
||||||
|
object_field = ObjectWithColor._meta.fields_map['color']
|
||||||
|
assert object_field.description == 'RGB enum description'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from .str_converters import to_camel_case, to_snake_case
|
from .str_converters import to_camel_case, to_snake_case, to_const
|
||||||
from .proxy_snake_dict import ProxySnakeDict
|
from .proxy_snake_dict import ProxySnakeDict
|
||||||
from .caching import cached_property, memoize
|
from .caching import cached_property, memoize
|
||||||
from .maybe_func import maybe_func
|
from .maybe_func import maybe_func
|
||||||
|
@ -7,6 +7,6 @@ from .resolve_only_args import resolve_only_args
|
||||||
from .lazylist import LazyList
|
from .lazylist import LazyList
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['to_camel_case', 'to_snake_case', 'ProxySnakeDict',
|
__all__ = ['to_camel_case', 'to_snake_case', 'to_const', 'ProxySnakeDict',
|
||||||
'cached_property', 'memoize', 'maybe_func', 'enum_to_graphql_enum',
|
'cached_property', 'memoize', 'maybe_func', 'enum_to_graphql_enum',
|
||||||
'resolve_only_args', 'LazyList']
|
'resolve_only_args', 'LazyList']
|
||||||
|
|
|
@ -15,3 +15,7 @@ def to_camel_case(snake_str):
|
||||||
def to_snake_case(name):
|
def to_snake_case(name):
|
||||||
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
|
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
|
||||||
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
||||||
|
|
||||||
|
|
||||||
|
def to_const(string):
|
||||||
|
return re.sub('[\W|^(?=\d)]+', '_', string).upper()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from ..str_converters import to_camel_case, to_snake_case
|
# coding: utf-8
|
||||||
|
from ..str_converters import to_camel_case, to_snake_case, to_const
|
||||||
|
|
||||||
|
|
||||||
def test_snake_case():
|
def test_snake_case():
|
||||||
|
@ -15,3 +16,7 @@ def test_camel_case():
|
||||||
assert to_camel_case('snakes_on_a_plane') == 'snakesOnAPlane'
|
assert to_camel_case('snakes_on_a_plane') == 'snakesOnAPlane'
|
||||||
assert to_camel_case('snakes_on_a__plane') == 'snakesOnA_Plane'
|
assert to_camel_case('snakes_on_a__plane') == 'snakesOnA_Plane'
|
||||||
assert to_camel_case('i_phone_hysteria') == 'iPhoneHysteria'
|
assert to_camel_case('i_phone_hysteria') == 'iPhoneHysteria'
|
||||||
|
|
||||||
|
|
||||||
|
def test_to_const():
|
||||||
|
assert to_const('snakes $1. on a "#plane') == 'SNAKES_ON_A_PLANE'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user