Skip to content

Commit 442b94b

Browse files
committed
Add sort enum cache to avoid name clash.
1 parent bead50a commit 442b94b

File tree

4 files changed

+25
-16
lines changed

4 files changed

+25
-16
lines changed

examples/flask_sqlalchemy/schema.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ class Meta:
3434

3535
class Query(graphene.ObjectType):
3636
node = relay.Node.Field()
37-
# Supports sorting only over one field
37+
# Allow only single column sorting
3838
all_employees = SQLAlchemyConnectionField(Employee, sort=graphene.Argument(SortEnumEmployee,
3939
default_value=utils.EnumValue('id_asc', EmployeeModel.id.asc())))
40-
# Add sort over multiple fields, sorting by default over the primary key
40+
# Add sort over multiple columns, sorting by default over the primary key
4141
all_roles = SQLAlchemyConnectionField(Role)
4242
# Disable sorting over this field
4343
all_departments = SQLAlchemyConnectionField(Department, sort=None)

graphene_sqlalchemy/fields.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from .utils import get_query, sort_argument_for_model
1010

1111

12-
class _UnsortedSQLAlchemyConnectionField(ConnectionField):
12+
class UnsortedSQLAlchemyConnectionField(ConnectionField):
1313

1414
@property
1515
def model(self):
@@ -20,9 +20,9 @@ def get_query(cls, model, info, sort=None, **args):
2020
query = get_query(model, info.context)
2121
if sort is not None:
2222
if isinstance(sort, str):
23-
query = query.order_by(sort.order)
23+
query = query.order_by(sort.value)
2424
else:
25-
query = query.order_by(*(value.order for value in sort))
25+
query = query.order_by(*(col.value for col in sort))
2626
return query
2727

2828
@property
@@ -62,7 +62,7 @@ def get_resolver(self, parent_resolver):
6262
return partial(self.connection_resolver, parent_resolver, self.type, self.model)
6363

6464

65-
class SQLAlchemyConnectionField(_UnsortedSQLAlchemyConnectionField):
65+
class SQLAlchemyConnectionField(UnsortedSQLAlchemyConnectionField):
6666

6767
def __init__(self, type, *args, **kwargs):
6868
if 'sort' not in kwargs:
@@ -72,7 +72,7 @@ def __init__(self, type, *args, **kwargs):
7272
super(SQLAlchemyConnectionField, self).__init__(type, *args, **kwargs)
7373

7474

75-
__connectionFactory = _UnsortedSQLAlchemyConnectionField
75+
__connectionFactory = UnsortedSQLAlchemyConnectionField
7676

7777

7878
def createConnectionField(_type):
@@ -86,4 +86,4 @@ def registerConnectionFieldFactory(factoryMethod):
8686

8787
def unregisterConnectionFieldFactory():
8888
global __connectionFactory
89-
__connectionFactory = _UnsortedSQLAlchemyConnectionField
89+
__connectionFactory = UnsortedSQLAlchemyConnectionField

graphene_sqlalchemy/tests/test_converter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from ..converter import (convert_sqlalchemy_column,
1717
convert_sqlalchemy_composite,
1818
convert_sqlalchemy_relationship)
19-
from ..fields import _UnsortedSQLAlchemyConnectionField
19+
from ..fields import UnsortedSQLAlchemyConnectionField
2020
from ..registry import Registry
2121
from ..types import SQLAlchemyObjectType
2222
from .models import Article, Pet, Reporter
@@ -205,7 +205,7 @@ class Meta:
205205

206206
dynamic_field = convert_sqlalchemy_relationship(Reporter.pets.property, A._meta.registry)
207207
assert isinstance(dynamic_field, graphene.Dynamic)
208-
assert isinstance(dynamic_field.get_type(), _UnsortedSQLAlchemyConnectionField)
208+
assert isinstance(dynamic_field.get_type(), UnsortedSQLAlchemyConnectionField)
209209

210210

211211
def test_should_manytoone_convert_connectionorlist():

graphene_sqlalchemy/utils.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,24 @@ def _symbol_name(column_name, is_asc):
4343

4444

4545
class EnumValue(str):
46-
'''Subclass of str that stores a string value and the sort order of the column'''
47-
def __new__(cls, str_value, order):
46+
'''Subclass of str that stores a string and an arbitrary value in the "value" property'''
47+
48+
def __new__(cls, str_value, value):
4849
return super(EnumValue, cls).__new__(cls, str_value)
4950

50-
def __init__(self, str_value, order):
51+
def __init__(self, str_value, value):
5152
super(EnumValue, self).__init__()
52-
self.order = order
53+
self.value = value
54+
55+
56+
# Cache for the generated enums, to avoid name clash
57+
_ENUM_CACHE = {}
5358

5459

5560
def _sort_enum_for_model(cls, name=None, symbol_name=_symbol_name):
5661
name = name or cls.__name__ + 'SortEnum'
62+
if name in _ENUM_CACHE:
63+
return _ENUM_CACHE[name]
5764
items = []
5865
default = []
5966
for column in inspect(cls).columns.values():
@@ -64,7 +71,9 @@ def _sort_enum_for_model(cls, name=None, symbol_name=_symbol_name):
6471
if column.primary_key:
6572
default.append(asc_value)
6673
items.extend(((asc_name, asc_value), (desc_name, desc_value)))
67-
return Enum(name, items), default
74+
enum = Enum(name, items)
75+
_ENUM_CACHE[name] = (enum, default)
76+
return enum, default
6877

6978

7079
def sort_enum_for_model(cls, name=None, symbol_name=_symbol_name):
@@ -89,7 +98,7 @@ def sort_enum_for_model(cls, name=None, symbol_name=_symbol_name):
8998

9099

91100
def sort_argument_for_model(cls, has_default=True):
92-
'''Returns an Graphene argument for the sort field that accepts a list of sorting directions for a model.
101+
'''Returns a Graphene argument for the sort field that accepts a list of sorting directions for a model.
93102
If `has_default` is True (the default) it will sort the result by the primary key(s)
94103
'''
95104
enum, default = _sort_enum_for_model(cls)

0 commit comments

Comments
 (0)