您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

test_loading.py 8.8KB

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