Permalink
Browse files

Python 3 support

  • Loading branch information...
1 parent 794bd23 commit 0723bc6c09eaf0db30d802a61eaf63f75d4988de @rafales rafales committed Feb 13, 2013
View
17 pytest_django/db_reuse.py
@@ -3,8 +3,9 @@
The code in this module is heavily inspired by django-nose:
https://github.com/jbalogh/django-nose/
"""
+import sys
+import types
-import new
import py
@@ -27,7 +28,7 @@ def test_database_exists_from_previous_run(connection):
try:
connection.cursor()
return True
- except StandardError: # TODO: Be more discerning but still DB agnostic.
+ except Exception: # TODO: Be more discerning but still DB agnostic.
return False
finally:
connection.close()
@@ -47,8 +48,8 @@ def create_test_db(self, verbosity=1, autoclobber=False):
test_db_repr = ''
if verbosity >= 2:
test_db_repr = " ('%s')" % test_database_name
- print "Re-using existing test database for alias '%s'%s..." % (
- self.connection.alias, test_db_repr)
+ print("Re-using existing test database for alias '%s'%s..." % (
+ self.connection.alias, test_db_repr))
# confirm() is not needed/available in Django >= 1.5
# See https://code.djangoproject.com/ticket/17760
@@ -69,5 +70,9 @@ def monkey_patch_creation_for_db_reuse():
# Make sure our monkey patch is still valid in the future
assert hasattr(creation, 'create_test_db')
- creation.create_test_db = new.instancemethod(
- create_test_db, creation, creation.__class__)
+ if sys.version_info < (3, 0):
+ creation.create_test_db = types.MethodType(
+ create_test_db, creation, creation.__class__)
+ else:
+ creation.create_test_db = types.MethodType(create_test_db,
+ creation)
View
10 pytest_django/django_compat.py
@@ -1,5 +1,6 @@
# Note that all functions here assume django is available. So ensure
# this is the case before you call them.
+import sys
def is_django_unittest(item):
@@ -9,5 +10,10 @@ def is_django_unittest(item):
except ImportError:
from django.test import TestCase
- return (hasattr(item.obj, 'im_class') and
- issubclass(item.obj.im_class, TestCase))
+ if sys.version_info < (3, 0):
+ return (hasattr(item.obj, 'im_class') and
+ issubclass(item.obj.im_class, TestCase))
+
+ return (hasattr(item.obj, '__self__') and
+ hasattr(item.obj.__self__, '__class__') and
+ issubclass(item.obj.__self__.__class__, TestCase))
View
26 pytest_django/live_server_helper.py
@@ -1,5 +1,5 @@
-import pytest
-
+import sys
+import py
def supported():
import django.test.testcases
@@ -49,15 +49,21 @@ def stop(self):
def url(self):
return 'http://%s:%s' % (self.thread.host, self.thread.port)
- def __unicode__(self):
- return self.url
+ if sys.version_info < (3, 0):
+ def __unicode__(self):
+ return self.url
- def __repr__(self):
- return '<LiveServer listening at %s>' % unicode(self)
+ def __add__(self, other):
+ return unicode(self) + other
+ else:
+ def __str__(self):
+ return self.url
- def __add__(self, other):
- # Support string concatenation
- return unicode(self) + other
+ def __add__(self, other):
+ return str(self) + other
+
+ def __repr__(self):
+ return '<LiveServer listening at %s>' % self.url
def parse_addr(specified_address):
@@ -73,7 +79,7 @@ def parse_addr(specified_address):
host, port_ranges = specified_address.split(':')
for port_range in port_ranges.split(','):
# A port range can be of either form: '8000' or '8000-8010'.
- extremes = map(int, port_range.split('-'))
+ extremes = list(map(int, port_range.split('-')))
assert len(extremes) in [1, 2]
if len(extremes) == 1:
# Port range of the form '8000'
View
4 pytest_django/plugin.py
@@ -5,6 +5,7 @@
"""
import os
+import sys
import pytest
@@ -70,7 +71,8 @@ def pytest_configure(config):
from django.conf import settings
try:
settings.DATABASES
- except ImportError, e:
+ except ImportError:
+ e = sys.exc_info()[1]
raise pytest.UsageError(*e.args)
# Register the marks
View
4 setup.py
@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
import os
+import codecs
from setuptools import setup
@@ -10,7 +11,8 @@
# README file and 2) it's easier to type in the README file than to put a raw
# string in below ...
def read(fname):
- return open(os.path.join(os.path.dirname(__file__), fname)).read()
+ file_path = os.path.join(os.path.dirname(__file__), fname)
+ return codecs.open(file_path, encoding='utf-8').read()
setup(
View
10 tests/compat.py
@@ -0,0 +1,10 @@
+try:
+ from django.utils.encoding import force_text
+except ImportError:
+ from django.utils.encoding import force_unicode as force_text
+
+
+try:
+ from urllib2 import urlopen
+except ImportError:
+ from urllib.request import urlopen
View
4 tests/conftest.py
@@ -13,8 +13,6 @@
from django.conf import settings
-
-
from .db_helpers import create_empty_production_database, get_db_engine, DB_NAME
@@ -48,7 +46,7 @@ def django_testdir(testdir, monkeypatch):
app_source = TESTS_DIR.dirpath('app')
# Copy the test app to make it available in the new test run
- shutil.copytree(unicode(app_source), unicode(tpkg_path.join('app')))
+ shutil.copytree(py.builtin._totext(app_source), py.builtin._totext(tpkg_path.join('app')))
tpkg_path.join("db_test_settings.py").write(test_settings)
monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'tpkg.db_test_settings')
View
33 tests/db_helpers.py
@@ -1,5 +1,5 @@
import subprocess
-
+from .compat import force_text
DB_NAME = 'pytest_django_db_test'
TEST_DB_NAME = 'test_' + DB_NAME
@@ -24,17 +24,29 @@ def run_cmd(*args):
return CmdResult(ret, stdoutdata, stderrdata)
+def run_mysql(*args):
+ from django.conf import settings
+ user = settings.DATABASES['default'].get('USER', None)
+ if user:
+ args = ('-u', user) + tuple(args)
+ args = ('mysql',) + tuple(args)
+ return run_cmd(*args)
+
+
def create_empty_production_database():
drop_database(name=DB_NAME)
if get_db_engine() == 'postgresql_psycopg2':
r = run_cmd('psql', 'postgres', '-c', 'CREATE DATABASE %s' % DB_NAME)
- assert 'CREATE DATABASE' in r.std_out or 'already exists' in r.std_err
+ assert ('CREATE DATABASE' in force_text(r.std_out) or
+ 'already exists' in force_text(r.std_err))
return
if get_db_engine() == 'mysql':
- r = run_cmd('mysql', '-e', 'CREATE DATABASE %s' % DB_NAME)
- assert r.status_code == 0 or 'database exists' in r.std_out
+ r = run_mysql('-e', 'CREATE DATABASE %s' % DB_NAME)
+ assert (r.status_code == 0 or
+ 'database exists' in force_text(r.std_out) or
+ 'database exists' in force_text(r.std_err))
return
raise AssertionError('%s cannot be tested properly' % get_db_engine())
@@ -43,12 +55,13 @@ def create_empty_production_database():
def drop_database(name=TEST_DB_NAME):
if get_db_engine() == 'postgresql_psycopg2':
r = run_cmd('psql', 'postgres', '-c', 'DROP DATABASE %s' % name)
- assert 'DROP DATABASE' in r.std_out or 'does not exist' in r.std_err
+ assert ('DROP DATABASE' in force_text(r.std_out) or
+ 'does not exist' in force_text(r.std_err))
return
if get_db_engine() == 'mysql':
- r = run_cmd('mysql', '-u', 'root', '-e', 'DROP DATABASE %s' % name)
- assert ('database doesn\'t exist' in r.std_err
+ r = run_mysql('-e', 'DROP DATABASE %s' % name)
+ assert ('database doesn\'t exist' in force_text(r.std_err)
or r.status_code == 0)
return
@@ -61,7 +74,7 @@ def db_exists():
return r.status_code == 0
if get_db_engine() == 'mysql':
- r = run_cmd('psql', TEST_DB_NAME, '-e', 'SELECT 1')
+ r = run_mysql(TEST_DB_NAME, '-e', 'SELECT 1')
return r.status_code == 0
raise AssertionError('%s cannot be tested properly!' % get_db_engine())
@@ -74,7 +87,7 @@ def mark_database():
return
if get_db_engine() == 'mysql':
- r = run_cmd('mysql', TEST_DB_NAME, '-e', 'CREATE TABLE mark_table(kaka int);')
+ r = run_mysql(TEST_DB_NAME, '-e', 'CREATE TABLE mark_table(kaka int);')
assert r.status_code == 0
return
@@ -89,7 +102,7 @@ def mark_exists():
return bool(r.std_out)
if get_db_engine() == 'mysql':
- r = run_cmd('mysql', TEST_DB_NAME, '-e', 'SELECT 1 FROM mark_table')
+ r = run_mysql(TEST_DB_NAME, '-e', 'SELECT 1 FROM mark_table')
return r.status_code == 0
View
2 tests/settings_mysql.py
@@ -1,4 +1,4 @@
-from settings_base import *
+from tests.settings_base import *
DATABASES = {
'default': {
View
2 tests/settings_postgres.py
@@ -1,4 +1,4 @@
-from settings_base import *
+from tests.settings_base import *
# PyPy compatibility
try:
View
2 tests/settings_sqlite.py
@@ -1,4 +1,4 @@
-from settings_base import *
+from tests.settings_base import *
DATABASES = {
'default': {
View
2 tests/test_db_setup.py
@@ -19,7 +19,7 @@ def test_db_reuse(django_testdir):
create_test_module(django_testdir, '''
import pytest
-from app.models import Item
+from .app.models import Item
@pytest.mark.django_db
def test_db_can_be_accessed():
View
3 tests/test_django_settings_module.py
@@ -74,8 +74,7 @@ def test_ds_non_existent(testdir, monkeypatch):
monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'DOES_NOT_EXIST')
testdir.makepyfile('def test_ds(): pass')
result = testdir.runpytest()
- result.stderr.fnmatch_lines(['''*Could not import settings 'DOES_NOT_EXIST' (Is it on sys.path?): No module named DOES_NOT_EXIST*'''])
-
+ result.stderr.fnmatch_lines(['''*Could not import settings 'DOES_NOT_EXIST' (Is it on sys.path?):*'''])
def test_django_settings_configure(testdir, monkeypatch):
"""
View
2 tests/test_environment.py
@@ -3,7 +3,7 @@
import pytest
from django.core import mail
from django.db import connection
-from app.models import Item
+from .app.models import Item
# It doesn't matter which order all the _again methods are run, we just need
View
38 tests/test_fixtures.py
@@ -6,15 +6,15 @@
from __future__ import with_statement
-import urllib
-
+import py
import django
import pytest
from django.conf import settings as real_settings
from django.test.client import Client, RequestFactory
from .app.models import Item
from .test_database import noop_transactions
+from .compat import force_text, urlopen
django # Avoid pyflakes complaints
@@ -27,12 +27,14 @@ def test_client(client):
@pytest.mark.django_db
def test_admin_client(admin_client):
assert isinstance(admin_client, Client)
- assert admin_client.get('/admin-required/').content == 'You are an admin'
+ resp = admin_client.get('/admin-required/')
+ assert force_text(resp.content) == 'You are an admin'
def test_admin_client_no_db_marker(admin_client):
assert isinstance(admin_client, Client)
- assert admin_client.get('/admin-required/').content == 'You are an admin'
+ resp = admin_client.get('/admin-required/')
+ assert force_text(resp.content) == 'You are an admin'
def test_rf(rf):
@@ -81,29 +83,29 @@ class TestLiveServer:
pytest.mark.skipif('django.VERSION[:2] < (1, 4)'),
pytest.mark.urls('tests.urls_liveserver'),
]
-
+
def test_url(self, live_server):
- assert live_server.url == unicode(live_server)
+ assert live_server.url == force_text(live_server)
def test_transactions(self, live_server):
assert not noop_transactions()
def test_db_changes_visibility(self, live_server):
- response_data = urllib.urlopen(live_server + '/item_count/').read()
- assert response_data == 'Item count: 0'
+ response_data = urlopen(live_server + '/item_count/').read()
+ assert force_text(response_data) == 'Item count: 0'
Item.objects.create(name='foo')
- response_data = urllib.urlopen(live_server + '/item_count/').read()
- assert response_data == 'Item count: 1'
+ response_data = urlopen(live_server + '/item_count/').read()
+ assert force_text(response_data) == 'Item count: 1'
def test_fixture_db(self, db, live_server):
Item.objects.create(name='foo')
- response_data = urllib.urlopen(live_server + '/item_count/').read()
- assert response_data == 'Item count: 1'
+ response_data = urlopen(live_server + '/item_count/').read()
+ assert force_text(response_data) == 'Item count: 1'
def test_fixture_transactional_db(self, transactional_db, live_server):
Item.objects.create(name='foo')
- response_data = urllib.urlopen(live_server + '/item_count/').read()
- assert response_data == 'Item count: 1'
+ response_data = urlopen(live_server + '/item_count/').read()
+ assert force_text(response_data) == 'Item count: 1'
@pytest.fixture
def item(self):
@@ -123,13 +125,13 @@ def item_db(self, db):
return Item.objects.create(name='foo')
def test_item_db(self, item_db, live_server):
- response_data = urllib.urlopen(live_server + '/item_count/').read()
- assert response_data == 'Item count: 1'
+ response_data = urlopen(live_server + '/item_count/').read()
+ assert force_text(response_data) == 'Item count: 1'
@pytest.fixture
def item_transactional_db(self, transactional_db):
return Item.objects.create(name='foo')
def test_item_transactional_db(self, item_transactional_db, live_server):
- response_data = urllib.urlopen(live_server + '/item_count/').read()
- assert response_data == 'Item count: 1'
+ response_data = urlopen(live_server + '/item_count/').read()
+ assert force_text(response_data) == 'Item count: 1'
View
10 tests/test_unittest.py
@@ -1,10 +1,10 @@
import pytest
from django.test import TestCase
-from app.models import Item
-
+from .app.models import Item
from .conftest import create_test_module
+from .compat import force_text
class TestFixtures(TestCase):
@@ -65,8 +65,8 @@ class TestUrls(TestCase):
urls = 'tests.urls_unittest'
def test_urls(self):
- self.assertEqual(self.client.get('/test_url/').content,
- 'Test URL works!')
+ resp = self.client.get('/test_url/')
+ self.assertEqual(force_text(resp.content), 'Test URL works!')
def test_sole_test(django_testdir):
@@ -79,7 +79,7 @@ def test_sole_test(django_testdir):
from django.test import TestCase
from django.conf import settings
-from app.models import Item
+from .app.models import Item
class TestFoo(TestCase):
def test_foo(self):
View
3 tests/test_urls.py
@@ -1,5 +1,6 @@
import pytest
from django.conf import settings
+from .compat import force_text
try:
from django.core.urlresolvers import is_valid_path
@@ -29,4 +30,4 @@ def test_urls():
@pytest.mark.urls('tests.urls_overridden')
def test_urls_client(client):
response = client.get('/overridden_url/')
- assert response.content == 'Overridden urlconf works!'
+ assert force_text(response.content) == 'Overridden urlconf works!'
View
2 tests/urls_liveserver.py
@@ -1,7 +1,7 @@
from django.conf.urls.defaults import patterns, url
from django.http import HttpResponse
-from app.models import Item
+from .app.models import Item
urlpatterns = patterns('',
url(r'^item_count/$',
View
22 tox.ini
@@ -50,13 +50,25 @@ deps =
basepython = python2.6
deps =
pytest==2.3.4
- https://www.djangoproject.com/download/1.5b2/tarball/#egg=django
+ https://www.djangoproject.com/download/1.5c1/tarball/#egg=django
[testenv:py27-1.5.X]
basepython = python2.7
deps =
pytest==2.3.4
- https://www.djangoproject.com/download/1.5b2/tarball/#egg=django
+ https://www.djangoproject.com/download/1.5c1/tarball/#egg=django
+
+[testenv:py32-1.5.X]
+basepython = python3.2
+deps =
+ pytest==2.3.4
+ https://www.djangoproject.com/download/1.5c1/tarball/#egg=django
+
+[testenv:py33-1.5.X]
+basepython = python3.3
+deps =
+ pytest==2.3.4
+ https://www.djangoproject.com/download/1.5c1/tarball/#egg=django
[testenv:pypy-1.3.X]
basepython = pypy
@@ -69,3 +81,9 @@ basepython = pypy
deps =
pytest==2.3.4
Django==1.4
+
+[testenv:pypy-1.5.X]
+basepython = pypy
+deps =
+ pytest==2.3.4
+ https://www.djangoproject.com/download/1.5c1/tarball/#egg=django

0 comments on commit 0723bc6

Please sign in to comment.