mirror of
https://github.com/django/daphne.git
synced 2025-07-11 08:22:17 +03:00
Merge pull request #29 from ekmartin/tests_and_py3
Run tests with tox and add flake8/isort
This commit is contained in:
commit
0c03ea7780
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,5 +2,6 @@
|
||||||
dist/
|
dist/
|
||||||
docs/_build
|
docs/_build
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
.tox/
|
||||||
*.swp
|
*.swp
|
||||||
|
*.pyc
|
||||||
|
|
|
@ -2,8 +2,10 @@ __version__ = "0.8"
|
||||||
|
|
||||||
# Load backends, using settings if available (else falling back to a default)
|
# Load backends, using settings if available (else falling back to a default)
|
||||||
DEFAULT_CHANNEL_BACKEND = "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(
|
channel_backends = BackendManager(
|
||||||
getattr(settings, "CHANNEL_BACKENDS", {
|
getattr(settings, "CHANNEL_BACKENDS", {
|
||||||
DEFAULT_CHANNEL_BACKEND: {
|
DEFAULT_CHANNEL_BACKEND: {
|
||||||
|
@ -16,4 +18,4 @@ channel_backends = BackendManager(
|
||||||
default_app_config = 'channels.apps.ChannelsConfig'
|
default_app_config = 'channels.apps.ChannelsConfig'
|
||||||
|
|
||||||
# Promote channel to top-level (down here to avoid circular import errs)
|
# Promote channel to top-level (down here to avoid circular import errs)
|
||||||
from .channel import Channel, Group
|
from .channel import Channel, Group # NOQA isort:skip
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class ChannelsConfig(AppConfig):
|
class ChannelsConfig(AppConfig):
|
||||||
|
|
||||||
name = "channels"
|
name = "channels"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
|
|
||||||
from .decorators import channel_session, http_session
|
from .decorators import channel_session, http_session
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,11 @@ class BackendManager(object):
|
||||||
backend_class = import_string(self.configs[name]['BACKEND'])
|
backend_class = import_string(self.configs[name]['BACKEND'])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise InvalidChannelBackendError("No BACKEND specified for %s" % name)
|
raise InvalidChannelBackendError("No BACKEND specified for %s" % name)
|
||||||
except ImportError as e:
|
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
|
# 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
|
instance.alias = name
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from channels.consumer_registry import ConsumerRegistry
|
from channels.consumer_registry import ConsumerRegistry
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import time
|
|
||||||
import json
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
|
|
||||||
from django.apps.registry import Apps
|
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.functional import cached_property
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
|
@ -39,6 +38,7 @@ class DatabaseChannelBackend(BaseChannelBackend):
|
||||||
channel = models.CharField(max_length=200, db_index=True)
|
channel = models.CharField(max_length=200, db_index=True)
|
||||||
content = models.TextField()
|
content = models.TextField()
|
||||||
expiry = models.DateTimeField(db_index=True)
|
expiry = models.DateTimeField(db_index=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
apps = Apps()
|
apps = Apps()
|
||||||
app_label = "channels"
|
app_label = "channels"
|
||||||
|
@ -60,6 +60,7 @@ class DatabaseChannelBackend(BaseChannelBackend):
|
||||||
group = models.CharField(max_length=200)
|
group = models.CharField(max_length=200)
|
||||||
channel = models.CharField(max_length=200)
|
channel = models.CharField(max_length=200)
|
||||||
expiry = models.DateTimeField(db_index=True)
|
expiry = models.DateTimeField(db_index=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
apps = Apps()
|
apps = Apps()
|
||||||
app_label = "channels"
|
app_label = "channels"
|
||||||
|
@ -81,6 +82,7 @@ class DatabaseChannelBackend(BaseChannelBackend):
|
||||||
class Lock(models.Model):
|
class Lock(models.Model):
|
||||||
channel = models.CharField(max_length=200, unique=True)
|
channel = models.CharField(max_length=200, unique=True)
|
||||||
expiry = models.DateTimeField(db_index=True)
|
expiry = models.DateTimeField(db_index=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
apps = Apps()
|
apps = Apps()
|
||||||
app_label = "channels"
|
app_label = "channels"
|
||||||
|
@ -93,9 +95,9 @@ class DatabaseChannelBackend(BaseChannelBackend):
|
||||||
|
|
||||||
def send(self, channel, message):
|
def send(self, channel, message):
|
||||||
self.channel_model.objects.create(
|
self.channel_model.objects.create(
|
||||||
channel = channel,
|
channel=channel,
|
||||||
content = json.dumps(message),
|
content=json.dumps(message),
|
||||||
expiry = now() + datetime.timedelta(seconds=self.expiry)
|
expiry=now() + datetime.timedelta(seconds=self.expiry)
|
||||||
)
|
)
|
||||||
|
|
||||||
def receive_many(self, channels):
|
def receive_many(self, channels):
|
||||||
|
@ -125,9 +127,9 @@ class DatabaseChannelBackend(BaseChannelBackend):
|
||||||
seconds (expiry defaults to message expiry if not provided).
|
seconds (expiry defaults to message expiry if not provided).
|
||||||
"""
|
"""
|
||||||
self.group_model.objects.update_or_create(
|
self.group_model.objects.update_or_create(
|
||||||
group = group,
|
group=group,
|
||||||
channel = channel,
|
channel=channel,
|
||||||
defaults = {"expiry": now() + datetime.timedelta(seconds=expiry or self.expiry)},
|
defaults={"expiry": now() + datetime.timedelta(seconds=expiry or self.expiry)},
|
||||||
)
|
)
|
||||||
|
|
||||||
def group_discard(self, group, channel):
|
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
|
# We rely on the UNIQUE constraint for only-one-thread-wins on locks
|
||||||
try:
|
try:
|
||||||
self.lock_model.objects.create(
|
self.lock_model.objects.create(
|
||||||
channel = channel,
|
channel=channel,
|
||||||
expiry = now() + datetime.timedelta(seconds=expiry or self.expiry),
|
expiry=now() + datetime.timedelta(seconds=expiry or self.expiry),
|
||||||
)
|
)
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import time
|
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
from .base import BaseChannelBackend
|
from .base import BaseChannelBackend
|
||||||
|
|
||||||
queues = {}
|
queues = {}
|
||||||
groups = {}
|
groups = {}
|
||||||
locks = set()
|
locks = set()
|
||||||
|
|
||||||
|
|
||||||
class InMemoryChannelBackend(BaseChannelBackend):
|
class InMemoryChannelBackend(BaseChannelBackend):
|
||||||
"""
|
"""
|
||||||
In-memory channel implementation. Intended only for use with threading,
|
In-memory channel implementation. Intended only for use with threading,
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import time
|
|
||||||
import json
|
|
||||||
import datetime
|
|
||||||
import math
|
|
||||||
import redis
|
|
||||||
import random
|
|
||||||
import binascii
|
import binascii
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import random
|
||||||
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import redis
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
from .base import BaseChannelBackend
|
from .base import BaseChannelBackend
|
||||||
|
@ -64,7 +63,11 @@ class RedisChannelBackend(BaseChannelBackend):
|
||||||
def send(self, channel, message):
|
def send(self, channel, message):
|
||||||
# if channel is no str (=> bytes) convert it
|
# if channel is no str (=> bytes) convert it
|
||||||
if not isinstance(channel, str):
|
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
|
# Pick a connection to the right server - consistent for response
|
||||||
# channels, random for normal channels
|
# channels, random for normal channels
|
||||||
if channel.startswith("!"):
|
if channel.startswith("!"):
|
||||||
|
@ -72,9 +75,7 @@ class RedisChannelBackend(BaseChannelBackend):
|
||||||
connection = self.connection(index)
|
connection = self.connection(index)
|
||||||
else:
|
else:
|
||||||
connection = self.connection(None)
|
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(
|
connection.set(
|
||||||
key,
|
key,
|
||||||
json.dumps(message),
|
json.dumps(message),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
from channels import channel_backends, DEFAULT_CHANNEL_BACKEND
|
from channels import DEFAULT_CHANNEL_BACKEND, channel_backends
|
||||||
|
|
||||||
|
|
||||||
class Channel(object):
|
class Channel(object):
|
||||||
|
@ -81,7 +81,7 @@ class Group(object):
|
||||||
self.channel_backend.group_discard(self.name, channel)
|
self.channel_backend.group_discard(self.name, channel)
|
||||||
|
|
||||||
def channels(self):
|
def channels(self):
|
||||||
self.channel_backend.group_channels(self.name)
|
return self.channel_backend.group_channels(self.name)
|
||||||
|
|
||||||
def send(self, content):
|
def send(self, content):
|
||||||
if not isinstance(content, dict):
|
if not isinstance(content, dict):
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import importlib
|
import importlib
|
||||||
from django.utils import six
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.utils import six
|
||||||
|
|
||||||
from .utils import name_that_thing
|
from .utils import name_that_thing
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,10 @@ def linearize(func):
|
||||||
def inner(message, *args, **kwargs):
|
def inner(message, *args, **kwargs):
|
||||||
# Make sure there's a reply channel
|
# Make sure there's a reply channel
|
||||||
if not message.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
|
# Get the lock, or re-queue
|
||||||
locked = message.channel_backend.lock_channel(message.reply_channel)
|
locked = message.channel_backend.lock_channel(message.reply_channel)
|
||||||
if not locked:
|
if not locked:
|
||||||
|
@ -43,10 +46,14 @@ def channel_session(func):
|
||||||
def inner(message, *args, **kwargs):
|
def inner(message, *args, **kwargs):
|
||||||
# Make sure there's a reply_channel
|
# Make sure there's a reply_channel
|
||||||
if not message.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
|
# Make sure there's NOT a channel_session already
|
||||||
if hasattr(message, "channel_session"):
|
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.
|
# Turn the reply_channel into a valid session key length thing.
|
||||||
# We take the last 24 bytes verbatim, as these are the random section,
|
# 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
|
# and then hash the remaining ones onto the start, and add a prefix
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
from django.core.handlers.base import BaseHandler
|
||||||
from django.http.request import HttpRequest
|
from django.http.request import HttpRequest
|
||||||
from django.http.response import HttpResponseBase
|
from django.http.response import HttpResponseBase
|
||||||
from django.core.handlers.base import BaseHandler
|
|
||||||
from .request import encode_request, decode_request
|
from .request import decode_request, encode_request
|
||||||
from .response import encode_response, decode_response, ResponseLater
|
from .response import ResponseLater, decode_response, encode_response
|
||||||
|
|
||||||
|
|
||||||
def monkeypatch_django():
|
def monkeypatch_django():
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import asyncio
|
|
||||||
import time
|
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):
|
class WebsocketAsyncioInterface(object):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from channels import Channel, channel_backends, DEFAULT_CHANNEL_BACKEND
|
from channels import DEFAULT_CHANNEL_BACKEND, Channel, channel_backends
|
||||||
|
|
||||||
|
|
||||||
def get_protocol(base):
|
def get_protocol(base):
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
|
from autobahn.twisted.websocket import (
|
||||||
|
WebSocketServerFactory, WebSocketServerProtocol,
|
||||||
|
)
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
|
|
||||||
from .websocket_autobahn import get_protocol, get_factory
|
from .websocket_autobahn import get_factory, get_protocol
|
||||||
|
|
||||||
|
|
||||||
class WebsocketTwistedInterface(object):
|
class WebsocketTwistedInterface(object):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import django
|
import django
|
||||||
from django.core.handlers.wsgi import WSGIHandler
|
from django.core.handlers.wsgi import WSGIHandler
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
from channels import Channel
|
from channels import Channel
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from django.core.management.commands.runserver import Command as RunserverCommand
|
from django.core.management.commands.runserver import \
|
||||||
|
Command as RunserverCommand
|
||||||
|
|
||||||
from channels import channel_backends, DEFAULT_CHANNEL_BACKEND
|
from channels import DEFAULT_CHANNEL_BACKEND, channel_backends
|
||||||
from channels.adapters import UrlConsumer
|
from channels.adapters import UrlConsumer
|
||||||
from channels.interfaces.wsgi import WSGIInterface
|
from channels.interfaces.wsgi import WSGIInterface
|
||||||
from channels.log import setup_logger
|
from channels.log import setup_logger
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
from django.core.management import BaseCommand, CommandError
|
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.log import setup_logger
|
||||||
from channels.worker import Worker
|
from channels.worker import Worker
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.core.management import BaseCommand, CommandError
|
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.log import setup_logger
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class Command(BaseCommand):
|
||||||
# Run the interface
|
# Run the interface
|
||||||
port = int(options.get("port", None) or 9000)
|
port = int(options.get("port", None) or 9000)
|
||||||
try:
|
try:
|
||||||
import asyncio
|
import asyncio # NOQA
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from channels.interfaces.websocket_twisted import WebsocketTwistedInterface
|
from channels.interfaces.websocket_twisted import WebsocketTwistedInterface
|
||||||
self.logger.info("Running Twisted/Autobahn WebSocket interface server")
|
self.logger.info("Running Twisted/Autobahn WebSocket interface server")
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from django.utils.datastructures import MultiValueDict
|
|
||||||
from django.http.request import QueryDict
|
from django.http.request import QueryDict
|
||||||
from django.conf import settings
|
from django.utils.datastructures import MultiValueDict
|
||||||
|
|
||||||
|
|
||||||
def encode_request(request):
|
def encode_request(request):
|
||||||
|
|
|
@ -24,9 +24,9 @@ def decode_response(value):
|
||||||
Decodes a response JSONish value to a HttpResponse object.
|
Decodes a response JSONish value to a HttpResponse object.
|
||||||
"""
|
"""
|
||||||
response = HttpResponse(
|
response = HttpResponse(
|
||||||
content = value['content'],
|
content=value['content'],
|
||||||
content_type = value['content_type'],
|
content_type=value['content_type'],
|
||||||
status = value['status'],
|
status=value['status'],
|
||||||
)
|
)
|
||||||
for cookie in value['cookies']:
|
for cookie in value['cookies']:
|
||||||
response.cookies.load(cookie)
|
response.cookies.load(cookie)
|
||||||
|
|
9
channels/tests/settings.py
Normal file
9
channels/tests/settings.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
SECRET_KEY = 'cat'
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDDLEWARE_CLASSES = []
|
|
@ -1,10 +1,11 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from ..channel import Channel
|
|
||||||
from ..backends.database import DatabaseChannelBackend
|
from ..backends.database import DatabaseChannelBackend
|
||||||
from ..backends.redis_py import RedisChannelBackend
|
|
||||||
from ..backends.memory import InMemoryChannelBackend
|
from ..backends.memory import InMemoryChannelBackend
|
||||||
|
from ..backends.redis_py import RedisChannelBackend
|
||||||
|
|
||||||
|
|
||||||
class MemoryBackendTests(TestCase):
|
class MemoryBackendTests(TestCase):
|
||||||
|
|
15
runtests.py
Normal file
15
runtests.py
Normal file
|
@ -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))
|
12
setup.cfg
Normal file
12
setup.cfg
Normal file
|
@ -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
|
24
tox.ini
Normal file
24
tox.ini
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[tox]
|
||||||
|
skipsdist = True
|
||||||
|
envlist =
|
||||||
|
{py27}-django-{17,18,19}
|
||||||
|
{py35}-django-{18,19}
|
||||||
|
{py27,py35}-flake8
|
||||||
|
isort
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
setenv =
|
||||||
|
PYTHONPATH = {toxinidir}:{toxinidir}
|
||||||
|
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
|
Loading…
Reference in New Issue
Block a user