From 351a18ba07fba57ca3b2c1c5b098665cbc179ee1 Mon Sep 17 00:00:00 2001 From: ekmartin Date: Sat, 7 Nov 2015 03:54:56 +0100 Subject: [PATCH 1/5] Add tox and run tests for python 2.7/3.5 and Django 1.6-1.8 --- .gitignore | 3 ++- channels/tests/settings.py | 7 +++++++ runtests.py | 15 +++++++++++++++ tox.ini | 16 ++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 channels/tests/settings.py create mode 100644 runtests.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index b8252fc..1c527d5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ dist/ docs/_build __pycache__/ +.tox/ *.swp - +*.pyc diff --git a/channels/tests/settings.py b/channels/tests/settings.py new file mode 100644 index 0000000..e1c7f80 --- /dev/null +++ b/channels/tests/settings.py @@ -0,0 +1,7 @@ +SECRET_KEY = 'cat' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + } +} diff --git a/runtests.py b/runtests.py new file mode 100644 index 0000000..1d60d79 --- /dev/null +++ b/runtests.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +import os +import sys + +import django +from django.conf import settings +from django.test.utils import get_runner + +if __name__ == "__main__": + os.environ['DJANGO_SETTINGS_MODULE'] = "channels.tests.settings" + django.setup() + TestRunner = get_runner(settings) + test_runner = TestRunner() + failures = test_runner.run_tests(["channels.tests"]) + sys.exit(bool(failures)) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..18142eb --- /dev/null +++ b/tox.ini @@ -0,0 +1,16 @@ +[tox] +skipsdist = True +envlist = + {py27,py35}-django-{16,17,18} + +[testenv] +setenv = + PYTHONPATH = {toxinidir}:{toxinidir} +deps = + six + redis==2.10.5 + django-16: Django>=1.6,<1.7 + django-17: Django>=1.7,<1.8 + django-18: Django>=1.8,<1.9 +commands = + python {toxinidir}/runtests.py From 4469b55d96742b4c9039ecfce309c638d6e0d8af Mon Sep 17 00:00:00 2001 From: ekmartin Date: Sat, 7 Nov 2015 04:10:49 +0100 Subject: [PATCH 2/5] Fix pep8 errors using the Django core's flake8 preset --- channels/__init__.py | 2 +- channels/apps.py | 3 ++- channels/backends/__init__.py | 10 ++++++---- channels/backends/database.py | 20 +++++++++++--------- channels/backends/memory.py | 1 + channels/backends/redis_py.py | 11 ++++++----- channels/decorators.py | 9 ++++++--- channels/management/commands/runserver.py | 1 - channels/management/commands/runworker.py | 3 ++- channels/management/commands/runwsserver.py | 2 +- channels/request.py | 1 - channels/response.py | 6 +++--- channels/tests/settings.py | 2 ++ channels/tests/test_backends.py | 1 - tox.ini | 14 ++++++++++++-- 15 files changed, 53 insertions(+), 33 deletions(-) diff --git a/channels/__init__.py b/channels/__init__.py index 923d05c..185fbc0 100644 --- a/channels/__init__.py +++ b/channels/__init__.py @@ -16,4 +16,4 @@ channel_backends = BackendManager( default_app_config = 'channels.apps.ChannelsConfig' # Promote channel to top-level (down here to avoid circular import errs) -from .channel import Channel, Group +from .channel import Channel, Group # NOQA diff --git a/channels/apps.py b/channels/apps.py index 2d31d8d..389fc99 100644 --- a/channels/apps.py +++ b/channels/apps.py @@ -1,10 +1,11 @@ from django.apps import AppConfig + class ChannelsConfig(AppConfig): name = "channels" verbose_name = "Channels" - + def ready(self): # Do django monkeypatches from .hacks import monkeypatch_django diff --git a/channels/backends/__init__.py b/channels/backends/__init__.py index 5582b73..71efe76 100644 --- a/channels/backends/__init__.py +++ b/channels/backends/__init__.py @@ -13,17 +13,19 @@ class BackendManager(object): def __init__(self, backend_configs): self.configs = backend_configs self.backends = {} - + def make_backend(self, name): # Load the backend class try: backend_class = import_string(self.configs[name]['BACKEND']) except KeyError: raise InvalidChannelBackendError("No BACKEND specified for %s" % name) - except ImportError as e: - raise InvalidChannelBackendError("Cannot import BACKEND %r specified for %s" % (self.configs[name]['BACKEND'], name)) + except ImportError: + raise InvalidChannelBackendError("Cannot import BACKEND %r specified for %s" % + (self.configs[name]['BACKEND'], name)) # Initialise and pass config - instance = backend_class(**{k.lower(): v for k, v in self.configs[name].items() if k != "BACKEND"}) + instance = backend_class( + **{k.lower(): v for k, v in self.configs[name].items() if k != "BACKEND"}) instance.alias = name return instance diff --git a/channels/backends/database.py b/channels/backends/database.py index d1514fa..d6966e9 100644 --- a/channels/backends/database.py +++ b/channels/backends/database.py @@ -1,4 +1,3 @@ -import time import json import datetime @@ -39,6 +38,7 @@ class DatabaseChannelBackend(BaseChannelBackend): channel = models.CharField(max_length=200, db_index=True) content = models.TextField() expiry = models.DateTimeField(db_index=True) + class Meta: apps = Apps() app_label = "channels" @@ -60,6 +60,7 @@ class DatabaseChannelBackend(BaseChannelBackend): group = models.CharField(max_length=200) channel = models.CharField(max_length=200) expiry = models.DateTimeField(db_index=True) + class Meta: apps = Apps() app_label = "channels" @@ -81,6 +82,7 @@ class DatabaseChannelBackend(BaseChannelBackend): class Lock(models.Model): channel = models.CharField(max_length=200, unique=True) expiry = models.DateTimeField(db_index=True) + class Meta: apps = Apps() app_label = "channels" @@ -93,9 +95,9 @@ class DatabaseChannelBackend(BaseChannelBackend): def send(self, channel, message): self.channel_model.objects.create( - channel = channel, - content = json.dumps(message), - expiry = now() + datetime.timedelta(seconds=self.expiry) + channel=channel, + content=json.dumps(message), + expiry=now() + datetime.timedelta(seconds=self.expiry) ) def receive_many(self, channels): @@ -125,9 +127,9 @@ class DatabaseChannelBackend(BaseChannelBackend): seconds (expiry defaults to message expiry if not provided). """ self.group_model.objects.update_or_create( - group = group, - channel = channel, - defaults = {"expiry": now() + datetime.timedelta(seconds=expiry or self.expiry)}, + group=group, + channel=channel, + defaults={"expiry": now() + datetime.timedelta(seconds=expiry or self.expiry)}, ) def group_discard(self, group, channel): @@ -152,8 +154,8 @@ class DatabaseChannelBackend(BaseChannelBackend): # We rely on the UNIQUE constraint for only-one-thread-wins on locks try: self.lock_model.objects.create( - channel = channel, - expiry = now() + datetime.timedelta(seconds=expiry or self.expiry), + channel=channel, + expiry=now() + datetime.timedelta(seconds=expiry or self.expiry), ) except IntegrityError: return False diff --git a/channels/backends/memory.py b/channels/backends/memory.py index 9fff16c..6f4ca4b 100644 --- a/channels/backends/memory.py +++ b/channels/backends/memory.py @@ -7,6 +7,7 @@ queues = {} groups = {} locks = set() + class InMemoryChannelBackend(BaseChannelBackend): """ In-memory channel implementation. Intended only for use with threading, diff --git a/channels/backends/redis_py.py b/channels/backends/redis_py.py index f48f799..b0071f6 100644 --- a/channels/backends/redis_py.py +++ b/channels/backends/redis_py.py @@ -1,6 +1,5 @@ import time import json -import datetime import math import redis import random @@ -64,7 +63,11 @@ class RedisChannelBackend(BaseChannelBackend): def send(self, channel, message): # if channel is no str (=> bytes) convert it if not isinstance(channel, str): - channel = channel.decode('utf-8') + channel = channel.decode("utf-8") + # Write out message into expiring key (avoids big items in list) + # TODO: Use extended set, drop support for older redis? + key = self.prefix + uuid.uuid4().hex + # Pick a connection to the right server - consistent for response # channels, random for normal channels if channel.startswith("!"): @@ -72,9 +75,7 @@ class RedisChannelBackend(BaseChannelBackend): connection = self.connection(index) else: connection = self.connection(None) - # Write out message into expiring key (avoids big items in list) - # TODO: Use extended set, drop support for older redis? - key = self.prefix + uuid.uuid4().hex + connection.set( key, json.dumps(message), diff --git a/channels/decorators.py b/channels/decorators.py index 7c28143..6b0ca7e 100644 --- a/channels/decorators.py +++ b/channels/decorators.py @@ -18,7 +18,8 @@ def linearize(func): def inner(message, *args, **kwargs): # Make sure there's a reply channel if not message.reply_channel: - raise ValueError("No reply_channel sent to consumer; @no_overlap can only be used on messages containing it.") + raise ValueError("No reply_channel sent to consumer; " + "@no_overlap can only be used on messages containing it.") # Get the lock, or re-queue locked = message.channel_backend.lock_channel(message.reply_channel) if not locked: @@ -43,10 +44,12 @@ def channel_session(func): def inner(message, *args, **kwargs): # Make sure there's a reply_channel if not message.reply_channel: - raise ValueError("No reply_channel sent to consumer; @channel_session can only be used on messages containing it.") + raise ValueError("No reply_channel sent to consumer; " + "@channel_session can only be used on messages containing it.") # Make sure there's NOT a channel_session already if hasattr(message, "channel_session"): - raise ValueError("channel_session decorator wrapped inside another channel_session decorator") + raise ValueError("channel_session decorator wrapped " + "inside another channel_session decorator") # Turn the reply_channel into a valid session key length thing. # We take the last 24 bytes verbatim, as these are the random section, # and then hash the remaining ones onto the start, and add a prefix diff --git a/channels/management/commands/runserver.py b/channels/management/commands/runserver.py index 25be5d8..d9e91ea 100644 --- a/channels/management/commands/runserver.py +++ b/channels/management/commands/runserver.py @@ -1,7 +1,6 @@ import threading from django.core.management.commands.runserver import Command as RunserverCommand - from channels import channel_backends, DEFAULT_CHANNEL_BACKEND from channels.adapters import UrlConsumer from channels.interfaces.wsgi import WSGIInterface diff --git a/channels/management/commands/runworker.py b/channels/management/commands/runworker.py index 721e42f..1c7df73 100644 --- a/channels/management/commands/runworker.py +++ b/channels/management/commands/runworker.py @@ -14,7 +14,8 @@ class Command(BaseCommand): channel_backend = channel_backends[DEFAULT_CHANNEL_BACKEND] if channel_backend.local_only: raise CommandError( - "You have a process-local channel backend configured, and so cannot run separate workers.\n" + "You have a process-local channel backend configured, " + "and so cannot run separate workers.\n" "Configure a network-based backend in CHANNEL_BACKENDS to use this command." ) # Launch a worker diff --git a/channels/management/commands/runwsserver.py b/channels/management/commands/runwsserver.py index 72e3cb7..fae1e2c 100644 --- a/channels/management/commands/runwsserver.py +++ b/channels/management/commands/runwsserver.py @@ -23,7 +23,7 @@ class Command(BaseCommand): # Run the interface port = int(options.get("port", None) or 9000) try: - import asyncio + import asyncio # NOQA except ImportError: from channels.interfaces.websocket_twisted import WebsocketTwistedInterface self.logger.info("Running Twisted/Autobahn WebSocket interface server") diff --git a/channels/request.py b/channels/request.py index 2af4098..e29d711 100644 --- a/channels/request.py +++ b/channels/request.py @@ -1,7 +1,6 @@ from django.http import HttpRequest from django.utils.datastructures import MultiValueDict from django.http.request import QueryDict -from django.conf import settings def encode_request(request): diff --git a/channels/response.py b/channels/response.py index 4b253d7..f484da7 100644 --- a/channels/response.py +++ b/channels/response.py @@ -24,9 +24,9 @@ def decode_response(value): Decodes a response JSONish value to a HttpResponse object. """ response = HttpResponse( - content = value['content'], - content_type = value['content_type'], - status = value['status'], + content=value['content'], + content_type=value['content_type'], + status=value['status'], ) for cookie in value['cookies']: response.cookies.load(cookie) diff --git a/channels/tests/settings.py b/channels/tests/settings.py index e1c7f80..c472c7e 100644 --- a/channels/tests/settings.py +++ b/channels/tests/settings.py @@ -5,3 +5,5 @@ DATABASES = { 'ENGINE': 'django.db.backends.sqlite3', } } + +MIDDLEWARE_CLASSES = [] diff --git a/channels/tests/test_backends.py b/channels/tests/test_backends.py index c2cbba6..90089fd 100644 --- a/channels/tests/test_backends.py +++ b/channels/tests/test_backends.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals from django.test import TestCase -from ..channel import Channel from ..backends.database import DatabaseChannelBackend from ..backends.redis_py import RedisChannelBackend from ..backends.memory import InMemoryChannelBackend diff --git a/tox.ini b/tox.ini index 18142eb..ab262df 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,14 @@ [tox] skipsdist = True envlist = - {py27,py35}-django-{16,17,18} + {py27}-django-{17,18,19} + {py35}-django-{18,19} + {py27,py35}-flake8 + +[flake8] +exclude = venv/*,tox/*,docs/* +ignore = E123,E128,E402,W503,E731,W601 +max-line-length = 119 [testenv] setenv = @@ -9,8 +16,11 @@ setenv = deps = six redis==2.10.5 + flake8: flake8 django-16: Django>=1.6,<1.7 django-17: Django>=1.7,<1.8 django-18: Django>=1.8,<1.9 + django-19: Django==1.9b1 commands = - python {toxinidir}/runtests.py + flake8: flake8 + django: python {toxinidir}/runtests.py From 14bc3062143acaee72d968b4bdd42bb4cc436ae1 Mon Sep 17 00:00:00 2001 From: ekmartin Date: Sat, 7 Nov 2015 20:33:13 +0100 Subject: [PATCH 3/5] Make sure channels() actually returns the channel list --- channels/channel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/channel.py b/channels/channel.py index 0e047b5..5a0160e 100644 --- a/channels/channel.py +++ b/channels/channel.py @@ -81,7 +81,7 @@ class Group(object): self.channel_backend.group_discard(self.name, channel) def channels(self): - self.channel_backend.group_channels(self.name) + return self.channel_backend.group_channels(self.name) def send(self, content): if not isinstance(content, dict): From 1804d66b8597974754d8562d1793a18b6cb8eef5 Mon Sep 17 00:00:00 2001 From: ekmartin Date: Sat, 7 Nov 2015 20:51:50 +0100 Subject: [PATCH 4/5] Ignore testproject for flake8 --- channels/tests/test_backends.py | 1 + tox.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/channels/tests/test_backends.py b/channels/tests/test_backends.py index 90089fd..f4bc461 100644 --- a/channels/tests/test_backends.py +++ b/channels/tests/test_backends.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.test import TestCase diff --git a/tox.ini b/tox.ini index ab262df..cff47ce 100644 --- a/tox.ini +++ b/tox.ini @@ -6,7 +6,7 @@ envlist = {py27,py35}-flake8 [flake8] -exclude = venv/*,tox/*,docs/* +exclude = venv/*,tox/*,docs/*,testproject/* ignore = E123,E128,E402,W503,E731,W601 max-line-length = 119 From cf2de79d64745f9328225fa7e3666b2d5f4a4dd4 Mon Sep 17 00:00:00 2001 From: ekmartin Date: Sat, 7 Nov 2015 21:03:31 +0100 Subject: [PATCH 5/5] Add isort and fix errors --- channels/__init__.py | 8 +++++--- channels/auth.py | 1 + channels/backends/__init__.py | 9 +++++---- channels/backends/base.py | 1 + channels/backends/database.py | 4 ++-- channels/backends/memory.py | 3 ++- channels/backends/redis_py.py | 6 +++--- channels/channel.py | 2 +- channels/consumer_registry.py | 4 +++- channels/decorators.py | 16 ++++++++++------ channels/hacks.py | 7 ++++--- channels/interfaces/websocket_asyncio.py | 8 +++++--- channels/interfaces/websocket_autobahn.py | 2 +- channels/interfaces/websocket_twisted.py | 6 ++++-- channels/interfaces/wsgi.py | 1 + channels/management/commands/runserver.py | 6 ++++-- channels/management/commands/runworker.py | 6 +++--- channels/management/commands/runwsserver.py | 2 +- channels/request.py | 2 +- channels/tests/test_backends.py | 3 ++- setup.cfg | 12 ++++++++++++ tox.ini | 8 +++----- 22 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 setup.cfg diff --git a/channels/__init__.py b/channels/__init__.py index 185fbc0..dde140b 100644 --- a/channels/__init__.py +++ b/channels/__init__.py @@ -2,8 +2,10 @@ __version__ = "0.8" # Load backends, using settings if available (else falling back to a default) DEFAULT_CHANNEL_BACKEND = "default" -from .backends import BackendManager -from django.conf import settings + +from .backends import BackendManager # isort:skip +from django.conf import settings # isort:skip + channel_backends = BackendManager( getattr(settings, "CHANNEL_BACKENDS", { DEFAULT_CHANNEL_BACKEND: { @@ -16,4 +18,4 @@ channel_backends = BackendManager( default_app_config = 'channels.apps.ChannelsConfig' # Promote channel to top-level (down here to avoid circular import errs) -from .channel import Channel, Group # NOQA +from .channel import Channel, Group # NOQA isort:skip diff --git a/channels/auth.py b/channels/auth.py index 261010c..d0c786a 100644 --- a/channels/auth.py +++ b/channels/auth.py @@ -1,6 +1,7 @@ import functools from django.contrib import auth + from .decorators import channel_session, http_session diff --git a/channels/backends/__init__.py b/channels/backends/__init__.py index 71efe76..e52d24f 100644 --- a/channels/backends/__init__.py +++ b/channels/backends/__init__.py @@ -21,11 +21,12 @@ class BackendManager(object): except KeyError: raise InvalidChannelBackendError("No BACKEND specified for %s" % name) except ImportError: - raise InvalidChannelBackendError("Cannot import BACKEND %r specified for %s" % - (self.configs[name]['BACKEND'], name)) + raise InvalidChannelBackendError( + "Cannot import BACKEND %r specified for %s" % (self.configs[name]['BACKEND'], name) + ) + # Initialise and pass config - instance = backend_class( - **{k.lower(): v for k, v in self.configs[name].items() if k != "BACKEND"}) + instance = backend_class(**{k.lower(): v for k, v in self.configs[name].items() if k != "BACKEND"}) instance.alias = name return instance diff --git a/channels/backends/base.py b/channels/backends/base.py index 9baaf6c..fbf9c5f 100644 --- a/channels/backends/base.py +++ b/channels/backends/base.py @@ -1,4 +1,5 @@ import time + from channels.consumer_registry import ConsumerRegistry diff --git a/channels/backends/database.py b/channels/backends/database.py index d6966e9..d0b7f69 100644 --- a/channels/backends/database.py +++ b/channels/backends/database.py @@ -1,8 +1,8 @@ -import json import datetime +import json from django.apps.registry import Apps -from django.db import models, connections, DEFAULT_DB_ALIAS, IntegrityError +from django.db import DEFAULT_DB_ALIAS, IntegrityError, connections, models from django.utils.functional import cached_property from django.utils.timezone import now diff --git a/channels/backends/memory.py b/channels/backends/memory.py index 6f4ca4b..0cb28ba 100644 --- a/channels/backends/memory.py +++ b/channels/backends/memory.py @@ -1,6 +1,7 @@ -import time import json +import time from collections import deque + from .base import BaseChannelBackend queues = {} diff --git a/channels/backends/redis_py.py b/channels/backends/redis_py.py index b0071f6..0cfbea9 100644 --- a/channels/backends/redis_py.py +++ b/channels/backends/redis_py.py @@ -1,11 +1,11 @@ -import time +import binascii import json import math -import redis import random -import binascii +import time import uuid +import redis from django.utils import six from .base import BaseChannelBackend diff --git a/channels/channel.py b/channels/channel.py index 5a0160e..33112d8 100644 --- a/channels/channel.py +++ b/channels/channel.py @@ -1,7 +1,7 @@ import random import string -from channels import channel_backends, DEFAULT_CHANNEL_BACKEND +from channels import DEFAULT_CHANNEL_BACKEND, channel_backends class Channel(object): diff --git a/channels/consumer_registry.py b/channels/consumer_registry.py index 359fcd7..5102e7a 100644 --- a/channels/consumer_registry.py +++ b/channels/consumer_registry.py @@ -1,6 +1,8 @@ import importlib -from django.utils import six + from django.core.exceptions import ImproperlyConfigured +from django.utils import six + from .utils import name_that_thing diff --git a/channels/decorators.py b/channels/decorators.py index 6b0ca7e..6f78c49 100644 --- a/channels/decorators.py +++ b/channels/decorators.py @@ -18,8 +18,10 @@ def linearize(func): def inner(message, *args, **kwargs): # Make sure there's a reply channel if not message.reply_channel: - raise ValueError("No reply_channel sent to consumer; " - "@no_overlap can only be used on messages containing it.") + raise ValueError( + "No reply_channel sent to consumer; @no_overlap can only be used on messages containing it." + ) + # Get the lock, or re-queue locked = message.channel_backend.lock_channel(message.reply_channel) if not locked: @@ -44,12 +46,14 @@ def channel_session(func): def inner(message, *args, **kwargs): # Make sure there's a reply_channel if not message.reply_channel: - raise ValueError("No reply_channel sent to consumer; " - "@channel_session can only be used on messages containing it.") + raise ValueError( + "No reply_channel sent to consumer; @no_overlap can only be used on messages containing it." + ) + # Make sure there's NOT a channel_session already if hasattr(message, "channel_session"): - raise ValueError("channel_session decorator wrapped " - "inside another channel_session decorator") + raise ValueError("channel_session decorator wrapped inside another channel_session decorator") + # Turn the reply_channel into a valid session key length thing. # We take the last 24 bytes verbatim, as these are the random section, # and then hash the remaining ones onto the start, and add a prefix diff --git a/channels/hacks.py b/channels/hacks.py index e782eb6..b8050cb 100644 --- a/channels/hacks.py +++ b/channels/hacks.py @@ -1,8 +1,9 @@ +from django.core.handlers.base import BaseHandler from django.http.request import HttpRequest from django.http.response import HttpResponseBase -from django.core.handlers.base import BaseHandler -from .request import encode_request, decode_request -from .response import encode_response, decode_response, ResponseLater + +from .request import decode_request, encode_request +from .response import ResponseLater, decode_response, encode_response def monkeypatch_django(): diff --git a/channels/interfaces/websocket_asyncio.py b/channels/interfaces/websocket_asyncio.py index b0d852a..899bfcf 100644 --- a/channels/interfaces/websocket_asyncio.py +++ b/channels/interfaces/websocket_asyncio.py @@ -1,9 +1,11 @@ -import asyncio import time -from autobahn.asyncio.websocket import WebSocketServerProtocol, WebSocketServerFactory +import asyncio +from autobahn.asyncio.websocket import ( + WebSocketServerFactory, WebSocketServerProtocol, +) -from .websocket_autobahn import get_protocol, get_factory +from .websocket_autobahn import get_factory, get_protocol class WebsocketAsyncioInterface(object): diff --git a/channels/interfaces/websocket_autobahn.py b/channels/interfaces/websocket_autobahn.py index 7517b8c..1445ad1 100644 --- a/channels/interfaces/websocket_autobahn.py +++ b/channels/interfaces/websocket_autobahn.py @@ -1,6 +1,6 @@ import time -from channels import Channel, channel_backends, DEFAULT_CHANNEL_BACKEND +from channels import DEFAULT_CHANNEL_BACKEND, Channel, channel_backends def get_protocol(base): diff --git a/channels/interfaces/websocket_twisted.py b/channels/interfaces/websocket_twisted.py index e6055f1..e8122a7 100644 --- a/channels/interfaces/websocket_twisted.py +++ b/channels/interfaces/websocket_twisted.py @@ -1,9 +1,11 @@ import time -from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory +from autobahn.twisted.websocket import ( + WebSocketServerFactory, WebSocketServerProtocol, +) from twisted.internet import reactor -from .websocket_autobahn import get_protocol, get_factory +from .websocket_autobahn import get_factory, get_protocol class WebsocketTwistedInterface(object): diff --git a/channels/interfaces/wsgi.py b/channels/interfaces/wsgi.py index b856b93..004e6ea 100644 --- a/channels/interfaces/wsgi.py +++ b/channels/interfaces/wsgi.py @@ -1,6 +1,7 @@ import django from django.core.handlers.wsgi import WSGIHandler from django.http import HttpResponse + from channels import Channel diff --git a/channels/management/commands/runserver.py b/channels/management/commands/runserver.py index d9e91ea..6fa54d6 100644 --- a/channels/management/commands/runserver.py +++ b/channels/management/commands/runserver.py @@ -1,7 +1,9 @@ import threading -from django.core.management.commands.runserver import Command as RunserverCommand -from channels import channel_backends, DEFAULT_CHANNEL_BACKEND +from django.core.management.commands.runserver import \ + Command as RunserverCommand + +from channels import DEFAULT_CHANNEL_BACKEND, channel_backends from channels.adapters import UrlConsumer from channels.interfaces.wsgi import WSGIInterface from channels.log import setup_logger diff --git a/channels/management/commands/runworker.py b/channels/management/commands/runworker.py index 1c7df73..2c157bc 100644 --- a/channels/management/commands/runworker.py +++ b/channels/management/commands/runworker.py @@ -1,6 +1,7 @@ + from django.core.management import BaseCommand, CommandError -from channels import channel_backends, DEFAULT_CHANNEL_BACKEND +from channels import DEFAULT_CHANNEL_BACKEND, channel_backends from channels.log import setup_logger from channels.worker import Worker @@ -14,8 +15,7 @@ class Command(BaseCommand): channel_backend = channel_backends[DEFAULT_CHANNEL_BACKEND] if channel_backend.local_only: raise CommandError( - "You have a process-local channel backend configured, " - "and so cannot run separate workers.\n" + "You have a process-local channel backend configured, and so cannot run separate workers.\n" "Configure a network-based backend in CHANNEL_BACKENDS to use this command." ) # Launch a worker diff --git a/channels/management/commands/runwsserver.py b/channels/management/commands/runwsserver.py index fae1e2c..54f2f0c 100644 --- a/channels/management/commands/runwsserver.py +++ b/channels/management/commands/runwsserver.py @@ -1,6 +1,6 @@ from django.core.management import BaseCommand, CommandError -from channels import channel_backends, DEFAULT_CHANNEL_BACKEND +from channels import DEFAULT_CHANNEL_BACKEND, channel_backends from channels.log import setup_logger diff --git a/channels/request.py b/channels/request.py index e29d711..4060335 100644 --- a/channels/request.py +++ b/channels/request.py @@ -1,6 +1,6 @@ from django.http import HttpRequest -from django.utils.datastructures import MultiValueDict from django.http.request import QueryDict +from django.utils.datastructures import MultiValueDict def encode_request(request): diff --git a/channels/tests/test_backends.py b/channels/tests/test_backends.py index f4bc461..b25750f 100644 --- a/channels/tests/test_backends.py +++ b/channels/tests/test_backends.py @@ -2,9 +2,10 @@ from __future__ import unicode_literals from django.test import TestCase + from ..backends.database import DatabaseChannelBackend -from ..backends.redis_py import RedisChannelBackend from ..backends.memory import InMemoryChannelBackend +from ..backends.redis_py import RedisChannelBackend class MemoryBackendTests(TestCase): diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..445b946 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,12 @@ +[flake8] +exclude = venv/*,tox/*,docs/*,testproject/* +ignore = E123,E128,E402,W503,E731,W601 +max-line-length = 119 + +[isort] +combine_as_imports = true +default_section = THIRDPARTY +include_trailing_comma = true +known_first_party = channels +multi_line_output = 5 +not_skip = __init__.py diff --git a/tox.ini b/tox.ini index cff47ce..f42ff19 100644 --- a/tox.ini +++ b/tox.ini @@ -4,11 +4,7 @@ envlist = {py27}-django-{17,18,19} {py35}-django-{18,19} {py27,py35}-flake8 - -[flake8] -exclude = venv/*,tox/*,docs/*,testproject/* -ignore = E123,E128,E402,W503,E731,W601 -max-line-length = 119 + isort [testenv] setenv = @@ -17,10 +13,12 @@ deps = six redis==2.10.5 flake8: flake8 + isort: isort django-16: Django>=1.6,<1.7 django-17: Django>=1.7,<1.8 django-18: Django>=1.8,<1.9 django-19: Django==1.9b1 commands = flake8: flake8 + isort: isort -c -rc channels django: python {toxinidir}/runtests.py