diff --git a/.travis.yml b/.travis.yml index 89da675..81b5e15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: python python: - - "2.6" - "2.7" sudo: false @@ -10,6 +9,7 @@ env: - DJANGO=1.5.12 POSTGRES_TEST_USER=postgres POSTGRES_TEST_NAME=avocado MYSQL_TEST_USER=root MYSQL_TEST_NAME=avocado - DJANGO=1.6.10 POSTGRES_TEST_USER=postgres POSTGRES_TEST_NAME=avocado MYSQL_TEST_USER=root MYSQL_TEST_NAME=avocado - DJANGO=1.7.6 POSTGRES_TEST_USER=postgres POSTGRES_TEST_NAME=avocado MYSQL_TEST_USER=root MYSQL_TEST_NAME=avocado + - DJANGO=1.8.16 POSTGRES_TEST_USER=postgres POSTGRES_TEST_NAME=avocado MYSQL_TEST_USER=root MYSQL_TEST_NAME=avocado services: - memcached diff --git a/avocado/core/backup.py b/avocado/core/backup.py index 51ace98..de0227d 100644 --- a/avocado/core/backup.py +++ b/avocado/core/backup.py @@ -102,24 +102,22 @@ def load_fixture(name, using=DEFAULT_DB_ALIAS): with open(fixture_path) as fixture: objects = serializers.deserialize(FIXTURE_FORMAT, fixture, using=using) - with transaction.commit_manually(using): - for obj in objects: - if ( - hasattr(router, "allow_migrate") and - router.allow_migrate(using, obj.object.__class__) - ) or ( - hasattr(router, "allow_syncdb") and - router.allow_syncdb(using, obj.object.__class__) - ): - try: + try: + with transaction.atomic(using): + for obj in objects: + if ( + hasattr(router, "allow_migrate") and + router.allow_migrate(using, obj.object.__class__) + ) or ( + hasattr(router, "allow_syncdb") and + router.allow_syncdb(using, obj.object.__class__) + ): obj.save(using=using) - except (DatabaseError, IntegrityError), e: - transaction.rollback(using) - msg = u'Could not load {0}.{1}(pk={2}): {3}'.format( - obj.object._meta.app_label, - obj.object._meta.object_name, obj.object.pk, e) - raise e.__class__, e.__class__(msg), sys.exc_info()[2] - transaction.commit(using) + except (DatabaseError, IntegrityError), e: + msg = u'Could not load {0}.{1}(pk={2}): {3}'.format( + obj.object._meta.app_label, + obj.object._meta.object_name, obj.object.pk, e) + raise e.__class__, e.__class__(msg), sys.exc_info()[2] log.info(u'Loaded data from fixture {0}'.format(name)) @@ -139,23 +137,21 @@ def safe_load(name, backup_path=None, using=DEFAULT_DB_ALIAS): """ _check_app() - with transaction.commit_manually(using): - # Create the backup fixture - if backup_path: - create_fixture(os.path.abspath(backup_path), using=using, - silent=True) - else: - backup_path = create_temp_fixture(using=using, silent=True) - log.info(u'Backup fixture written to {0}'.format(os.path.abspath( - backup_path))) - delete_metadata(using=using) - try: + try: + with transaction.atomic(using): + # Create the backup fixture + if backup_path: + create_fixture(os.path.abspath(backup_path), using=using, + silent=True) + else: + backup_path = create_temp_fixture(using=using, silent=True) + log.info(u'Backup fixture written to {0}'.format(os.path.abspath( + backup_path))) + delete_metadata(using=using) load_fixture(name, using=using) - except (DatabaseError, IntegrityError): - transaction.rollback(using) - log.error(u'Fixture load failed, reverting from backup: {0}' - .format(backup_path)) - load_fixture(os.path.abspath(backup_path), using=using) - raise - transaction.commit(using) + except (DatabaseError, IntegrityError): + log.error(u'Fixture load failed, reverting from backup: {0}' + .format(backup_path)) + load_fixture(os.path.abspath(backup_path), using=using) + raise return backup_path diff --git a/avocado/core/cache/model.py b/avocado/core/cache/model.py index eb621dc..ff69ae2 100644 --- a/avocado/core/cache/model.py +++ b/avocado/core/cache/model.py @@ -108,7 +108,7 @@ def instance_cache_key(instance, label=None, version=None, args=None, version = version(instance) opts = instance._meta - key = [opts.app_label, opts.module_name, instance.pk] + key = [opts.app_label, opts.model_name, instance.pk] if label is not None: key.append(label) diff --git a/avocado/history/managers.py b/avocado/history/managers.py index 169a751..cab5c1d 100644 --- a/avocado/history/managers.py +++ b/avocado/history/managers.py @@ -69,7 +69,7 @@ def object_has_changed(self, obj, model=None, fields=None): return True return bool(revision.diff(obj, fields=fields)) - @transaction.commit_on_success + @transaction.atomic def create_revision(self, obj, fields, model=None, commit=True, deleted=False, **kwargs): """Creates a revision for the object. @@ -118,7 +118,7 @@ def create_revision(self, obj, fields, model=None, commit=True, revision.save() return revision - @transaction.commit_on_success + @transaction.atomic def revert(self, obj, model=None, commit=True): "Revert object to last revision." revision = self.get_latest_for_object(obj, model=model) @@ -126,7 +126,7 @@ def revert(self, obj, model=None, commit=True): revision.apply(obj, commit=commit) return obj - @transaction.commit_on_success + @transaction.atomic def cull_for_object(self, obj, model=None, max_size=None): """Culls revisions for an object down to `max_size`. diff --git a/avocado/management/commands/avocado.py b/avocado/management/commands/avocado.py index bd2a8ed..1e44c4b 100644 --- a/avocado/management/commands/avocado.py +++ b/avocado/management/commands/avocado.py @@ -17,6 +17,9 @@ class Command(BaseCommand): 'migration': 'migration', } + def add_arguments(self, parser): + parser.add_argument('subcommands', metavar='N', nargs='+') + def print_subcommands(self, prog_name): usage = ['', 'Available subcommands:'] for name in sorted(self.commands.keys()): @@ -63,6 +66,7 @@ def run_from_argv(self, argv): self.execute(*args, **options.__dict__) def handle(self, *args, **options): + args = options['subcommands'] if not args or args[0] not in self.commands.keys(): return self.print_help('./manage.py', 'avocado') subcommand, args = args[0], args[1:] diff --git a/avocado/management/subcommands/cache.py b/avocado/management/subcommands/cache.py index 131f189..e13d316 100644 --- a/avocado/management/subcommands/cache.py +++ b/avocado/management/subcommands/cache.py @@ -48,7 +48,7 @@ class Command(DataFieldCommand): .format(METHOD_CHOICES)), ) - @transaction.commit_on_success + @transaction.atomic def _handle_field_method(self, f, method, flush): func = getattr(f, method) diff --git a/avocado/management/subcommands/history.py b/avocado/management/subcommands/history.py index d225c4e..714a5a2 100644 --- a/avocado/management/subcommands/history.py +++ b/avocado/management/subcommands/history.py @@ -18,7 +18,7 @@ class Command(BaseCommand): 'HISTORY_MAX_SIZE.'), ) - @transaction.commit_on_success + @transaction.atomic def handle(self, *args, **options): cull = options.get('cull') max_size = options.get('max_size', settings.HISTORY_MAX_SIZE) diff --git a/avocado/managers.py b/avocado/managers.py index 684d837..12c8dad 100644 --- a/avocado/managers.py +++ b/avocado/managers.py @@ -249,7 +249,7 @@ class DataConceptManager(PublishedManager, DataConceptSearchMixin): def get_query_set(self): return DataConceptQuerySet(self.model, using=self._db) - @transaction.commit_on_success + @transaction.atomic def create_from_field(self, field, save=True, **kwargs): """Derives a DataConcept from this DataField's descriptors. Additional keyword arguments can be passed in to customize the new DataConcept diff --git a/avocado/stats/agg.py b/avocado/stats/agg.py index ede43a5..b5ad049 100644 --- a/avocado/stats/agg.py +++ b/avocado/stats/agg.py @@ -2,7 +2,7 @@ from django.db import models from django.db.models import Q, Count, Sum, Avg, Max, Min, StdDev, Variance from django.db.models.query import REPR_OUTPUT_SIZE, QuerySet -from modeltree.compat import LOOKUP_SEP +from django.db.models.constants import LOOKUP_SEP from modeltree.utils import M diff --git a/requirements.txt b/requirements.txt index bf1e0da..817ba3a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,9 @@ -Django>=1.5.12,<=1.7.6 -South==1.0.2 +Django==1.8.16 django-guardian==1.2.5 django-haystack==2.3.1 Whoosh==2.6.0 jsonfield==1.0.0 -modeltree==1.1.9 +modeltree==2.0.0 openpyxl==2.1.4 python-memcached==1.53 ordereddict diff --git a/test_suite.py b/test_suite.py index 53f064b..270e468 100644 --- a/test_suite.py +++ b/test_suite.py @@ -33,17 +33,17 @@ if not apps: apps = [ - 'core', - 'exporting', - 'formatters', - 'events', - 'history', - 'models', - 'query', - 'stats', - 'search', - 'subcommands', - 'validation', + 'tests.cases.core.tests', + 'tests.cases.exporting.tests', + 'tests.cases.formatters.tests', + 'tests.cases.events_test.tests', + 'tests.cases.history.tests', + 'tests.cases.models.tests', + 'tests.cases.query.tests', + 'tests.cases.search.tests', + 'tests.cases.stats.tests', + 'tests.cases.subcommands.tests', + 'tests.cases.validation.tests' ] management.call_command('test', *apps) diff --git a/tests/runner.py b/tests/runner.py index 061db79..c293a33 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -1,10 +1,14 @@ import sys import cProfile import unittest -from django.test.simple import DjangoTestSuiteRunner +from django.test.runner import DiscoverRunner -class ProfilingTestRunner(DjangoTestSuiteRunner): +class ProfilingTestRunner(DiscoverRunner): + def __init__(self, *args, **kwargs): + kwargs['pattern'] = "**/*.py" + super(ProfilingTestRunner, self).__init__(*args, **kwargs) + def run_suite(self, suite, **kwargs): stream = open('profiled_tests.txt', 'w')