Skip to content

Commit

Permalink
Native support for additional Type Converters (#353)
Browse files Browse the repository at this point in the history
* Fields generated from Hybrid Properties & Type hints now support Unions (Union[ObjectType1,OT2] or ObjectType1 | OT2)
* Support for Variant and types.JSON Columns
* BREAKING: Date&Time now convert to their corresponding graphene scalars instead of String.
* BREAKING: PG UUID & sqlalchemy_utils.UUIDType now convert to graphene.UUID instead of graphene.String
* Change: Sort Enums & ChoiceType enums are now generated from Column.key instead of Column.name, see #330

Signed-off-by: Erik Wrede <erikwrede2@gmail.com>
Co-authored-by: Nicolas Delaby <nicolas.delaby@infarm.com>
Co-authored-by: davidcim <david@cimaware.com>
Co-authored-by: Viktor Pegy <xtpvxt@gmail.com>
Co-authored-by: Ian Epperson <ian@epperson.com>
  • Loading branch information
5 people committed Jul 15, 2022
1 parent f16d434 commit a702569
Show file tree
Hide file tree
Showing 10 changed files with 468 additions and 131 deletions.
204 changes: 139 additions & 65 deletions graphene_sqlalchemy/converter.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions graphene_sqlalchemy/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,9 @@ def sort_enum_for_object_type(
column = orm_field.columns[0]
if only_indexed and not (column.primary_key or column.index):
continue
asc_name = get_name(column.name, True)
asc_name = get_name(column.key, True)
asc_value = EnumValue(asc_name, column.asc())
desc_name = get_name(column.name, False)
desc_name = get_name(column.key, False)
desc_value = EnumValue(desc_name, column.desc())
if column.primary_key:
default.append(asc_value)
Expand Down
38 changes: 29 additions & 9 deletions graphene_sqlalchemy/registry.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from collections import defaultdict
from typing import List, Type

from sqlalchemy.types import Enum as SQLAlchemyEnumType

import graphene
from graphene import Enum


Expand All @@ -13,12 +15,13 @@ def __init__(self):
self._registry_composites = {}
self._registry_enums = {}
self._registry_sort_enums = {}
self._registry_unions = {}

def register(self, obj_type):
from .types import SQLAlchemyObjectType

from .types import SQLAlchemyObjectType
if not isinstance(obj_type, type) or not issubclass(
obj_type, SQLAlchemyObjectType
obj_type, SQLAlchemyObjectType
):
raise TypeError(
"Expected SQLAlchemyObjectType, but got: {!r}".format(obj_type)
Expand All @@ -37,7 +40,7 @@ def register_orm_field(self, obj_type, field_name, orm_field):
from .types import SQLAlchemyObjectType

if not isinstance(obj_type, type) or not issubclass(
obj_type, SQLAlchemyObjectType
obj_type, SQLAlchemyObjectType
):
raise TypeError(
"Expected SQLAlchemyObjectType, but got: {!r}".format(obj_type)
Expand All @@ -55,7 +58,7 @@ def register_composite_converter(self, composite, converter):
def get_converter_for_composite(self, composite):
return self._registry_composites.get(composite)

def register_enum(self, sa_enum, graphene_enum):
def register_enum(self, sa_enum: SQLAlchemyEnumType, graphene_enum: Enum):
if not isinstance(sa_enum, SQLAlchemyEnumType):
raise TypeError(
"Expected SQLAlchemyEnumType, but got: {!r}".format(sa_enum)
Expand All @@ -67,14 +70,14 @@ def register_enum(self, sa_enum, graphene_enum):

self._registry_enums[sa_enum] = graphene_enum

def get_graphene_enum_for_sa_enum(self, sa_enum):
def get_graphene_enum_for_sa_enum(self, sa_enum: SQLAlchemyEnumType):
return self._registry_enums.get(sa_enum)

def register_sort_enum(self, obj_type, sort_enum):
from .types import SQLAlchemyObjectType
def register_sort_enum(self, obj_type, sort_enum: Enum):

from .types import SQLAlchemyObjectType
if not isinstance(obj_type, type) or not issubclass(
obj_type, SQLAlchemyObjectType
obj_type, SQLAlchemyObjectType
):
raise TypeError(
"Expected SQLAlchemyObjectType, but got: {!r}".format(obj_type)
Expand All @@ -83,9 +86,26 @@ def register_sort_enum(self, obj_type, sort_enum):
raise TypeError("Expected Graphene Enum, but got: {!r}".format(sort_enum))
self._registry_sort_enums[obj_type] = sort_enum

def get_sort_enum_for_object_type(self, obj_type):
def get_sort_enum_for_object_type(self, obj_type: graphene.ObjectType):
return self._registry_sort_enums.get(obj_type)

def register_union_type(self, union: graphene.Union, obj_types: List[Type[graphene.ObjectType]]):
if not isinstance(union, graphene.Union):
raise TypeError(
"Expected graphene.Union, but got: {!r}".format(union)
)

for obj_type in obj_types:
if not isinstance(obj_type, type(graphene.ObjectType)):
raise TypeError(
"Expected Graphene ObjectType, but got: {!r}".format(obj_type)
)

self._registry_unions[frozenset(obj_types)] = union

def get_union_for_object_types(self, obj_types : List[Type[graphene.ObjectType]]):
return self._registry_unions.get(frozenset(obj_types))


registry = None

Expand Down
10 changes: 8 additions & 2 deletions graphene_sqlalchemy/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from decimal import Decimal
from typing import List, Optional, Tuple

from sqlalchemy import (Column, Date, Enum, ForeignKey, Integer, String, Table,
func, select)
from sqlalchemy import (Column, Date, Enum, ForeignKey, Integer, Numeric,
String, Table, func, select)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import column_property, composite, mapper, relationship
Expand Down Expand Up @@ -228,3 +228,9 @@ def hybrid_prop_self_referential_list(self) -> List['ShoppingCart']:
@hybrid_property
def hybrid_prop_optional_self_referential(self) -> Optional['ShoppingCart']:
return None


class KeyedModel(Base):
__tablename__ = "test330"
id = Column(Integer(), primary_key=True)
reporter_number = Column("% reporter_number", Numeric, key="reporter_number")
Loading

0 comments on commit a702569

Please sign in to comment.