Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

test_loading.py 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. from os.path import dirname
  2. import sys
  3. from django.apps import AppConfig, apps
  4. from django.test import override_settings, TestCase
  5. from django.conf import settings
  6. from oscar.core.loading import (
  7. get_model, AppNotFoundError, get_classes, get_class, get_class_loader,
  8. ClassNotFoundError)
  9. from tests import temporary_python_path
  10. from tests._site.loader import DummyClass
  11. class TestClassLoading(TestCase):
  12. """
  13. Oscar's class loading utilities
  14. """
  15. def test_load_oscar_classes_correctly(self):
  16. Product, Category = get_classes('catalogue.models', ('Product', 'Category'))
  17. self.assertEqual('oscar.apps.catalogue.models', Product.__module__)
  18. self.assertEqual('oscar.apps.catalogue.models', Category.__module__)
  19. def test_load_oscar_class_correctly(self):
  20. Product = get_class('catalogue.models', 'Product')
  21. self.assertEqual('oscar.apps.catalogue.models', Product.__module__)
  22. def test_load_oscar_class_from_dashboard_subapp(self):
  23. ReportForm = get_class('dashboard.reports.forms', 'ReportForm')
  24. self.assertEqual('oscar.apps.dashboard.reports.forms', ReportForm.__module__)
  25. def test_raise_exception_when_bad_appname_used(self):
  26. with self.assertRaises(AppNotFoundError):
  27. get_classes('fridge.models', ('Product', 'Category'))
  28. def test_raise_exception_when_bad_classname_used(self):
  29. with self.assertRaises(ClassNotFoundError):
  30. get_class('catalogue.models', 'Monkey')
  31. def test_raise_importerror_if_app_raises_importerror(self):
  32. """
  33. This tests that Oscar doesn't fall back to using the Oscar core
  34. app class if the overriding app class throws an ImportError.
  35. "get_class()" returns None in this case, since there is no such named
  36. class in the core app. We use this fictitious class because classes in
  37. the "models" and "views" modules (along with modules they are related
  38. to) are imported as part of the Django app-loading process, which is
  39. triggered when we override the INSTALLED_APPS setting.
  40. """
  41. apps = list(settings.INSTALLED_APPS)
  42. apps[apps.index('tests._site.apps.catalogue')] = 'tests._site.import_error_app.catalogue'
  43. with override_settings(INSTALLED_APPS=apps):
  44. with self.assertRaises(ImportError):
  45. get_class('catalogue.import_error_module', 'ImportErrorClass')
  46. class ClassLoadingWithLocalOverrideTests(TestCase):
  47. def setUp(self):
  48. self.installed_apps = list(settings.INSTALLED_APPS)
  49. self.installed_apps[self.installed_apps.index('oscar.apps.shipping')] = 'tests._site.apps.shipping'
  50. def test_loading_class_defined_in_local_module(self):
  51. with override_settings(INSTALLED_APPS=self.installed_apps):
  52. (Free,) = get_classes('shipping.methods', ('Free',))
  53. self.assertEqual('tests._site.apps.shipping.methods', Free.__module__)
  54. def test_loading_class_which_is_not_defined_in_local_module(self):
  55. with override_settings(INSTALLED_APPS=self.installed_apps):
  56. (FixedPrice,) = get_classes('shipping.methods', ('FixedPrice',))
  57. self.assertEqual('oscar.apps.shipping.methods', FixedPrice.__module__)
  58. def test_loading_class_from_module_not_defined_in_local_app(self):
  59. with override_settings(INSTALLED_APPS=self.installed_apps):
  60. (Repository,) = get_classes('shipping.repository', ('Repository',))
  61. self.assertEqual('oscar.apps.shipping.repository', Repository.__module__)
  62. def test_loading_classes_defined_in_both_local_and_oscar_modules(self):
  63. with override_settings(INSTALLED_APPS=self.installed_apps):
  64. (Free, FixedPrice) = get_classes('shipping.methods', ('Free', 'FixedPrice'))
  65. self.assertEqual('tests._site.apps.shipping.methods', Free.__module__)
  66. self.assertEqual('oscar.apps.shipping.methods', FixedPrice.__module__)
  67. def test_loading_classes_with_root_app(self):
  68. import tests._site.shipping
  69. path = dirname(dirname(tests._site.shipping.__file__))
  70. with temporary_python_path([path]):
  71. self.installed_apps[
  72. self.installed_apps.index('tests._site.apps.shipping')] = 'shipping'
  73. with override_settings(INSTALLED_APPS=self.installed_apps):
  74. (Free,) = get_classes('shipping.methods', ('Free',))
  75. self.assertEqual('shipping.methods', Free.__module__)
  76. def test_overriding_view_is_possible_without_overriding_app(self):
  77. # If test fails, it's helpful to know if it's caused by order of
  78. # execution
  79. customer_app_config = AppConfig.create('oscar.apps.customer')
  80. customer_app_config.ready()
  81. self.assertEqual(customer_app_config.summary_view.__module__,
  82. 'tests._site.apps.customer.views')
  83. self.assertEqual(apps.get_app_config('customer').summary_view.__module__,
  84. 'tests._site.apps.customer.views')
  85. class ClassLoadingWithLocalOverrideWithMultipleSegmentsTests(TestCase):
  86. def setUp(self):
  87. self.installed_apps = list(settings.INSTALLED_APPS)
  88. self.installed_apps[self.installed_apps.index('oscar.apps.shipping')] = 'tests._site.apps.shipping'
  89. def test_loading_class_defined_in_local_module(self):
  90. with override_settings(INSTALLED_APPS=self.installed_apps):
  91. (Free,) = get_classes('shipping.methods', ('Free',))
  92. self.assertEqual('tests._site.apps.shipping.methods', Free.__module__)
  93. class TestOverridingCoreApps(TestCase):
  94. def test_means_the_overriding_model_is_registered_first(self):
  95. klass = get_model('partner', 'StockRecord')
  96. self.assertEqual(
  97. 'tests._site.apps.partner.models', klass.__module__)
  98. class TestAppLabelsForModels(TestCase):
  99. def test_all_oscar_models_have_app_labels(self):
  100. from django.apps import apps
  101. models = apps.get_models()
  102. missing = []
  103. for model in models:
  104. # Ignore non-Oscar models
  105. if 'oscar' not in repr(model):
  106. continue
  107. # Don't know how to get the actual model's Meta class. But if
  108. # the parent doesn't have a Meta class, it's doesn't have an
  109. # base in Oscar anyway and is not intended to be overridden
  110. abstract_model = model.__base__
  111. meta_class = getattr(abstract_model, 'Meta', None)
  112. if meta_class is None:
  113. continue
  114. if not hasattr(meta_class, 'app_label'):
  115. missing.append(model)
  116. if missing:
  117. self.fail("Those models don't have an app_label set: %s" % missing)
  118. class TestDynamicLoadingOn3rdPartyApps(TestCase):
  119. core_app_prefix = 'thirdparty_package.apps'
  120. def setUp(self):
  121. self.installed_apps = list(settings.INSTALLED_APPS)
  122. sys.path.append('./tests/_site/')
  123. def tearDown(self):
  124. sys.path.remove('./tests/_site/')
  125. def test_load_core_3rd_party_class_correctly(self):
  126. self.installed_apps.append('thirdparty_package.apps.myapp')
  127. with override_settings(INSTALLED_APPS=self.installed_apps):
  128. Cow, Goat = get_classes('myapp.models', ('Cow', 'Goat'), self.core_app_prefix)
  129. self.assertEqual('thirdparty_package.apps.myapp.models', Cow.__module__)
  130. self.assertEqual('thirdparty_package.apps.myapp.models', Goat.__module__)
  131. def test_load_overriden_3rd_party_class_correctly(self):
  132. self.installed_apps.append('tests._site.apps.myapp')
  133. with override_settings(INSTALLED_APPS=self.installed_apps):
  134. Cow, Goat = get_classes('myapp.models', ('Cow', 'Goat'), self.core_app_prefix)
  135. self.assertEqual('thirdparty_package.apps.myapp.models', Cow.__module__)
  136. self.assertEqual('tests._site.apps.myapp.models', Goat.__module__)
  137. class OverriddenClassLoadingTestCase(TestCase):
  138. def test_non_override_class_loader(self):
  139. from oscar.apps.catalogue.views import ProductDetailView
  140. View = get_class('catalogue.views', 'ProductDetailView')
  141. self.assertEqual(View, ProductDetailView)
  142. @override_settings(OSCAR_DYNAMIC_CLASS_LOADER='tests._site.loader.custom_class_loader')
  143. def test_override_class_loader(self):
  144. # Clear lru cache for the class loader
  145. get_class_loader.cache_clear()
  146. View = get_class('catalogue.views', 'ProductDetailView')
  147. self.assertEqual(View, DummyClass)
  148. # Clear lru cache for the class loader again
  149. get_class_loader.cache_clear()