diff --git a/setup.py b/setup.py index ec7bc7d..f8b9d5f 100755 --- a/setup.py +++ b/setup.py @@ -5,11 +5,11 @@ from setuptools import find_packages, setup install_requires=[ - 'django-oscar>=1.1.1', 'python-dateutil>=2.4,<3.0', ] tests_require = [ + 'django-oscar>=1.1.1', 'django-webtest==1.7.8', 'pytest==2.9.0', 'pytest-cov==2.1.0', diff --git a/src/oscar_accounts/abstract_models.py b/src/oscar_accounts/abstract_models.py index 2918b8b..b6f744a 100644 --- a/src/oscar_accounts/abstract_models.py +++ b/src/oscar_accounts/abstract_models.py @@ -8,10 +8,10 @@ from django.utils import six, timezone from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ -from oscar.core.compat import AUTH_USER_MODEL from treebeard.mp_tree import MP_Node from oscar_accounts import exceptions +from oscar_accounts.compact_oscar import AUTH_USER_MODEL class ActiveAccountManager(models.Manager): diff --git a/src/oscar_accounts/api/app.py b/src/oscar_accounts/api/app.py index 70acda3..e8897e6 100644 --- a/src/oscar_accounts/api/app.py +++ b/src/oscar_accounts/api/app.py @@ -1,8 +1,8 @@ from django.conf.urls import patterns, url from django.views.decorators.csrf import csrf_exempt -from oscar.core.application import Application from oscar_accounts.api import decorators, views +from oscar_accounts.compact_oscar import Application class APIApplication(Application): diff --git a/src/oscar_accounts/api/views.py b/src/oscar_accounts/api/views.py index a2d31d5..db4939d 100644 --- a/src/oscar_accounts/api/views.py +++ b/src/oscar_accounts/api/views.py @@ -9,10 +9,10 @@ from django.shortcuts import get_object_or_404 from django.utils import timezone from django.views import generic -from oscar.core.loading import get_model from oscar_accounts import codes, exceptions, facade, names from oscar_accounts.api import errors +from oscar_accounts.compact_oscar import get_model Account = get_model('oscar_accounts', 'Account') AccountType = get_model('oscar_accounts', 'AccountType') diff --git a/src/oscar_accounts/checkout/forms.py b/src/oscar_accounts/checkout/forms.py index 662e158..544700e 100644 --- a/src/oscar_accounts/checkout/forms.py +++ b/src/oscar_accounts/checkout/forms.py @@ -2,8 +2,8 @@ from django import forms from django.utils.translation import ugettext_lazy as _ -from oscar.core.loading import get_model -from oscar.templatetags.currency_filters import currency + +from oscar_accounts.compact_oscar import get_model, currency Account = get_model('oscar_accounts', 'Account') diff --git a/src/oscar_accounts/checkout/gateway.py b/src/oscar_accounts/checkout/gateway.py index 64de26d..33b6d37 100644 --- a/src/oscar_accounts/checkout/gateway.py +++ b/src/oscar_accounts/checkout/gateway.py @@ -1,8 +1,7 @@ from django.utils.translation import ugettext_lazy as _ -from oscar.apps.payment.exceptions import UnableToTakePayment -from oscar.core.loading import get_model from oscar_accounts import codes, core, exceptions, facade +from oscar_accounts.compact_oscar import get_model, UnableToTakePayment Account = get_model('oscar_accounts', 'Account') Transfer = get_model('oscar_accounts', 'Transfer') diff --git a/src/oscar_accounts/codes.py b/src/oscar_accounts/codes.py index 4b50473..9803d37 100644 --- a/src/oscar_accounts/codes.py +++ b/src/oscar_accounts/codes.py @@ -1,7 +1,7 @@ import random import string -from oscar.core.loading import get_model +from oscar_accounts.compact_oscar import get_model Account = get_model('oscar_accounts', 'Account') diff --git a/src/oscar_accounts/compact_oscar.py b/src/oscar_accounts/compact_oscar.py new file mode 100644 index 0000000..d865ff0 --- /dev/null +++ b/src/oscar_accounts/compact_oscar.py @@ -0,0 +1,95 @@ +try: + import oscar.core + +except ImportError: + from importlib import import_module + from django.apps import apps + from django.apps.config import MODELS_MODULE_NAME + from django.conf import settings + from django.core.exceptions import ImproperlyConfigured, AppRegistryNotReady + from django import forms + + # from oscar.core.compat + # A setting that can be used in foreign key declarations + AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') + try: + AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME = AUTH_USER_MODEL.rsplit('.', 1) + except ValueError: + raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form" + " 'app_label.model_name'") + + # from oscar.core.loading + def get_model(app_label, model_name): + """ + Fetches a Django model using the app registry. + This doesn't require that an app with the given app label exists, + which makes it safe to call when the registry is being populated. + All other methods to access models might raise an exception about the + registry not being ready yet. + Raises LookupError if model isn't found. + """ + try: + return apps.get_model(app_label, model_name) + except AppRegistryNotReady: + if apps.apps_ready and not apps.models_ready: + # If this function is called while `apps.populate()` is + # loading models, ensure that the module that defines the + # target model has been imported and try looking the model up + # in the app registry. This effectively emulates + # `from path.to.app.models import Model` where we use + # `Model = get_model('app', 'Model')` instead. + app_config = apps.get_app_config(app_label) + # `app_config.import_models()` cannot be used here because it + # would interfere with `apps.populate()`. + import_module('%s.%s' % (app_config.name, MODELS_MODULE_NAME)) + # In order to account for case-insensitivity of model_name, + # look up the model through a private API of the app registry. + return apps.get_registered_model(app_label, model_name) + else: + # This must be a different case (e.g. the model really doesn't + # exist). We just re-raise the exception. + raise + + + # from oscar.core.loading + def is_model_registered(app_label, model_name): + """ + Checks whether a given model is registered. This is used to only + register Oscar models if they aren't overridden by a forked app. + """ + try: + apps.get_registered_model(app_label, model_name) + except LookupError: + return False + else: + return True + + # from oscar.apps.payment.exceptions + class UnableToTakePayment(Exception): + """ + Exception to be used for ANTICIPATED payment errors (eg card number wrong, + expiry date has passed). The message passed here will be shown to the end + user. + """ + + # dummy for oscar.templatetags.currency_filters.currency + def currency(value, currency=None): + return value + + # dummy for oscar.forms.widgets.DatePickerInput + DatePickerInput = forms.DateInput + + # dummy for oscar.application.Application + class Application(object): + def post_process_urls(self, urlpatterns): + return urlpatterns + + +else: # oscar is installed, use it. + from oscar.apps.payment.exceptions import UnableToTakePayment + from oscar.core.application import Application + from oscar.core.compat import AUTH_USER_MODEL + from oscar.core.loading import get_model, is_model_registered + from oscar.forms.widgets import DatePickerInput + from oscar.templatetags.currency_filters import currency + diff --git a/src/oscar_accounts/core.py b/src/oscar_accounts/core.py index f08e67d..1c9e35c 100644 --- a/src/oscar_accounts/core.py +++ b/src/oscar_accounts/core.py @@ -1,4 +1,4 @@ -from oscar.core.loading import get_model +from oscar_accounts.compact_oscar import get_model from oscar_accounts import names diff --git a/src/oscar_accounts/dashboard/app.py b/src/oscar_accounts/dashboard/app.py index 1152bc1..52f43b3 100644 --- a/src/oscar_accounts/dashboard/app.py +++ b/src/oscar_accounts/dashboard/app.py @@ -1,7 +1,7 @@ from django.conf.urls import patterns, url from django.contrib.admin.views.decorators import staff_member_required -from oscar.core.application import Application +from oscar_accounts.compact_oscar import Application from oscar_accounts.dashboard import views diff --git a/src/oscar_accounts/dashboard/forms.py b/src/oscar_accounts/dashboard/forms.py index 8c189a1..0a05d6c 100644 --- a/src/oscar_accounts/dashboard/forms.py +++ b/src/oscar_accounts/dashboard/forms.py @@ -4,11 +4,9 @@ from django.conf import settings from django.core import exceptions from django.utils.translation import ugettext_lazy as _ -from oscar.core.loading import get_model -from oscar.forms.widgets import DatePickerInput -from oscar.templatetags.currency_filters import currency from oscar_accounts import codes, names +from oscar_accounts.compact_oscar import get_model, currency, DatePickerInput Account = get_model('oscar_accounts', 'Account') AccountType = get_model('oscar_accounts', 'AccountType') diff --git a/src/oscar_accounts/dashboard/reports.py b/src/oscar_accounts/dashboard/reports.py index 39ba8d3..fb0ae4a 100644 --- a/src/oscar_accounts/dashboard/reports.py +++ b/src/oscar_accounts/dashboard/reports.py @@ -1,9 +1,9 @@ from decimal import Decimal as D from django.db.models import Sum -from oscar.core.loading import get_model from oscar_accounts import names +from oscar_accounts.compact_oscar import get_model AccountType = get_model('oscar_accounts', 'AccountType') Account = get_model('oscar_accounts', 'Account') diff --git a/src/oscar_accounts/dashboard/views.py b/src/oscar_accounts/dashboard/views.py index d54a2fc..4ae7dda 100644 --- a/src/oscar_accounts/dashboard/views.py +++ b/src/oscar_accounts/dashboard/views.py @@ -9,10 +9,9 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from django.views import generic -from oscar.core.loading import get_model -from oscar.templatetags.currency_filters import currency from oscar_accounts import exceptions, facade, names +from oscar_accounts.compact_oscar import get_model, currency from oscar_accounts.dashboard import forms, reports AccountType = get_model('oscar_accounts', 'AccountType') diff --git a/src/oscar_accounts/facade.py b/src/oscar_accounts/facade.py index 8927e40..df6b5c6 100644 --- a/src/oscar_accounts/facade.py +++ b/src/oscar_accounts/facade.py @@ -1,6 +1,6 @@ import logging -from oscar.core.loading import get_model +from oscar_accounts.compact_oscar import get_model from oscar_accounts import core, exceptions diff --git a/src/oscar_accounts/forms.py b/src/oscar_accounts/forms.py index a3d1bea..e1a1b58 100644 --- a/src/oscar_accounts/forms.py +++ b/src/oscar_accounts/forms.py @@ -1,6 +1,6 @@ from django import forms from django.utils.translation import ugettext_lazy as _ -from oscar.core.loading import get_model +from oscar_accounts.compact_oscar import get_model Account = get_model('oscar_accounts', 'Account') diff --git a/src/oscar_accounts/models.py b/src/oscar_accounts/models.py index 7f59f13..f7f6629 100644 --- a/src/oscar_accounts/models.py +++ b/src/oscar_accounts/models.py @@ -1,6 +1,5 @@ -from oscar.core.loading import is_model_registered - from oscar_accounts import abstract_models +from oscar_accounts.compact_oscar import is_model_registered if not is_model_registered('oscar_accounts', 'AccountType'): class AccountType(abstract_models.AccountType): diff --git a/src/oscar_accounts/security.py b/src/oscar_accounts/security.py index e7664b7..b1623db 100644 --- a/src/oscar_accounts/security.py +++ b/src/oscar_accounts/security.py @@ -1,4 +1,4 @@ -from oscar.core.loading import get_model +from oscar_accounts.compact_oscar import get_model IPAddressRecord = get_model('oscar_accounts', 'IPAddressRecord') diff --git a/src/oscar_accounts/setup.py b/src/oscar_accounts/setup.py index 49613ca..7c958d4 100644 --- a/src/oscar_accounts/setup.py +++ b/src/oscar_accounts/setup.py @@ -1,9 +1,10 @@ -from oscar.core.loading import get_model def create_default_accounts(): """Create the default structure""" from oscar_accounts import names + from oscar_accounts.compact_oscar import get_model + AccountType = get_model('oscar_accounts', 'AccountType') assets = AccountType.add_root(name=names.ASSETS) diff --git a/src/oscar_accounts/test_factories.py b/src/oscar_accounts/test_factories.py index d538686..1f61dfb 100644 --- a/src/oscar_accounts/test_factories.py +++ b/src/oscar_accounts/test_factories.py @@ -1,7 +1,7 @@ from decimal import Decimal as D import factory -from oscar.core.loading import get_model +from oscar_accounts.compact_oscar import get_model class AccountFactory(factory.DjangoModelFactory):