Skip to content

Commit 5d33b93

Browse files
authored
Merge pull request #206 from alainburindi/add-django5-support
add Django 5 support
2 parents 209ae49 + c4f77d7 commit 5d33b93

26 files changed

+1080
-559
lines changed

.flake8

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ ignore = E203, E266, E501, W503
55
max-line-length = 80
66
max-complexity = 18
77
select = B,C,E,F,W,T4,B9
8+
exclude =
9+
.venv
10+
.tox
11+
dist

.github/workflows/cicd.yaml

+18-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ jobs:
1010
strategy:
1111
matrix:
1212
include:
13-
- python: 3.7
14-
django: 3.2
15-
toxenv: py37-django32
1613
- python: 3.8
1714
django: 3.2
1815
toxenv: py38-django32
@@ -37,6 +34,24 @@ jobs:
3734
- python: '3.10'
3835
django: 4.1
3936
toxenv: py310-django41
37+
- python: '3.10'
38+
django: 5.0
39+
toxenv: py310-django50
40+
- python: '3.11'
41+
django: 5.0
42+
toxenv: py311-django50
43+
- python: '3.12'
44+
django: 5.0
45+
toxenv: py312-django50
46+
- python: '3.10'
47+
django: 5.1
48+
toxenv: py310-django51
49+
- python: '3.11'
50+
django: 5.1
51+
toxenv: py311-django51
52+
- python: '3.12'
53+
django: 5.1
54+
toxenv: py312-django51
4055
steps:
4156
- uses: actions/checkout@v2
4257
- uses: actions/setup-python@v1

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ __pycache__
1818
.coverage*
1919
.tox/
2020
.pytest*/
21+
22+
.DS_Store
23+
24+
.venv/

graphene_django_extras/base_types.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ def serialize(time):
154154
if isinstance(time, datetime.datetime):
155155
time = time.time()
156156

157-
assert isinstance(time, datetime.time), 'Received not compatible time "{}"'.format(
158-
repr(time)
159-
)
157+
assert isinstance(
158+
time, datetime.time
159+
), 'Received not compatible time "{}"'.format(repr(time))
160160
return time.isoformat()
161161

162162

@@ -168,9 +168,9 @@ def serialize(date):
168168

169169
if isinstance(date, datetime.datetime):
170170
date = date.date()
171-
assert isinstance(date, datetime.date), 'Received not compatible date "{}"'.format(
172-
repr(date)
173-
)
171+
assert isinstance(
172+
date, datetime.date
173+
), 'Received not compatible date "{}"'.format(repr(date))
174174
return date.isoformat()
175175

176176

graphene_django_extras/converter.py

+66-20
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,26 @@
44
from functools import singledispatch
55

66
from django.conf import settings
7-
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRel, GenericRelation
7+
from django.contrib.contenttypes.fields import (
8+
GenericForeignKey,
9+
GenericRel,
10+
GenericRelation,
11+
)
812
from django.db import models
913
from django.utils.encoding import force_str
10-
from graphene import ID, UUID, Boolean, Dynamic, Enum, Field, Float, Int, List, NonNull, String
14+
from graphene import (
15+
ID,
16+
UUID,
17+
Boolean,
18+
Dynamic,
19+
Enum,
20+
Field,
21+
Float,
22+
Int,
23+
List,
24+
NonNull,
25+
String,
26+
)
1127
from graphene.types.json import JSONString
1228
from graphene.utils.str_converters import to_camel_case
1329
from graphene_django.compat import ArrayField, HStoreField, JSONField, RangeField
@@ -30,9 +46,9 @@
3046

3147
def assert_valid_name(name):
3248
"""Helper to assert that provided names are valid."""
33-
assert COMPILED_NAME_PATTERN.match(name), 'Names must match /{}/ but "{}" does not.'.format(
34-
NAME_PATTERN, name
35-
)
49+
assert COMPILED_NAME_PATTERN.match(
50+
name
51+
), 'Names must match /{}/ but "{}" does not.'.format(NAME_PATTERN, name)
3652

3753

3854
def convert_choice_name(name):
@@ -59,7 +75,9 @@ def get_choices(choices):
5975
yield name, value, description
6076

6177

62-
def convert_django_field_with_choices(field, registry=None, input_flag=None, nested_field=False):
78+
def convert_django_field_with_choices(
79+
field, registry=None, input_flag=None, nested_field=False
80+
):
6381
choices = getattr(field, "choices", None)
6482
if choices:
6583
meta = field.model._meta
@@ -109,14 +127,18 @@ def construct_fields(
109127

110128
if settings.DEBUG:
111129
if input_flag == "create":
112-
_model_fields = sorted(_model_fields, key=lambda f: (not is_required(f[1]), f[0]))
130+
_model_fields = sorted(
131+
_model_fields, key=lambda f: (not is_required(f[1]), f[0])
132+
)
113133
elif not input_flag:
114134
_model_fields = sorted(_model_fields, key=lambda f: f[0])
115135

116136
fields = OrderedDict()
117137

118138
if input_flag == "delete":
119-
converted = convert_django_field_with_choices(dict(_model_fields)["id"], registry)
139+
converted = convert_django_field_with_choices(
140+
dict(_model_fields)["id"], registry
141+
)
120142
fields["id"] = converted
121143
else:
122144
for name, field in _model_fields:
@@ -126,7 +148,9 @@ def construct_fields(
126148
nested_field = name in nested_fields
127149
is_not_in_only = only_fields and name not in only_fields
128150
# is_already_created = name in options.fields
129-
is_excluded = exclude_fields and name in exclude_fields # or is_already_created
151+
is_excluded = (
152+
exclude_fields and name in exclude_fields
153+
) # or is_already_created
130154
# https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_query_name
131155
is_no_backref = str(name).endswith("+")
132156
# if is_not_in_only or is_excluded or is_no_backref:
@@ -144,15 +168,19 @@ def construct_fields(
144168
):
145169
continue
146170

147-
converted = convert_django_field_with_choices(field, registry, input_flag, nested_field)
171+
converted = convert_django_field_with_choices(
172+
field, registry, input_flag, nested_field
173+
)
148174
fields[name] = converted
149175
return fields
150176

151177

152178
@singledispatch
153179
def convert_django_field(field, registry=None, input_flag=None, nested_field=False):
154180
raise Exception(
155-
"Don't know how to convert the Django field {} ({})".format(field, field.__class__)
181+
"Don't know how to convert the Django field {} ({})".format(
182+
field, field.__class__
183+
)
156184
)
157185

158186

@@ -212,7 +240,9 @@ def convert_field_to_boolean(field, registry=None, input_flag=None, nested_field
212240

213241

214242
@convert_django_field.register(models.NullBooleanField)
215-
def convert_field_to_nullboolean(field, registry=None, input_flag=None, nested_field=False):
243+
def convert_field_to_nullboolean(
244+
field, registry=None, input_flag=None, nested_field=False
245+
):
216246
return Boolean(
217247
description=field.help_text or field.verbose_name,
218248
required=is_required(field) and input_flag == "create",
@@ -246,7 +276,9 @@ def convert_date_to_string(field, registry=None, input_flag=None, nested_field=F
246276

247277

248278
@convert_django_field.register(models.DateTimeField)
249-
def convert_datetime_to_string(field, registry=None, input_flag=None, nested_field=False):
279+
def convert_datetime_to_string(
280+
field, registry=None, input_flag=None, nested_field=False
281+
):
250282
return CustomDateTime(
251283
description=field.help_text or field.verbose_name,
252284
required=is_required(field) and input_flag == "create",
@@ -279,7 +311,9 @@ def dynamic_type():
279311

280312

281313
@convert_django_field.register(models.ManyToManyField)
282-
def convert_field_to_list_or_connection(field, registry=None, input_flag=None, nested_field=False):
314+
def convert_field_to_list_or_connection(
315+
field, registry=None, input_flag=None, nested_field=False
316+
):
283317
model = get_related_model(field)
284318

285319
def dynamic_type():
@@ -315,7 +349,9 @@ def dynamic_type():
315349
@convert_django_field.register(GenericRel)
316350
@convert_django_field.register(models.ManyToManyRel)
317351
@convert_django_field.register(models.ManyToOneRel)
318-
def convert_many_rel_to_djangomodel(field, registry=None, input_flag=None, nested_field=False):
352+
def convert_many_rel_to_djangomodel(
353+
field, registry=None, input_flag=None, nested_field=False
354+
):
319355
model = field.related_model
320356

321357
def dynamic_type():
@@ -343,12 +379,16 @@ def dynamic_type():
343379

344380
@convert_django_field.register(models.OneToOneField)
345381
@convert_django_field.register(models.ForeignKey)
346-
def convert_field_to_djangomodel(field, registry=None, input_flag=None, nested_field=False):
382+
def convert_field_to_djangomodel(
383+
field, registry=None, input_flag=None, nested_field=False
384+
):
347385
model = get_related_model(field)
348386

349387
def dynamic_type():
350388
# Avoid create field for auto generate OneToOneField product of an inheritance
351-
if isinstance(field, models.OneToOneField) and issubclass(field.model, field.related_model):
389+
if isinstance(field, models.OneToOneField) and issubclass(
390+
field.model, field.related_model
391+
):
352392
return
353393
if input_flag and not nested_field:
354394
return ID(
@@ -433,7 +473,9 @@ def dynamic_type():
433473

434474

435475
@convert_django_field.register(ArrayField)
436-
def convert_postgres_array_to_list(field, registry=None, input_flag=None, nested_field=False):
476+
def convert_postgres_array_to_list(
477+
field, registry=None, input_flag=None, nested_field=False
478+
):
437479
base_type = convert_django_field(field.base_field)
438480
if not isinstance(base_type, (List, NonNull)):
439481
base_type = type(base_type)
@@ -446,15 +488,19 @@ def convert_postgres_array_to_list(field, registry=None, input_flag=None, nested
446488

447489
@convert_django_field.register(HStoreField)
448490
@convert_django_field.register(JSONField)
449-
def convert_postgres_field_to_string(field, registry=None, input_flag=None, nested_field=False):
491+
def convert_postgres_field_to_string(
492+
field, registry=None, input_flag=None, nested_field=False
493+
):
450494
return JSONString(
451495
description=field.help_text or field.verbose_name,
452496
required=is_required(field) and input_flag == "create",
453497
)
454498

455499

456500
@convert_django_field.register(RangeField)
457-
def convert_postgres_range_to_string(field, registry=None, input_flag=None, nested_field=False):
501+
def convert_postgres_range_to_string(
502+
field, registry=None, input_flag=None, nested_field=False
503+
):
458504
inner_type = convert_django_field(field.base_field)
459505
if not isinstance(inner_type, (List, NonNull)):
460506
inner_type = type(inner_type)

graphene_django_extras/directives/date.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ def _format_relativedelta(rdelta, full=False, two_days=False, original_dt=None):
140140
def _format_time_ago(dt, now=None, full=False, ago_in=False, two_days=False):
141141
if not isinstance(dt, timedelta):
142142
if now is None:
143-
now = timezone.localtime(timezone=timezone.get_fixed_timezone(-int(t.timezone / 60)))
143+
now = timezone.localtime(
144+
timezone=timezone.get_fixed_timezone(-int(t.timezone / 60))
145+
)
144146

145147
original_dt = dt
146148
dt = _parse(dt)
@@ -201,7 +203,9 @@ def _format_dt(dt, format="default"):
201203
else:
202204
if temp_format != "":
203205
if temp_format in FORMATS_MAP:
204-
translate_format_list.append(FORMATS_MAP.get(temp_format, ""))
206+
translate_format_list.append(
207+
FORMATS_MAP.get(temp_format, "")
208+
)
205209
else:
206210
return None
207211
if str_in_dict_keys(char, FORMATS_MAP):
@@ -236,7 +240,9 @@ def get_args():
236240

237241
@staticmethod
238242
def resolve(value, directive, root, info, **kwargs):
239-
format_argument = [arg for arg in directive.arguments if arg.name.value == "format"]
243+
format_argument = [
244+
arg for arg in directive.arguments if arg.name.value == "format"
245+
]
240246
format_argument = format_argument[0] if len(format_argument) > 0 else None
241247

242248
custom_format = format_argument.value.value if format_argument else "default"

graphene_django_extras/directives/list.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ def resolve(value, directive, root, info, **kwargs):
2424
class SampleGraphQLDirective(BaseExtraGraphQLDirective):
2525
@staticmethod
2626
def get_args():
27-
return {"k": GraphQLArgument(GraphQLNonNull(GraphQLInt), description="Value to default to")}
27+
return {
28+
"k": GraphQLArgument(
29+
GraphQLNonNull(GraphQLInt), description="Value to default to"
30+
)
31+
}
2832

2933
@staticmethod
3034
def resolve(value, directive, root, info, **kwargs):

0 commit comments

Comments
 (0)