Ticket #13376: messages_expirity_capabilities.1.diff

File messages_expirity_capabilities.1.diff, 36.9 KB (added by marekw2143, 14 years ago)
  • contrib/messages/restrictions.py

     
     1import time as time_provider
     2
     3
     4class Restriction (object):
     5    def __init__(self, name):
     6        self.type = name
     7
     8    def to_remove(self):
     9        ''' indicates whether given message should be removed '''
     10        raise NotImplementedError ()
     11
     12    def on_iter (self):
     13        ''' called when iterated - defaultly do nothing '''
     14
     15
     16class TimeRestriction (Restriction):
     17    def __init__(self, seconds):
     18        """
     19        seconds - expiration time since now
     20        """
     21        Restriction.__init__(self, 'time')
     22        created = time_provider.time()
     23        self.expires = created + int(seconds)
     24
     25    def set_expirity_time(self, expiration_time):
     26        """
     27        Sets expilcity expiration time
     28        """
     29        self.expires = int(expiration_time)
     30
     31    def to_remove (self):
     32        return self.expires < time_provider.time()
     33
     34    def __eq__(self, other):
     35        return self.expires == other.expires
     36
     37
     38class AmountRestriction (Restriction):
     39    def __init__(self, amount):
     40        assert int(amount) >= 0
     41        Restriction.__init__(self, 'amount')
     42        self.can_be_shown = int(amount)
     43
     44    def on_iter (self):
     45        self.can_be_shown -= 1
     46
     47    def to_remove(self):
     48        return int(self.can_be_shown) <= 0
     49
     50    def __eq__(self, other):
     51        return self.can_be_shown == other.can_be_shown
     52
  • contrib/messages/api.py

     
    1313    pass
    1414
    1515
    16 def add_message(request, level, message, extra_tags='', fail_silently=False):
     16def add_message(request, level, message, extra_tags='', fail_silently=False, restrictions = []):
    1717    """
    1818    Attempts to add a message to the request using the 'messages' app, falling
    1919    back to the user's message_set if MessageMiddleware hasn't been enabled.
    2020    """
    2121    if hasattr(request, '_messages'):
    22         return request._messages.add(level, message, extra_tags)
     22        return request._messages.add(level, message, extra_tags, restrictions = restrictions)
    2323    if hasattr(request, 'user') and request.user.is_authenticated():
    2424        return request.user.message_set.create(message=message)
    2525    if not fail_silently:
  • contrib/messages/tests/restrictions.py

     
     1from django.test import TestCase
     2from django.contrib.messages import restrictions
     3from django.contrib.messages.restrictions import AmountRestriction, TimeRestriction
     4from django.contrib.messages.tests.time_provider import TestTimeProvider
     5
     6restrictions.time_provider = TestTimeProvider ()
     7
     8class RestrictionsTest(TestCase):
     9    def __check_expired(self, amount_restriction, iterations_amount):
     10        """
     11        Checks whether after iterations_amount of on_iterate given restriction will become expired
     12        But before iterations_amount given amount_restriction must not indicate to_remove
     13        """
     14        for i in range(iterations_amount):
     15            self.assertFalse(amount_restriction.to_remove())
     16            amount_restriction.on_iter()
     17        self.assertTrue(amount_restriction.to_remove())
     18
     19    def test_amount_restrictions(self):
     20        res = AmountRestriction(4)
     21        self.__check_expired(res, 4)
     22
     23    def test_amount_restrictions_invalid_argument(self):
     24        self.assertRaises(AssertionError, AmountRestriction, -1)
     25
     26    def test_equal(self):
     27        self.assertEqual(AmountRestriction(5), AmountRestriction(5))
     28        self.assertFalse(AmountRestriction(1) == AmountRestriction(3))
     29        self.assertEqual(TimeRestriction(2), TimeRestriction(2))
     30        self.assertFalse(TimeRestriction(3) == TimeRestriction(4))
     31
  • contrib/messages/tests/time_provider.py

     
     1class TestTimeProvider(object):
     2    def __init__(self, act_time = 0):
     3        self.act_time = act_time
     4    def set_act_time(self, act_time):
     5        self.act_time = act_time
     6    def time(self):
     7        return self.act_time
     8    def inc_act_time(self):
     9        self.act_time += 1
  • contrib/messages/tests/cookie.py

     
    11from django.contrib.messages import constants
    22from django.contrib.messages.tests.base import BaseTest
     3from django.contrib.messages.tests.time_provider import TestTimeProvider
     4from django.contrib.messages import restrictions
     5from django.contrib.messages.restrictions import TimeRestriction, AmountRestriction
    36from django.contrib.messages.storage.cookie import CookieStorage, \
    47                                            MessageEncoder, MessageDecoder
    58from django.contrib.messages.storage.base import Message
     
    4649    def test_get(self):
    4750        storage = self.storage_class(self.get_request())
    4851        # Set initial data.
    49         example_messages = ['test', 'me']
     52        example_messages = [Message(constants.INFO, 'test'), Message(constants.INFO, 'me')]
     53        expected_messages = [Message(constants.INFO, 'test', restrictions = [AmountRestriction(0),]),\
     54                                     Message(constants.INFO, 'me', restrictions = [AmountRestriction(0),])]
    5055        set_cookie_data(storage, example_messages)
    5156        # Test that the message actually contains what we expect.
    52         self.assertEqual(list(storage), example_messages)
     57        self.assertEqual(list(storage), expected_messages)
    5358
    5459    def test_get_bad_cookie(self):
    5560        request = self.get_request()
     
    9196        instances is properly encoded/decoded by the custom JSON
    9297        encoder/decoder classes.
    9398        """
     99        restrictions.time_provider = TestTimeProvider()
     100        restrictions.time_provider.set_act_time(0)
    94101        messages = [
    95102            {
    96103                'message': Message(constants.INFO, 'Test message'),
    97                 'message_list': [Message(constants.INFO, 'message %s') \
     104                'message_list': [Message(constants.INFO, 'message %s', \
     105                                 restrictions = [TimeRestriction(5), AmountRestriction(3), TimeRestriction(2), AmountRestriction(10)]) \
    98106                                 for x in xrange(5)] + [{'another-message': \
    99107                                 Message(constants.ERROR, 'error')}],
    100108            },
     
    104112        value = encoder.encode(messages)
    105113        decoded_messages = json.loads(value, cls=MessageDecoder)
    106114        self.assertEqual(messages, decoded_messages)
     115
     116    def transport_storage(self, response, request):
     117        request.COOKIES['messages'] = response.cookies['messages'].value
     118
  • contrib/messages/tests/base.py

     
    44from django.test import TestCase
    55from django.conf import settings
    66from django.utils.translation import ugettext_lazy
    7 from django.contrib.messages import constants, utils, get_level, set_level
     7from django.contrib.messages import constants, utils, get_level, set_level, restrictions
    88from django.contrib.messages.api import MessageFailure
     9from django.contrib.messages.restrictions import AmountRestriction, TimeRestriction
    910from django.contrib.messages.storage import default_storage, base
    1011from django.contrib.messages.storage.base import Message
     12from django.contrib.messages.tests.time_provider import TestTimeProvider
    1113from django.core.urlresolvers import reverse
    1214from django.contrib.auth.models import User
    1315
     16restrictions.time_provider= TestTimeProvider()
    1417
     18# TODO: make def read(storage) method that would simulate reading messages from storage
    1519def add_level_messages(storage):
    1620    """
    1721    Adds 6 messages from different levels (including a custom one) to a storage
     
    9296        storage._loaded_data = data or []
    9397        return storage
    9498
     99    def read_storage(self, storage):
     100        """
     101        Simulates reading all messages from given storage
     102        Returns list of read messages
     103        """
     104        return list(storage)
     105
    95106    def test_add(self):
    96107        storage = self.get_storage()
    97108        self.assertFalse(storage.added_new)
     
    167178            response = self.client.post(add_url, data, follow=True)
    168179            self.assertRedirects(response, show_url)
    169180            self.assertTrue('messages' in response.context)
    170             messages = [Message(self.levels[level], msg) for msg in
     181            messages = [Message(self.levels[level], msg, restrictions = [AmountRestriction(0),]) for msg in
    171182                                                         data['messages']]
    172183            self.assertEqual(list(response.context['messages']), messages)
    173184            for msg in data['messages']:
     
    180191        """
    181192        settings.MESSAGE_LEVEL = constants.DEBUG
    182193        data = {
    183             'messages': ['Test message %d' % x for x in xrange(10)],
     194            'messages': ['%d' % x for x in xrange(10)],
    184195        }
    185196        show_url = reverse('django.contrib.messages.tests.urls.show')
    186197        messages = []
     
    191202                              args=(level,))
    192203            self.client.post(add_url, data)
    193204        response = self.client.get(show_url)
     205        new_messages = []
     206        for level in ('debug', 'info', 'success', 'warning', 'error'):
     207            new_messages.extend([Message(self.levels[level], msg, \
     208                                         restrictions = [AmountRestriction(0),]) for msg in data['messages']])
    194209        self.assertTrue('messages' in response.context)
    195         self.assertEqual(list(response.context['messages']), messages)
     210        self.assertEqual(list(response.context['messages']), new_messages)
    196211        for msg in data['messages']:
    197212            self.assertContains(response, msg)
    198213
     
    406421            # Ensure the level tags constant is put back like we found it.
    407422            self.restore_setting('MESSAGE_TAGS')
    408423            base.LEVEL_TAGS = utils.get_level_tags()
     424
     425    def test_storing_restrictoins(self):
     426        storage = self.get_storage()
     427        response = self.get_response()
     428
     429        get_res = lambda ar1, ar2, tr1, tr2: [AmountRestriction(ar1), AmountRestriction(ar2), TimeRestriction(tr1), TimeRestriction(tr2)]
     430       
     431        restrictions.time_provider.set_act_time(0)
     432        storage.add(constants.WARNING, 'First msg', restrictions = get_res(10, 20, 30, 40))
     433        messages = self.__read_messages(storage, response)
     434        self.assertEqual(len(messages), 1)
     435        rest = messages[0].restrictions
     436        for a in (9, 19):
     437            self.assertTrue(a in [r.can_be_shown for r in rest if r.type == 'amount'])
     438        for t in (30, 40):
     439            self.assertTrue(t in [r.expires for r in rest if r.type == 'time'])
     440
     441        restrictions.time_provider.set_act_time(4)
     442        storage = self.get_storage()
     443        response = self.get_response()
     444        storage.add(constants.WARNING, 'First msg', restrictions = get_res(10, 20, 30, 40))
     445        messages = self.__read_messages(storage, response)
     446        rest = messages[0].restrictions
     447        for a in (9, 19):
     448            self.assertTrue(a in [r.can_be_shown for r in rest if r.type == 'amount'])
     449        for t in (34, 44):
     450            self.assertTrue(t in [r.expires for r in rest if r.type == 'time'])
     451
     452    def test_expire_default(self):
     453        """
     454        Tests against message expiration in default behaviour (no explicity defined restrictions on expire -> show only once)
     455        """
     456        storage = self.get_existing_storage()
     457        response = self.get_response()
     458       
     459        list (storage)
     460        storage.update(response)
     461       
     462        storing = self.stored_messages_count(storage, response)
     463        self.assertEqual(storing, 0)
     464
     465    def test_expire_after_showing_given_amount_of_times(self):
     466        """
     467        Tests against expiring message after beeing shown given amount of times
     468        """
     469        storage = self.get_existing_storage()
     470        response = self.get_response()
     471
     472        read_messages = lambda: self.__read_messages(storage, response)
     473
     474        storage.add(constants.WARNING, 'Third message, should be shown four times', restrictions = [AmountRestriction(4),])
     475        storage.add(constants.ERROR, "Four'th message, should be shown five times", restrictions = [AmountRestriction(5),])
     476
     477
     478        messages = read_messages ()
     479        self.assertEqual(len(messages), 4)
     480        storing = self.stored_messages_count(storage, response)
     481        self.assertEqual(storing, 2)
     482
     483
     484        for i in range(2):
     485            messages = read_messages ()
     486            self.assertEqual(len(messages), 2)
     487            storing = self.stored_messages_count(storage, response)
     488            self.assertEqual(storing, 2)
     489            [self.assertTrue(level in [x.level for x in messages]) for level in (constants.ERROR, constants.WARNING)]
     490
     491
     492        messages = read_messages ()
     493        self.assertEqual(len(messages), 2)
     494        storing = self.stored_messages_count(storage, response)
     495        self.assertEqual(storing, 1)
     496
     497
     498        messages = read_messages()
     499        self.assertEqual(len(messages), 1)
     500        self.assertEqual(messages[0].level, constants.ERROR)
     501        storing = self.stored_messages_count(storage, response)
     502        self.assertEqual(storing, 0)
     503
     504
     505        messages = read_messages()
     506        self.assertEqual(len(messages), 0)
     507        storing = self.stored_messages_count(storage, response)
     508        self.assertEqual(storing, 0)
     509
     510    def test_expire_after_time(self):
     511        storage = self.get_storage()
     512        response = self.get_response()
     513        res = restrictions
     514        res.time_provider.set_act_time(0)
     515
     516        storage.add(constants.WARNING, 'Third message, should be shown four times', restrictions = [TimeRestriction(4),])
     517        storage.add(constants.ERROR, "Four'th message, should be shown five times", restrictions = [TimeRestriction(6),])
     518
     519        for i in range(10):
     520            messages = self.__read_messages(storage, response)
     521            self.assertEqual(len(messages), 2)
     522            storing = self.stored_messages_count(storage, response)
     523            self.assertEqual(storing, 2)
     524
     525        res.time_provider.set_act_time(5)
     526        messages = self.__read_messages(storage, response)
     527        self.assertEqual(len(messages), 1)
     528        self.assertEqual(messages[0].level, constants.ERROR)
     529        storing = self.stored_messages_count(storage, response)
     530        self.assertEqual(storing, 1)
     531
     532        res.time_provider.set_act_time(7)
     533        messages = self.__read_messages(storage, response)
     534        self.assertEqual(len(messages), 0)
     535        storing = self.stored_messages_count(storage, response)
     536        self.assertEqual(storing, 0)
     537
     538    def test_expire_fixed_restrictions(self):
     539        """
     540        Check message expirity when defining few sort of restrictions
     541        of different kind
     542        """
     543        get_storage_and_response = lambda: (self.get_storage(), self.get_response())
     544        storage, response = get_storage_and_response()
     545        get_res = lambda ar1, ar2, tr1, tr2: [AmountRestriction(ar1), AmountRestriction(ar2), TimeRestriction(tr1), TimeRestriction(tr2)]
     546
     547
     548        def check_storage(storage, iterations, expected_amount, fnct = None):
     549            """
     550            Checks whether given storage would contain expected_amount of messages before each of iterations iterations
     551            Performs iterations amount of iterations
     552            Calls fnct at the end of each iteration
     553            """
     554            for i in range(iterations): #read 2 times
     555                messages = self.__read_messages(storage, response)
     556                self.assertEqual(len(messages), expected_amount)
     557                storing = self.stored_messages_count(storage, response)
     558                self.assertEqual(storing, expected_amount)
     559                if fnct: fnct()
     560
     561        # first - expires after amount of showing
     562        restrictions.time_provider.set_act_time(0)
     563        storage.add(constants.ERROR, "Some message", restrictions = get_res(7, 30, 5, 20))
     564        storage.add(constants.INFO, "another message", restrictions = get_res(3, 10, 4, 11))
     565        check_storage(storage, 2, 2)
     566        messages = self.__read_messages(storage, response) # 3 times read
     567        self.assertEqual(len(messages), 2)
     568        storing = self.stored_messages_count(storage, response)
     569        self.assertEqual(storing, 1)
     570        check_storage(storage, 3, 1)
     571           
     572
     573        storage, response = get_storage_and_response()
     574        restrictions.time_provider.set_act_time(0)
     575        storage.add(constants.ERROR, "Some message", restrictions = get_res(7, 30, 5, 20))
     576        storage.add(constants.INFO, "another message", restrictions = get_res(3, 10, 4, 11))
     577        restrictions.time_provider.set_act_time(2)
     578        check_storage(storage, 2, 2, lambda:restrictions.time_provider.set_act_time(3))
     579 
     580        # second - expires after amount of time
     581        storage, response = get_storage_and_response()
     582        restrictions.time_provider.set_act_time(0)
     583        storage.add(constants.ERROR, "Some message", restrictions = get_res(10, 30, 5, 20))
     584        storage.add(constants.INFO, "another message", restrictions = get_res(10, 20, 3, 11))
     585        check_storage(storage, 2, 2)
     586        restrictions.time_provider.set_act_time(2)
     587        check_storage(storage, 2, 2)
     588        restrictions.time_provider.set_act_time(4)
     589        check_storage(storage, 2, 1)
     590
     591    def transport_storage(self, response, request):
     592        """
     593        Transports storage from response to request
     594        This method can be overriden by subclasses
     595        """
     596
     597    def __read_messages(self, storage, response):#simulate next call to render messages
     598        """
     599        Simulates iterating storage in template
     600        Returns messages from that iteration that would be returned
     601        """
     602        messages = self.read_storage(storage)
     603        storage.update(response)
     604        self.transport_storage (response, storage.request)
     605        storage.used = False 
     606        storage._queued_messages = []
     607        del storage._loaded_data
     608        return messages
     609
  • contrib/messages/tests/__init__.py

     
     1from django.contrib.messages.tests.session import SessionTest
    12from django.contrib.messages.tests.cookie import CookieTest
    23from django.contrib.messages.tests.fallback import FallbackTest
    3 from django.contrib.messages.tests.middleware import MiddlewareTest
    4 from django.contrib.messages.tests.session import SessionTest
     4from django.contrib.messages.tests.restrictions import RestrictionsTest
     5from django.contrib.messages.tests.message import MessageTest
    56from django.contrib.messages.tests.user_messages import \
    67                                           UserMessagesTest, LegacyFallbackTest
     8
     9from django.contrib.messages.tests.middleware import MiddlewareTest
     10
  • contrib/messages/tests/fallback.py

     
    11from django.contrib.messages import constants
     2from django.contrib.messages.storage.base import Message
    23from django.contrib.messages.storage.fallback import FallbackStorage, \
    34    CookieStorage
    45from django.contrib.messages.tests.base import BaseTest
    56from django.contrib.messages.tests.cookie import set_cookie_data, \
    67    stored_cookie_messages_count
     8from django.contrib.messages.restrictions import AmountRestriction
    79from django.contrib.messages.tests.session import set_session_data, \
    810    stored_session_messages_count
    911
     
    4446        cookie_storage = self.get_cookie_storage(storage)
    4547
    4648        # Set initial cookie data.
    47         example_messages = [str(i) for i in range(5)]
     49        example_messages = [Message(constants.INFO, str(i)) for i in range(5)]
     50        expected_messages = [Message(constants.INFO, str(i), restrictions = [AmountRestriction(0),]) for i in range(5)]
    4851        set_cookie_data(cookie_storage, example_messages)
    4952
    5053        # Overwrite the _get method of the fallback storage to prove it is not
     
    5255        self.get_session_storage(storage)._get = None
    5356
    5457        # Test that the message actually contains what we expect.
    55         self.assertEqual(list(storage), example_messages)
     58        self.assertEqual(list(storage), expected_messages)
    5659
    5760    def test_get_empty(self):
    5861        request = self.get_request()
     
    7275        session_storage = self.get_session_storage(storage)
    7376
    7477        # Set initial cookie and session data.
    75         example_messages = [str(i) for i in range(5)]
     78        example_messages = [Message(constants.INFO, str(i)) for i in range(5)]
     79        expected_messages = [Message(constants.INFO, str(i), restrictions = [AmountRestriction(0),]) for i in range(5)]
    7680        set_cookie_data(cookie_storage, example_messages[:4] +
    7781                        [CookieStorage.not_finished])
    7882        set_session_data(session_storage, example_messages[4:])
    7983
    8084        # Test that the message actually contains what we expect.
    81         self.assertEqual(list(storage), example_messages)
     85        self.assertEqual(list(storage), expected_messages)
    8286
    8387    def test_get_fallback_only(self):
    8488        request = self.get_request()
     
    8791        session_storage = self.get_session_storage(storage)
    8892
    8993        # Set initial cookie and session data.
    90         example_messages = [str(i) for i in range(5)]
     94        example_messages = [Message(constants.INFO, str(i)) for i in range(5)]
    9195        set_cookie_data(cookie_storage, [CookieStorage.not_finished],
    9296                        encode_empty=True)
    9397        set_session_data(session_storage, example_messages)
     
    102106        session_storage = self.get_session_storage(storage)
    103107
    104108        # Set initial cookie and session data.
    105         set_cookie_data(cookie_storage, ['cookie', CookieStorage.not_finished])
    106         set_session_data(session_storage, ['session'])
     109        set_cookie_data(cookie_storage, [Message(constants.INFO, 'cookie'), CookieStorage.not_finished])
     110        set_session_data(session_storage, [Message(constants.INFO, 'session')])
    107111
    108112        # When updating, previously used but no longer needed backends are
    109113        # flushed.
     
    173177        self.assertEqual(cookie_storing, 0)
    174178        session_storing = self.stored_session_messages_count(storage, response)
    175179        self.assertEqual(session_storing, 1)
     180
     181    def transport_storage(self, response, request):
     182        request.COOKIES['messages'] = response.cookies['messages'].value
  • contrib/messages/tests/session.py

     
    11from django.contrib.messages.tests.base import BaseTest
    22from django.contrib.messages.storage.session import SessionStorage
     3from django.contrib.messages.storage.base import Message
    34
    45
    56def set_session_data(storage, messages):
     
    3233    def test_get(self):
    3334        storage = self.storage_class(self.get_request())
    3435        # Set initial data.
    35         example_messages = ['test', 'me']
     36        example_messages = [Message(1, 'test') , Message(1, 'me')]
    3637        set_session_data(storage, example_messages)
    3738        # Test that the message actually contains what we expect.
    3839        self.assertEqual(list(storage), example_messages)
  • contrib/messages/tests/message.py

     
     1from django.test import TestCase
     2from django.contrib.messages.storage.base import Message
     3from django.contrib.messages import restrictions
     4from django.contrib.messages.restrictions import AmountRestriction, TimeRestriction, time_provider
     5from django.contrib.messages.tests.time_provider import TestTimeProvider
     6from django.contrib.messages import constants
     7
     8
     9class MessageTest(TestCase):
     10    def setUp(self):
     11        self.tp = restrictions.time_provider = TestTimeProvider ()
     12    def __check_active(self, msg, iterations):
     13        """
     14        Reads msg given amount of iterations, and after each read
     15        checks whether before each read message is active
     16        """
     17        for i in range(iterations):
     18            self.assertTrue(msg.active())
     19            msg.on_iter()
     20        self.assertFalse(msg.active())
     21        msg.on_iter()
     22        self.assertFalse(msg.active())
     23
     24    def test_active_default(self):
     25        msg = Message(constants.INFO, "Test message")
     26        self.__check_active(msg, 1)
     27
     28    def test_active_custom_one_amount_restriction(self):
     29        msg = Message(constants.INFO, "Test message", restrictions = [AmountRestriction(3),])
     30        self.__check_active(msg, 3)
     31
     32    def test_active_custom_few_amount_restriction(self):
     33        msg = Message(constants.INFO, "Test message", restrictions = [AmountRestriction(x) for x in (2, 3, 5)])
     34        self.__check_active(msg, 2)
     35
     36    def test_active_custom_one_time_restriction(self):
     37        msg = Message(constants.INFO, "Test message", restrictions = [TimeRestriction(3),])
     38        def check_iter():
     39            for i in range(10): # iteration doesn't have direct impact for TimeRestriction
     40                self.assertTrue(msg.active())
     41                msg.on_iter()
     42        check_iter()
     43        self.tp.set_act_time(3)
     44        check_iter()
     45        self.tp.set_act_time(4)
     46        self.assertFalse(msg.active())
     47
     48
     49    def test_mixed_restrictions(self):
     50        get_restrictions = lambda:[TimeRestriction(3), TimeRestriction(5), AmountRestriction(2), AmountRestriction(3)]
     51        get_msg = lambda:Message(constants.INFO, "Test message", restrictions = get_restrictions())
     52
     53        msg = get_msg()
     54        for i in range(2):
     55            self.assertTrue(msg.active())
     56            msg.on_iter()
     57        self.assertFalse(msg.active())
     58
     59        msg = get_msg()
     60        self.assertTrue(msg.active())
     61        msg.on_iter()
     62        self.assertTrue(msg.active())
     63        self.tp.set_act_time(4)
     64        self.assertFalse(msg.active())
     65        for i in range(10):
     66            self.assertFalse(msg.active())
     67            msg.on_iter()
     68       
     69           
  • contrib/messages/tests/user_messages.py

     
    11from django import http
    22from django.contrib.auth.models import User
     3from django.contrib.messages import constants
     4from django.contrib.messages.storage.base import Message
    35from django.contrib.messages.storage.user_messages import UserMessagesStorage,\
    46    LegacyFallbackStorage
    57from django.contrib.messages.tests.cookie import set_cookie_data
     
    5759        storage = self.storage_class(request)
    5860        cookie_storage = self.get_cookie_storage(storage)
    5961        self.user.message_set.create(message='user message')
    60         set_cookie_data(cookie_storage, ['cookie'])
     62        set_cookie_data(cookie_storage, [Message(constants.INFO,'cookie')])
    6163
    6264        # Test that the message actually contains what we expect.
    6365        self.assertEqual(len(storage), 2)
    6466        self.assertEqual(list(storage)[0].message, 'user message')
    65         self.assertEqual(list(storage)[1], 'cookie')
     67        self.assertEqual(list(storage)[1].message, 'cookie')
  • contrib/messages/storage/cookie.py

     
    77from django.utils import simplejson as json
    88from django.utils.hashcompat import sha_hmac
    99
     10from django.contrib.messages.restrictions import AmountRestriction, TimeRestriction
    1011
    1112class MessageEncoder(json.JSONEncoder):
    1213    """
     
    1415    """
    1516    message_key = '__json_message'
    1617
     18    def __encode_restriction (self, r):
     19        if r.type == 'amount': ret = '%s@%s' % ('a', r.can_be_shown)
     20        elif r.type == 'time': ret = '%s@%s' % ('t', r.expires)
     21        return ret
     22
    1723    def default(self, obj):
    1824        if isinstance(obj, Message):
    1925            message = [self.message_key, obj.level, obj.message]
    2026            if obj.extra_tags:
    2127                message.append(obj.extra_tags)
     28            restrictions = [self.__encode_restriction(r) for r in obj.restrictions]
     29            message.append (restrictions)
    2230            return message
    2331        return super(MessageEncoder, self).default(obj)
    2432
     
    2735    """
    2836    Decodes JSON that includes serialized ``Message`` instances.
    2937    """
     38    def __get_restrictions (self, restrictions):
     39        def _get_r(type, value):
     40            if type == 'a':  return AmountRestriction (value)
     41            elif type == 't':
     42                ret = TimeRestriction(0)
     43                ret.set_expirity_time(value)
     44                return ret
     45        ret = []
     46        for r in restrictions:
     47            rtype, value = r.split('@')
     48            added = _get_r (rtype, value)
     49            ret.append (added)
     50        return ret
     51        #return [_get_r(rtype, value) for rtype, value in [r.split('@') for r in restrictions] ]
    3052
     53
     54    def create_message(self, vars):
     55        ''' creates message on the basis of encoded data '''
     56        args = vars[:-1]
     57        restrictions = vars[-1]
     58        restrictions = self.__get_restrictions (restrictions)
     59        return Message(*args, **{'restrictions': restrictions})
     60
    3161    def process_messages(self, obj):
    3262        if isinstance(obj, list) and obj:
    3363            if obj[0] == MessageEncoder.message_key:
    34                 return Message(*obj[1:])
     64                return self.create_message (obj[1:])
    3565            return [self.process_messages(item) for item in obj]
    3666        if isinstance(obj, dict):
    3767            return dict([(key, self.process_messages(value))
     
    136166        """
    137167        if not data:
    138168            return None
    139         bits = data.split('$', 1)
     169        try:
     170            bits = data.split('$', 1)
     171        except:
     172            set_trace ()
    140173        if len(bits) == 2:
    141174            hash, value = bits
    142175            if hash == self._hash(value):
     
    150183        # with the data.
    151184        self.used = True
    152185        return None
     186 
     187    def transport_storage(self, response, request):
     188        storage.request.COOKIES['messages'] = response.cookies['messages'].value
  • contrib/messages/storage/base.py

     
    11from django.conf import settings
    22from django.utils.encoding import force_unicode, StrAndUnicode
    3 from django.contrib.messages import constants, utils
     3from django.contrib.messages import constants, utils, restrictions as res
    44
    55
    66LEVEL_TAGS = utils.get_level_tags()
    77
     8       
    89
    910class Message(StrAndUnicode):
    1011    """
     
    1314    or template.
    1415    """
    1516
    16     def __init__(self, level, message, extra_tags=None):
     17    def __init__(self, level, message, extra_tags=None, restrictions = []):
    1718        self.level = int(level)
    1819        self.message = message
    1920        self.extra_tags = extra_tags
    2021
    21     def _prepare(self):
     22        self.restrictions = restrictions or list([res.AmountRestriction(1)])
     23        # if not given any restriction - one show by default
     24
     25    def _prepare(self): # todo: slef.restrictions =
    2226        """
    2327        Prepares the message for serialization by forcing the ``message``
    2428        and ``extra_tags`` to unicode in case they are lazy translations.
     
    3135
    3236    def __eq__(self, other):
    3337        return isinstance(other, Message) and self.level == other.level and \
    34                                               self.message == other.message
     38                                              self.message == other.message and \
     39                                              self.restrictions == other.restrictions
    3540
    3641    def __unicode__(self):
    37         return force_unicode(self.message)
     42        return force_unicode(self.message)  + ':' + unicode('CFVB')
    3843
     44
    3945    def _get_tags(self):
    4046        label_tag = force_unicode(LEVEL_TAGS.get(self.level, ''),
    4147                                  strings_only=True)
     
    5056    tags = property(_get_tags)
    5157
    5258
     59    def active (self):
     60        for r in self.restrictions:
     61            if r.to_remove(): return False
     62        return True
     63
     64
     65    def on_iter (self):
     66        for r in self.restrictions:
     67            r.on_iter ()
     68
     69
    5370class BaseStorage(object):
    5471    """
    5572    This is the base backend for temporary message storage.
     
    6077
    6178    def __init__(self, request, *args, **kwargs):
    6279        self.request = request
     80        self.used = False
    6381        self._queued_messages = []
    64         self.used = False
    6582        self.added_new = False
    6683        super(BaseStorage, self).__init__(*args, **kwargs)
    6784
     
    6986        return len(self._loaded_messages) + len(self._queued_messages)
    7087
    7188    def __iter__(self):
    72         self.used = True
    73         if self._queued_messages:
    74             self._loaded_messages.extend(self._queued_messages)
    75             self._queued_messages = []
    76         return iter(self._loaded_messages)
     89        if not self.used:
     90            self.used = True
     91            if self._queued_messages:
     92                self._loaded_messages.extend(self._queued_messages)
     93                self._queued_messages = []
    7794
     95            active_messages = [x for x in self._loaded_messages if x.active ()]
     96            for x in active_messages:
     97                x.on_iter ()
     98            self._queued_messages.extend (active_messages)
     99        return iter(self._queued_messages)
     100
     101
    78102    def __contains__(self, item):
    79103        return item in self._loaded_messages or item in self._queued_messages
    80104
     
    104128        """
    105129        raise NotImplementedError()
    106130
     131    def filter_store(self, messages, response, *args, **kwargs):
     132        ''' stores only active messages from given messages in storage '''
     133        filtered_messages = [x for x in messages if x.active ()]
     134        return self._store(filtered_messages, response, *args, **kwargs)
     135
     136
    107137    def _store(self, messages, response, *args, **kwargs):
    108138        """
    109139        Stores a list of messages, returning a list of any messages which could
     
    130160        be stored again. Otherwise, only messages added after the last
    131161        iteration will be stored.
    132162        """
     163        # if used or used and added, then _queued_messages contains all messages that should be saved
     164        # if added, then save: all messages currently stored and added ones
    133165        self._prepare_messages(self._queued_messages)
    134166        if self.used:
    135             return self._store(self._queued_messages, response)
     167            return self.filter_store(self._queued_messages, response)
    136168        elif self.added_new:
    137169            messages = self._loaded_messages + self._queued_messages
    138             return self._store(messages, response)
     170            return self.filter_store(messages, response)
    139171
    140     def add(self, level, message, extra_tags=''):
     172    def add(self, level, message, extra_tags='', restrictions = []):
    141173        """
    142174        Queues a message to be stored.
    143175
     
    152184            return
    153185        # Add the message.
    154186        self.added_new = True
    155         message = Message(level, message, extra_tags=extra_tags)
     187        message = Message(level, message, extra_tags=extra_tags, restrictions = restrictions)
    156188        self._queued_messages.append(message)
    157189
    158190    def _get_level(self):
  • contrib/messages/storage/session.py

     
    2222        """
    2323        return self.request.session.get(self.session_key), True
    2424
    25     def _store(self, messages, response, *args, **kwargs):
     25    def _store(self, messages, response, *args, **kwargs): # overrides all messages existing in storage so far
    2626        """
    27         Stores a list of messages to the request's session.
     27        Stores a list of messages to the request's session. 
    2828        """
    2929        if messages:
    3030            self.request.session[self.session_key] = messages
Back to Top