11from __future__ import absolute_import , unicode_literals
2- from six import string_types
32from django .core .exceptions import ImproperlyConfigured
3+ from django .core .urlresolvers import get_callable
4+ from django .utils import six
45from django .test .signals import setting_changed
5- from concurrency .utils import import_by_path
66
77
88# List Editable Policy
99# 0 do not save updated records, save others, show message to the user
1010# 1 abort whole transaction
1111
12- CONCURRENCY_POLICY_SILENT = 0
13- CONCURRENCY_POLICY_ABORT_ALL = 1
14- CONCURRENCY_POLICY_RAISE = 2
12+ CONCURRENCY_LIST_EDITABLE_POLICY_SILENT = 1
13+ CONCURRENCY_LIST_EDITABLE_POLICY_ABORT_ALL = 2
14+ CONCURRENCY_POLICY_RAISE = 4
15+ CONCURRENCY_POLICY_CALLBACK = 8
16+
17+ CONFLICTS_POLICIES = [CONCURRENCY_POLICY_RAISE , CONCURRENCY_POLICY_CALLBACK ]
18+ LIST_EDITABLE_POLICIES = [CONCURRENCY_LIST_EDITABLE_POLICY_SILENT , CONCURRENCY_LIST_EDITABLE_POLICY_ABORT_ALL ]
19+
1520
1621class AppSettings (object ):
1722 """
@@ -43,7 +48,8 @@ class AppSettings(object):
4348 defaults = {
4449 'SANITY_CHECK' : True ,
4550 'FIELD_SIGNER' : 'concurrency.forms.VersionFieldSigner' ,
46- 'POLICY' : CONCURRENCY_POLICY_SILENT ,
51+ 'POLICY' : CONCURRENCY_LIST_EDITABLE_POLICY_SILENT | CONCURRENCY_POLICY_RAISE ,
52+ 'CALLBACK' : 'concurrency.views.callback' ,
4753 'HANDLER409' : 'concurrency.views.conflict' }
4854
4955 def __init__ (self , prefix ):
@@ -63,8 +69,28 @@ def __init__(self, prefix):
6369
6470 setting_changed .connect (self ._handler )
6571
72+ def _check_config (self ):
73+ list_editable_policy = self .POLICY | sum (LIST_EDITABLE_POLICIES )
74+ if list_editable_policy == sum (LIST_EDITABLE_POLICIES ):
75+ raise ImproperlyConfigured ("Invalid value for `CONCURRENCY_POLICY`: "
76+ "Use only one of `CONCURRENCY_LIST_EDITABLE_*` flags" )
77+
78+ conflict_policy = self .POLICY | sum (CONFLICTS_POLICIES )
79+ if conflict_policy == sum (CONFLICTS_POLICIES ):
80+ raise ImproperlyConfigured ("Invalid value for `CONCURRENCY_POLICY`: "
81+ "Use only one of `CONCURRENCY_POLICY_*` flags" )
82+
6683 def _set_attr (self , prefix_name , value ):
6784 name = prefix_name [len (self .prefix ) + 1 :]
85+ if name == 'CALLBACK' :
86+ if isinstance (value , six .string_types ):
87+ func = get_callable (value )
88+ elif callable (value ):
89+ func = value
90+ else :
91+ raise ImproperlyConfigured ("`CALLBACK` must be a callable or a fullpath to callable" )
92+ self ._callback = func
93+
6894 setattr (self , name , value )
6995
7096 def _handler (self , sender , setting , value , ** kwargs ):
@@ -76,19 +102,5 @@ def _handler(self, sender, setting, value, **kwargs):
76102 if setting .startswith (self .prefix ):
77103 self ._set_attr (setting , value )
78104
79- def _import_by_path (self , attrname , value ):
80- processed = None
81- if isinstance (value , (list , tuple )):
82- processed = []
83- for entry in value :
84- processed .append (import_by_path (entry ))
85- elif isinstance (value , string_types ):
86- processed = import_by_path (value )
87-
88- if processed is not None :
89- setattr (self , attrname , processed )
90- else :
91- raise ImproperlyConfigured ('Cannot import by path `%s`' % value )
92-
93105
94106conf = AppSettings ('CONCURRENCY' )
0 commit comments