diff --git a/.travis.yml b/.travis.yml
index bbeeb80e0..f1ca20128 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,10 +5,10 @@ dist: xenial
install:
- pip install tox tox-travis
-script:
+script:
- tox
-after_success:
+after_success:
- pip install coveralls
- coveralls
@@ -24,24 +24,8 @@ jobs:
- env: DJANGO=master
include:
- - python: 2.7
- env: DJANGO=1.11
-
- - python: 3.5
- env: DJANGO=1.11
- - python: 3.5
- env: DJANGO=2.0
- - python: 3.5
- env: DJANGO=2.1
- - python: 3.5
- env: DJANGO=2.2
-
- python: 3.6
env: DJANGO=1.11
- - python: 3.6
- env: DJANGO=2.0
- - python: 3.6
- env: DJANGO=2.1
- python: 3.6
env: DJANGO=2.2
- python: 3.6
@@ -51,10 +35,6 @@ jobs:
- python: 3.7
env: DJANGO=1.11
- - python: 3.7
- env: DJANGO=2.0
- - python: 3.7
- env: DJANGO=2.1
- python: 3.7
env: DJANGO=2.2
- python: 3.7
@@ -62,12 +42,21 @@ jobs:
- python: 3.7
env: DJANGO=master
- - python: 3.7
+ - python: 3.8
+ env: DJANGO=1.11
+ - python: 3.8
+ env: DJANGO=2.2
+ - python: 3.8
+ env: DJANGO=3.0
+ - python: 3.8
+ env: DJANGO=master
+
+ - python: 3.8
env: TOXENV=black,flake8
- stage: deploy
script: skip
- python: 3.7
+ python: 3.8
after_success: true
deploy:
provider: pypi
diff --git a/docs/authorization.rst b/docs/authorization.rst
index 63123b0b4..7e09c3781 100644
--- a/docs/authorization.rst
+++ b/docs/authorization.rst
@@ -184,4 +184,4 @@ For Django 2.0 and above:
path('graphql', PrivateGraphQLView.as_view(graphiql=True, schema=schema)),
]
-.. _LoginRequiredMixin: https://docs.djangoproject.com/en/1.10/topics/auth/default/#the-loginrequired-mixin
+.. _LoginRequiredMixin: https://docs.djangoproject.com/en/dev/topics/auth/default/#the-loginrequired-mixin
diff --git a/docs/conf.py b/docs/conf.py
index a485d5be7..b83e0f061 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -60,18 +60,18 @@
master_doc = "index"
# General information about the project.
-project = u"Graphene Django"
-copyright = u"Graphene 2017"
-author = u"Syrus Akbary"
+project = "Graphene Django"
+copyright = "Graphene 2017"
+author = "Syrus Akbary"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = u"1.0"
+version = "1.0"
# The full version, including alpha/beta/rc tags.
-release = u"1.0.dev"
+release = "1.0.dev"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -276,7 +276,7 @@
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, "Graphene.tex", u"Graphene Documentation", u"Syrus Akbary", "manual")
+ (master_doc, "Graphene.tex", "Graphene Documentation", "Syrus Akbary", "manual")
]
# The name of an image file (relative to this directory) to place at the top of
@@ -317,7 +317,7 @@
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
- (master_doc, "graphene_django", u"Graphene Django Documentation", [author], 1)
+ (master_doc, "graphene_django", "Graphene Django Documentation", [author], 1)
]
# If true, show URL addresses after external links.
@@ -334,7 +334,7 @@
(
master_doc,
"Graphene-Django",
- u"Graphene Django Documentation",
+ "Graphene Django Documentation",
author,
"Graphene Django",
"One line description of project.",
diff --git a/docs/filtering.rst b/docs/filtering.rst
index 6fe7cabaa..fb737446d 100644
--- a/docs/filtering.rst
+++ b/docs/filtering.rst
@@ -2,8 +2,7 @@ Filtering
=========
Graphene integrates with
-`django-filter `__ (2.x for
-Python 3 or 1.x for Python 2) to provide filtering of results. See the `usage
+`django-filter `__ to provide filtering of results. See the `usage
documentation `__
for details on the format for ``filter_fields``.
diff --git a/graphene_django/converter.py b/graphene_django/converter.py
index bd8f79d03..36116ed5a 100644
--- a/graphene_django/converter.py
+++ b/graphene_django/converter.py
@@ -1,4 +1,6 @@
from collections import OrderedDict
+from functools import singledispatch
+
from django.db import models
from django.utils.encoding import force_str
from django.utils.module_loading import import_string
@@ -26,9 +28,6 @@
from .settings import graphene_settings
from .compat import ArrayField, HStoreField, JSONField, RangeField
from .fields import DjangoListField, DjangoConnectionField
-from .utils import import_single_dispatch
-
-singledispatch = import_single_dispatch()
def convert_choice_name(name):
diff --git a/graphene_django/debug/sql/tracking.py b/graphene_django/debug/sql/tracking.py
index a7c9d8db0..aacd1a01c 100644
--- a/graphene_django/debug/sql/tracking.py
+++ b/graphene_django/debug/sql/tracking.py
@@ -5,7 +5,6 @@
from threading import local
from time import time
-import six
from django.utils.encoding import force_str
from .types import DjangoDebugSQL
@@ -77,7 +76,7 @@ def __init__(self, cursor, db, logger):
self.logger = logger
def _quote_expr(self, element):
- if isinstance(element, six.string_types):
+ if isinstance(element, str):
return "'%s'" % force_str(element).replace("'", "''")
else:
return repr(element)
diff --git a/graphene_django/fields.py b/graphene_django/fields.py
index fb6b98a4a..f0a382814 100644
--- a/graphene_django/fields.py
+++ b/graphene_django/fields.py
@@ -1,6 +1,5 @@
from functools import partial
-import six
from django.db.models.query import QuerySet
from graphql_relay.connection.arrayconnection import connection_from_list_slice
from promise import Promise
diff --git a/graphene_django/filter/filterset.py b/graphene_django/filter/filterset.py
index 7676ea85b..34108aea4 100644
--- a/graphene_django/filter/filterset.py
+++ b/graphene_django/filter/filterset.py
@@ -1,7 +1,7 @@
import itertools
from django.db import models
-from django_filters import Filter, MultipleChoiceFilter, VERSION
+from django_filters import Filter, MultipleChoiceFilter
from django_filters.filterset import BaseFilterSet, FilterSet
from django_filters.filterset import FILTER_FOR_DBFIELD_DEFAULTS
@@ -50,36 +50,6 @@ class GrapheneFilterSetMixin(BaseFilterSet):
)
-# To support a Django 1.11 + Python 2.7 combination django-filter must be
-# < 2.x.x. To support the earlier version of django-filter, the
-# filter_for_reverse_field method must be present on GrapheneFilterSetMixin and
-# must not be present for later versions of django-filter.
-if VERSION[0] < 2:
- from django.utils.text import capfirst
-
- class GrapheneFilterSetMixinPython2(GrapheneFilterSetMixin):
- @classmethod
- def filter_for_reverse_field(cls, f, name):
- """Handles retrieving filters for reverse relationships
- We override the default implementation so that we can handle
- Global IDs (the default implementation expects database
- primary keys)
- """
- try:
- rel = f.field.remote_field
- except AttributeError:
- rel = f.field.rel
- default = {"name": name, "label": capfirst(rel.related_name)}
- if rel.multiple:
- # For to-many relationships
- return GlobalIDMultipleChoiceFilter(**default)
- else:
- # For to-one relationships
- return GlobalIDFilter(**default)
-
- GrapheneFilterSetMixin = GrapheneFilterSetMixinPython2
-
-
def setup_filterset(filterset_class):
""" Wrap a provided filterset in Graphene-specific functionality
"""
diff --git a/graphene_django/filter/utils.py b/graphene_django/filter/utils.py
index c5f18e29c..ea4f8dc60 100644
--- a/graphene_django/filter/utils.py
+++ b/graphene_django/filter/utils.py
@@ -1,5 +1,3 @@
-import six
-
from django_filters.utils import get_model_field
from .filterset import custom_filterset_factory, setup_filterset
@@ -13,7 +11,7 @@ def get_filtering_args_from_filterset(filterset_class, type):
args = {}
model = filterset_class._meta.model
- for name, filter_field in six.iteritems(filterset_class.base_filters):
+ for name, filter_field in filterset_class.base_filters.items():
form_field = None
if name in filterset_class.declared_filters:
diff --git a/graphene_django/forms/converter.py b/graphene_django/forms/converter.py
index 891645618..7b154b4ca 100644
--- a/graphene_django/forms/converter.py
+++ b/graphene_django/forms/converter.py
@@ -1,13 +1,11 @@
+from functools import singledispatch
+
from django import forms
from django.core.exceptions import ImproperlyConfigured
from graphene import ID, Boolean, Float, Int, List, String, UUID, Date, DateTime, Time
from .forms import GlobalIDFormField, GlobalIDMultipleChoiceField
-from ..utils import import_single_dispatch
-
-
-singledispatch = import_single_dispatch()
@singledispatch
diff --git a/graphene_django/rest_framework/serializer_converter.py b/graphene_django/rest_framework/serializer_converter.py
index 82a113a29..b26e5e67e 100644
--- a/graphene_django/rest_framework/serializer_converter.py
+++ b/graphene_django/rest_framework/serializer_converter.py
@@ -1,3 +1,5 @@
+from functools import singledispatch
+
from django.core.exceptions import ImproperlyConfigured
from rest_framework import serializers
@@ -5,11 +7,8 @@
from ..registry import get_global_registry
from ..converter import convert_choices_to_named_enum_with_descriptions
-from ..utils import import_single_dispatch
from .types import DictType
-singledispatch = import_single_dispatch()
-
@singledispatch
def get_graphene_type_from_serializer_field(field):
diff --git a/graphene_django/settings.py b/graphene_django/settings.py
index 666ad8a14..07cbba1ec 100644
--- a/graphene_django/settings.py
+++ b/graphene_django/settings.py
@@ -13,7 +13,6 @@
"""
from __future__ import unicode_literals
-import six
from django.conf import settings
from django.test.signals import setting_changed
@@ -55,7 +54,7 @@ def perform_import(val, setting_name):
"""
if val is None:
return None
- elif isinstance(val, six.string_types):
+ elif isinstance(val, str):
return import_from_string(val, setting_name)
elif isinstance(val, (list, tuple)):
return [import_from_string(item, setting_name) for item in val]
diff --git a/graphene_django/tests/models.py b/graphene_django/tests/models.py
index 44a5d8a5c..708fe579a 100644
--- a/graphene_django/tests/models.py
+++ b/graphene_django/tests/models.py
@@ -1,7 +1,7 @@
from __future__ import absolute_import
from django.db import models
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
CHOICES = ((1, "this"), (2, _("that")))
@@ -46,7 +46,7 @@ class Reporter(models.Model):
"Reporter Type",
null=True,
blank=True,
- choices=[(1, u"Regular"), (2, u"CNN Reporter")],
+ choices=[(1, "Regular"), (2, "CNN Reporter")],
)
def __str__(self): # __unicode__ on Python 2
@@ -105,7 +105,7 @@ class Article(models.Model):
"Importance",
null=True,
blank=True,
- choices=[(1, u"Very important"), (2, u"Not as important")],
+ choices=[(1, "Very important"), (2, "Not as important")],
)
def __str__(self): # __unicode__ on Python 2
diff --git a/graphene_django/tests/test_command.py b/graphene_django/tests/test_command.py
index 8b0a8e6a0..6dfe330a6 100644
--- a/graphene_django/tests/test_command.py
+++ b/graphene_django/tests/test_command.py
@@ -1,8 +1,8 @@
from textwrap import dedent
from django.core import management
+from io import StringIO
from mock import mock_open, patch
-from six import StringIO
from graphene import ObjectType, Schema, String
diff --git a/graphene_django/tests/test_converter.py b/graphene_django/tests/test_converter.py
index 7f84de3ae..f1d1b9bb0 100644
--- a/graphene_django/tests/test_converter.py
+++ b/graphene_django/tests/test_converter.py
@@ -1,7 +1,7 @@
import pytest
from collections import namedtuple
from django.db import models
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from graphene import NonNull
from py.test import raises
diff --git a/graphene_django/types.py b/graphene_django/types.py
index 0c0cb1cf5..9bb47b992 100644
--- a/graphene_django/types.py
+++ b/graphene_django/types.py
@@ -1,7 +1,7 @@
import warnings
from collections import OrderedDict
+from typing import Type
-import six
from django.db.models import Model
from django.utils.functional import SimpleLazyObject
@@ -21,9 +21,6 @@
is_valid_django_model,
)
-if six.PY3:
- from typing import Type
-
ALL_FIELDS = "__all__"
diff --git a/graphene_django/utils/__init__.py b/graphene_django/utils/__init__.py
index 9d8658b1f..671b0609a 100644
--- a/graphene_django/utils/__init__.py
+++ b/graphene_django/utils/__init__.py
@@ -4,7 +4,6 @@
camelize,
get_model_fields,
get_reverse_fields,
- import_single_dispatch,
is_valid_django_model,
maybe_queryset,
)
@@ -16,6 +15,5 @@
"get_model_fields",
"camelize",
"is_valid_django_model",
- "import_single_dispatch",
"GraphQLTestCase",
]
diff --git a/graphene_django/utils/utils.py b/graphene_django/utils/utils.py
index c1d3572f0..c5ea85bf5 100644
--- a/graphene_django/utils/utils.py
+++ b/graphene_django/utils/utils.py
@@ -1,9 +1,8 @@
import inspect
-import six
from django.db import models
from django.db.models.manager import Manager
-from django.utils.encoding import force_text
+from django.utils.encoding import force_str
from django.utils.functional import Promise
from graphene.utils.str_converters import to_camel_case
@@ -26,14 +25,14 @@ def isiterable(value):
def _camelize_django_str(s):
if isinstance(s, Promise):
- s = force_text(s)
- return to_camel_case(s) if isinstance(s, six.string_types) else s
+ s = force_str(s)
+ return to_camel_case(s) if isinstance(s, str) else s
def camelize(data):
if isinstance(data, dict):
return {_camelize_django_str(k): camelize(v) for k, v in data.items()}
- if isiterable(data) and not isinstance(data, (six.string_types, Promise)):
+ if isiterable(data) and not isinstance(data, (str, Promise)):
return [camelize(d) for d in data]
return data
@@ -77,26 +76,3 @@ def get_model_fields(model):
def is_valid_django_model(model):
return inspect.isclass(model) and issubclass(model, models.Model)
-
-
-def import_single_dispatch():
- try:
- from functools import singledispatch
- except ImportError:
- singledispatch = None
-
- if not singledispatch:
- try:
- from singledispatch import singledispatch
- except ImportError:
- pass
-
- if not singledispatch:
- raise Exception(
- "It seems your python version does not include "
- "functools.singledispatch. Please install the 'singledispatch' "
- "package. More information here: "
- "https://pypi.python.org/pypi/singledispatch"
- )
-
- return singledispatch
diff --git a/graphene_django/views.py b/graphene_django/views.py
index 4c58839ef..8d57d5088 100644
--- a/graphene_django/views.py
+++ b/graphene_django/views.py
@@ -2,7 +2,6 @@
import json
import re
-import six
from django.http import HttpResponse, HttpResponseNotAllowed
from django.http.response import HttpResponseBadRequest
from django.shortcuts import render
@@ -314,7 +313,7 @@ def get_graphql_params(request, data):
variables = request.GET.get("variables") or data.get("variables")
id = request.GET.get("id") or data.get("id")
- if variables and isinstance(variables, six.text_type):
+ if variables and isinstance(variables, str):
try:
variables = json.loads(variables)
except Exception:
@@ -331,7 +330,7 @@ def format_error(error):
if isinstance(error, GraphQLError):
return format_graphql_error(error)
- return {"message": six.text_type(error)}
+ return {"message": str(error)}
@staticmethod
def get_content_type(request):
diff --git a/setup.py b/setup.py
index 560549a9d..3639fb147 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,4 @@
from setuptools import find_packages, setup
-import sys
import ast
import re
@@ -19,8 +18,7 @@
"coveralls",
"mock",
"pytz",
- "django-filter<2;python_version<'3'",
- "django-filter>=2;python_version>='3'",
+ "django-filter>=2",
"pytest-django>=3.3.2",
] + rest_framework_require
@@ -45,22 +43,18 @@
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
- "Programming Language :: Python :: 2",
- "Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.4",
- "Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: Implementation :: PyPy",
],
keywords="api graphql protocol rest relay graphene",
packages=find_packages(exclude=["tests"]),
install_requires=[
- "six>=1.10.0",
"graphene>=2.1.7,<3",
"graphql-core>=2.1.0,<3",
- "Django>=1.11",
- "singledispatch>=3.4.0.3",
+ "Django>=1.11,!=2.0.*,!=2.1.*",
"promise>=2.1",
],
setup_requires=["pytest-runner"],
diff --git a/tox.ini b/tox.ini
index e7287ffb9..9354bdb17 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,14 +1,11 @@
[tox]
envlist =
- py{27,35,36,37}-django{111,20,21,22,master},
- py{36,37}-django30,
+ py{36,37,38}-django{111,django22,django30,master},
black,flake8
[travis:env]
DJANGO =
1.11: django111
- 2.0: django20
- 2.1: django21
2.2: django22
3.0: django30
master: djangomaster
@@ -20,23 +17,21 @@ setenv =
DJANGO_SETTINGS_MODULE=django_test_settings
deps =
-e.[test]
- psycopg2
+ psycopg2-binary
django111: Django>=1.11,<2.0
- django20: Django>=2.0,<2.1
- django21: Django>=2.1,<2.2
django22: Django>=2.2,<3.0
django30: Django>=3.0a1,<3.1
djangomaster: https://github.com/django/django/archive/master.zip
commands = {posargs:py.test --cov=graphene_django graphene_django examples}
[testenv:black]
-basepython = python3.7
+basepython = python3.8
deps = -e.[dev]
commands =
black --exclude "/migrations/" graphene_django examples setup.py --check
[testenv:flake8]
-basepython = python3.7
+basepython = python3.8
deps = -e.[dev]
commands =
flake8 graphene_django examples