Coverage for /home/chris/workspace/django-shop/shop/backends_pool: 100.00%

# Coverage for /home/chris/workspace/django-shop/shop/backends_pool : 100.00%

## 42 statements 42 run 0 missing 0 excluded 0 partial

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #-*- coding: utf-8 -*- from django.conf import settings from shop.payment.api import PaymentAPI from shop.shipping.api import ShippingAPI from shop.util.loader import load_class class BackendsPool(object): """ A pool for backends. It handles loading backend modules (both shipping and payment backends), and keeping a cached copy of the classes in-memory (so that the backends aren't loaded from file every time one requests them) """ SHIPPING = 'SHOP_SHIPPING_BACKENDS' PAYMENT = 'SHOP_PAYMENT_BACKENDS' PAYMENT_SHOP_INTERFACE = PaymentAPI() SHIPPING_SHOP_INTERFACE = ShippingAPI() def __init__(self, use_cache=True): """ The use_cache parameter is mostly used for testing, since setting it to false will trigger reloading from disk """ self._payment_backends_list = [] self._shippment_backends_list = [] self.use_cache = use_cache def get_payment_backends_list(self): """ Returns the list of payment backends, as instances, from the list of backends defined in settings.SHOP_PAYMENT_BACKENDS """ if self._payment_backends_list and self.use_cache: return self._payment_backends_list else: self._payment_backends_list = self._load_backends_list(self.PAYMENT, self.PAYMENT_SHOP_INTERFACE) return self._payment_backends_list def get_shipping_backends_list(self): """ Returns the list of shipping backends, as instances, from the list of backends defined in settings.SHOP_SHIPPING_BACKENDS """ if self._shippment_backends_list and self.use_cache: return self._shippment_backends_list else: self._shippment_backends_list = self._load_backends_list(self.SHIPPING, self.SHIPPING_SHOP_INTERFACE) return self._shippment_backends_list def _check_backend_for_validity(self, backend_instance): """ This enforces having a valid name and url namespace defined. Backends, both shipping and payment are namespaced in respectively /pay/ and /ship/ URL spaces, so as to avoid name clashes. "Namespaces are one honking great idea -- let's do more of those!" """ backend_name = getattr(backend_instance, 'backend_name', "") if not backend_name: d_tuple = (str(backend_instance), str(type(backend_instance))) raise NotImplementedError( 'One of your backends ("%s" of type "%s") lacks a name, please define one.' % d_tuple ) url_namespace = getattr(backend_instance, 'url_namespace', "") if not url_namespace: raise NotImplementedError( 'Please set a namespace for backend "%s"' % backend_instance.backend_name) def _load_backends_list(self, setting_name, shop_object): """ This actually loads the backends from disk""" result = [] if not getattr(settings, setting_name, None): return result for backend_path in getattr(settings, setting_name, None): # The load_class function takes care of the classloading. It returns # a CLASS, not an INSTANCE! mod_class = load_class(backend_path,setting_name) # Seems like it is a real, valid class - let's instanciate it! # This is where the backends receive their self.shop reference! mod_instance = mod_class(shop=shop_object) self._check_backend_for_validity(mod_instance) # The backend seems valid (nothing raised), let's add it to the # return list. result.append(mod_instance) return result backends_pool = BackendsPool()