Ticket #13376: messages_expirity_capabilities.3.diff
File messages_expirity_capabilities.3.diff, 37.3 KB (added by , 14 years ago) |
---|
-
contrib/messages/restrictions.py
1 import time as time_provider 2 from pdb import set_trace 3 4 5 class Restriction (object): 6 JSON_SEPARATOR = '@' 7 8 def __init__(self, name): 9 self.type = name 10 11 def is_expired(self): 12 """ 13 indicates whether given message should be removed 14 """ 15 raise NotImplementedError () 16 17 def on_display (self): 18 """ 19 called when iterated - does nothing by default 20 """ 21 pass 22 23 def to_json(self): 24 """ 25 returns json representation of restriction 26 """ 27 raise NotImplementedError 28 29 def from_json_param(self, *args): 30 """ 31 returns restriction on the basis of data encoded in json 32 """ 33 raise NotImplementedError 34 35 36 def __cmp__(self, other): 37 if self.__eq__(other): return 0 38 return -1 39 40 class TimeRestriction (Restriction): 41 JSON_TYPE_CODE = 't' 42 43 def __init__(self, seconds): 44 """ 45 seconds - expiration time since now 46 """ 47 Restriction.__init__(self, 'time') 48 created = time_provider.time() 49 self.expires = created + int(seconds) 50 51 def set_expirity_time(self, expiration_time): 52 """ 53 Sets expilcity expiration time 54 """ 55 self.expires = int(expiration_time) 56 57 def is_expired (self): 58 return self.expires < time_provider.time() 59 60 def __eq__(self, other): 61 return self.type == other.type and not bool(self.expires ^ other.expires) 62 63 def __hash__(self): 64 return self.expires 65 66 def to_json(self): 67 return '%s%s%s' % (self.JSON_TYPE_CODE, self.JSON_SEPARATOR, self.expires) 68 69 @classmethod 70 def from_json_param(cls, expirity_time): 71 ret = TimeRestriction(0) 72 ret.set_expirity_time(expirity_time) 73 return ret 74 75 76 77 class AmountRestriction (Restriction): 78 JSON_TYPE_CODE = 'a' 79 80 def __init__(self, amount): 81 assert int(amount) >= 0 82 Restriction.__init__(self, 'amount') 83 self.can_be_shown = int(amount) 84 85 def on_display (self): 86 self.can_be_shown -= 1 87 88 def is_expired(self): 89 return int(self.can_be_shown) <= 0 90 91 def __eq__(self, other): 92 return self.type == other.type and not bool(self.can_be_shown ^ other.can_be_shown) 93 94 95 def __hash__(self): 96 return self.can_be_shown 97 98 def to_json(self): 99 return '%s%s%s' % (self.JSON_TYPE_CODE, self.JSON_SEPARATOR, self.can_be_shown) 100 101 @classmethod 102 def from_json_param(cls, amount): 103 return AmountRestriction(amount) 104 105 -
contrib/messages/api.py
13 13 pass 14 14 15 15 16 def add_message(request, level, message, extra_tags='', fail_silently=False ):16 def add_message(request, level, message, extra_tags='', fail_silently=False, restrictions = []): 17 17 """ 18 18 Attempts to add a message to the request using the 'messages' app, falling 19 19 back to the user's message_set if MessageMiddleware hasn't been enabled. 20 20 """ 21 21 if hasattr(request, '_messages'): 22 return request._messages.add(level, message, extra_tags )22 return request._messages.add(level, message, extra_tags, restrictions = restrictions) 23 23 if hasattr(request, 'user') and request.user.is_authenticated(): 24 24 return request.user.message_set.create(message=message) 25 25 if not fail_silently: -
contrib/messages/tests/restrictions.py
1 from pdb import set_trace 2 from django.test import TestCase 3 from django.contrib.messages import restrictions 4 from django.contrib.messages.restrictions import AmountRestriction, TimeRestriction 5 from django.contrib.messages.tests.time_provider import TestTimeProvider 6 7 restrictions.time_provider = TestTimeProvider () 8 9 class RestrictionsTest(TestCase): 10 def __check_expired(self, amount_restriction, iterations_amount): 11 """ 12 Checks whether after iterations_amount of on_displayate given restriction will become expired 13 But before iterations_amount given amount_restriction must not indicate is_expired 14 """ 15 for i in range(iterations_amount): 16 self.assertFalse(amount_restriction.is_expired()) 17 amount_restriction.on_display() 18 self.assertTrue(amount_restriction.is_expired()) 19 20 def test_amount_restrictions(self): 21 res = AmountRestriction(4) 22 self.__check_expired(res, 4) 23 24 def test_amount_restrictions_invalid_argument(self): 25 self.assertRaises(AssertionError, AmountRestriction, -1) 26 27 def test_equal(self): 28 self.assertEqual(AmountRestriction(5), AmountRestriction(5)) 29 self.assertFalse(AmountRestriction(1) == AmountRestriction(3)) 30 self.assertEqual(TimeRestriction(2), TimeRestriction(2)) 31 self.assertFalse(TimeRestriction(3) == TimeRestriction(4)) 32 33 -
contrib/messages/tests/time_provider.py
1 class 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
1 1 from django.contrib.messages import constants 2 2 from django.contrib.messages.tests.base import BaseTest 3 from django.contrib.messages.tests.time_provider import TestTimeProvider 4 from django.contrib.messages import restrictions 5 from django.contrib.messages.restrictions import TimeRestriction, AmountRestriction 3 6 from django.contrib.messages.storage.cookie import CookieStorage, \ 4 7 MessageEncoder, MessageDecoder 5 8 from django.contrib.messages.storage.base import Message … … 56 59 def test_get(self): 57 60 storage = self.storage_class(self.get_request()) 58 61 # Set initial data. 59 example_messages = ['test', 'me'] 62 example_messages = [Message(constants.INFO, 'test'), Message(constants.INFO, 'me')] 63 expected_messages = [Message(constants.INFO, 'test', restrictions = [AmountRestriction(0),]),\ 64 Message(constants.INFO, 'me', restrictions = [AmountRestriction(0),])] 60 65 set_cookie_data(storage, example_messages) 61 66 # Test that the message actually contains what we expect. 62 self.assertEqual(list(storage), ex ample_messages)67 self.assertEqual(list(storage), expected_messages) 63 68 64 69 def test_domain(self): 65 70 """ … … 126 131 instances is properly encoded/decoded by the custom JSON 127 132 encoder/decoder classes. 128 133 """ 134 restrictions.time_provider = TestTimeProvider() 135 restrictions.time_provider.set_act_time(0) 129 136 messages = [ 130 137 { 131 138 'message': Message(constants.INFO, 'Test message'), 132 'message_list': [Message(constants.INFO, 'message %s') \ 139 'message_list': [Message(constants.INFO, 'message %s', \ 140 restrictions = [TimeRestriction(5), AmountRestriction(3), TimeRestriction(2), AmountRestriction(10)]) \ 133 141 for x in xrange(5)] + [{'another-message': \ 134 142 Message(constants.ERROR, 'error')}], 135 143 }, … … 139 147 value = encoder.encode(messages) 140 148 decoded_messages = json.loads(value, cls=MessageDecoder) 141 149 self.assertEqual(messages, decoded_messages) 150 151 def transport_storage(self, response, request): 152 request.COOKIES['messages'] = response.cookies['messages'].value 153 -
contrib/messages/tests/base.py
1 1 import warnings 2 from pdb import set_trace 2 3 3 4 from django import http 4 5 from django.test import TestCase 5 6 from django.conf import settings 6 7 from django.utils.translation import ugettext_lazy 7 8 from django.utils.unittest import skipIf 8 from django.contrib.messages import constants, utils, get_level, set_level 9 from django.contrib.messages import constants, utils, get_level, set_level, restrictions 9 10 from django.contrib.messages.api import MessageFailure 11 from django.contrib.messages.restrictions import AmountRestriction, TimeRestriction 10 12 from django.contrib.messages.storage import default_storage, base 11 13 from django.contrib.messages.storage.base import Message 14 from django.contrib.messages.tests.time_provider import TestTimeProvider 12 15 from django.core.urlresolvers import reverse 13 16 from django.contrib.auth.models import User 14 17 18 restrictions.time_provider = TestTimeProvider() 15 19 16 20 def skipUnlessAuthIsInstalled(func): 17 21 return skipIf( … … 102 106 storage._loaded_data = data or [] 103 107 return storage 104 108 109 def read_storage(self, storage): 110 """ 111 Simulates reading all messages from given storage 112 Returns list of read messages 113 """ 114 return list(storage) 115 105 116 def test_add(self): 106 117 storage = self.get_storage() 107 118 self.assertFalse(storage.added_new) … … 177 188 response = self.client.post(add_url, data, follow=True) 178 189 self.assertRedirects(response, show_url) 179 190 self.assertTrue('messages' in response.context) 180 messages = [Message(self.levels[level], msg ) for msg in191 messages = [Message(self.levels[level], msg, restrictions = [AmountRestriction(0),]) for msg in 181 192 data['messages']] 182 193 self.assertEqual(list(response.context['messages']), messages) 183 194 for msg in data['messages']: … … 210 221 """ 211 222 settings.MESSAGE_LEVEL = constants.DEBUG 212 223 data = { 213 'messages': [' Test message%d' % x for x in xrange(10)],224 'messages': ['%d' % x for x in xrange(10)], 214 225 } 215 226 show_url = reverse('django.contrib.messages.tests.urls.show') 216 227 messages = [] … … 221 232 args=(level,)) 222 233 self.client.post(add_url, data) 223 234 response = self.client.get(show_url) 235 new_messages = [] 236 for level in ('debug', 'info', 'success', 'warning', 'error'): 237 new_messages.extend([Message(self.levels[level], msg, \ 238 restrictions = [AmountRestriction(0),]) for msg in data['messages']]) 224 239 self.assertTrue('messages' in response.context) 225 self.assertEqual(list(response.context['messages']), messages)240 self.assertEqual(list(response.context['messages']), new_messages) 226 241 for msg in data['messages']: 227 242 self.assertContains(response, msg) 228 243 … … 437 452 # Ensure the level tags constant is put back like we found it. 438 453 self.restore_setting('MESSAGE_TAGS') 439 454 base.LEVEL_TAGS = utils.get_level_tags() 455 456 def test_storing_restrictoins(self): 457 storage = self.get_storage() 458 response = self.get_response() 459 460 get_res = lambda ar1, ar2, tr1, tr2: [AmountRestriction(ar1), AmountRestriction(ar2), TimeRestriction(tr1), TimeRestriction(tr2)] 461 462 restrictions.time_provider.set_act_time(0) 463 storage.add(constants.WARNING, 'First msg', restrictions = get_res(10, 20, 30, 40)) 464 messages = self.__read_messages(storage, response) 465 self.assertEqual(len(messages), 1) 466 rest = messages[0].restrictions 467 for a in (9, 19): 468 self.assertTrue(a in [r.can_be_shown for r in rest if r.type == 'amount']) 469 for t in (30, 40): 470 self.assertTrue(t in [r.expires for r in rest if r.type == 'time']) 471 472 restrictions.time_provider.set_act_time(4) 473 storage = self.get_storage() 474 response = self.get_response() 475 storage.add(constants.WARNING, 'First msg', restrictions = get_res(10, 20, 30, 40)) 476 messages = self.__read_messages(storage, response) 477 rest = messages[0].restrictions 478 for a in (9, 19): 479 self.assertTrue(a in [r.can_be_shown for r in rest if r.type == 'amount']) 480 for t in (34, 44): 481 self.assertTrue(t in [r.expires for r in rest if r.type == 'time']) 482 483 def test_expire_default(self): 484 """ 485 Tests against message expiration in default behaviour (no explicity defined restrictions on expire -> show only once) 486 """ 487 storage = self.get_existing_storage() 488 response = self.get_response() 489 490 list (storage) 491 storage.update(response) 492 493 storing = self.stored_messages_count(storage, response) 494 self.assertEqual(storing, 0) 495 496 def test_expire_after_showing_given_amount_of_times(self): 497 """ 498 Tests against expiring message after beeing shown given amount of times 499 """ 500 storage = self.get_existing_storage() 501 response = self.get_response() 502 503 read_messages = lambda: self.__read_messages(storage, response) 504 505 storage.add(constants.WARNING, 'Third message, should be shown four times', restrictions = [AmountRestriction(4),]) 506 storage.add(constants.ERROR, "Four'th message, should be shown five times", restrictions = [AmountRestriction(5),]) 507 508 509 messages = read_messages () 510 self.assertEqual(len(messages), 4) 511 storing = self.stored_messages_count(storage, response) 512 self.assertEqual(storing, 2) 513 514 515 for i in range(2): 516 messages = read_messages () 517 self.assertEqual(len(messages), 2) 518 storing = self.stored_messages_count(storage, response) 519 self.assertEqual(storing, 2) 520 [self.assertTrue(level in [x.level for x in messages]) for level in (constants.ERROR, constants.WARNING)] 521 522 523 messages = read_messages () 524 self.assertEqual(len(messages), 2) 525 storing = self.stored_messages_count(storage, response) 526 self.assertEqual(storing, 1) 527 528 529 messages = read_messages() 530 self.assertEqual(len(messages), 1) 531 self.assertEqual(messages[0].level, constants.ERROR) 532 storing = self.stored_messages_count(storage, response) 533 self.assertEqual(storing, 0) 534 535 536 messages = read_messages() 537 self.assertEqual(len(messages), 0) 538 storing = self.stored_messages_count(storage, response) 539 self.assertEqual(storing, 0) 540 541 def test_expire_after_time(self): 542 storage = self.get_storage() 543 response = self.get_response() 544 res = restrictions 545 res.time_provider.set_act_time(0) 546 547 storage.add(constants.WARNING, 'Third message, should be shown four times', restrictions = [TimeRestriction(4),]) 548 storage.add(constants.ERROR, "Four'th message, should be shown five times", restrictions = [TimeRestriction(6),]) 549 550 for i in range(10): 551 messages = self.__read_messages(storage, response) 552 self.assertEqual(len(messages), 2) 553 storing = self.stored_messages_count(storage, response) 554 self.assertEqual(storing, 2) 555 556 res.time_provider.set_act_time(5) 557 messages = self.__read_messages(storage, response) 558 self.assertEqual(len(messages), 1) 559 self.assertEqual(messages[0].level, constants.ERROR) 560 storing = self.stored_messages_count(storage, response) 561 self.assertEqual(storing, 1) 562 563 res.time_provider.set_act_time(7) 564 messages = self.__read_messages(storage, response) 565 self.assertEqual(len(messages), 0) 566 storing = self.stored_messages_count(storage, response) 567 self.assertEqual(storing, 0) 568 569 def test_expire_fixed_restrictions(self): 570 """ 571 Check message expirity when defining few sort of restrictions 572 of different kind 573 """ 574 get_storage_and_response = lambda: (self.get_storage(), self.get_response()) 575 storage, response = get_storage_and_response() 576 get_res = lambda ar1, ar2, tr1, tr2: [AmountRestriction(ar1), AmountRestriction(ar2), TimeRestriction(tr1), TimeRestriction(tr2)] 577 578 579 def check_storage(storage, iterations, expected_amount, fnct = None): 580 """ 581 Checks whether given storage would contain expected_amount of messages before each of iterations iterations 582 Performs iterations amount of iterations 583 Calls fnct at the end of each iteration 584 """ 585 for i in range(iterations): #read 2 times 586 messages = self.__read_messages(storage, response) 587 self.assertEqual(len(messages), expected_amount) 588 storing = self.stored_messages_count(storage, response) 589 self.assertEqual(storing, expected_amount) 590 if fnct: fnct() 591 592 # first - expires after amount of showing 593 restrictions.time_provider.set_act_time(0) 594 storage.add(constants.ERROR, "Some message", restrictions = get_res(7, 30, 5, 20)) 595 storage.add(constants.INFO, "another message", restrictions = get_res(3, 10, 4, 11)) 596 check_storage(storage, 2, 2) 597 messages = self.__read_messages(storage, response) # 3 times read 598 self.assertEqual(len(messages), 2) 599 storing = self.stored_messages_count(storage, response) 600 self.assertEqual(storing, 1) 601 check_storage(storage, 3, 1) 602 603 604 storage, response = get_storage_and_response() 605 restrictions.time_provider.set_act_time(0) 606 storage.add(constants.ERROR, "Some message", restrictions = get_res(7, 30, 5, 20)) 607 storage.add(constants.INFO, "another message", restrictions = get_res(3, 10, 4, 11)) 608 restrictions.time_provider.set_act_time(2) 609 check_storage(storage, 2, 2, lambda:restrictions.time_provider.set_act_time(3)) 610 611 # second - expires after amount of time 612 storage, response = get_storage_and_response() 613 restrictions.time_provider.set_act_time(0) 614 storage.add(constants.ERROR, "Some message", restrictions = get_res(10, 30, 5, 20)) 615 storage.add(constants.INFO, "another message", restrictions = get_res(10, 20, 3, 11)) 616 check_storage(storage, 2, 2) 617 restrictions.time_provider.set_act_time(2) 618 check_storage(storage, 2, 2) 619 restrictions.time_provider.set_act_time(4) 620 check_storage(storage, 2, 1) 621 622 def transport_storage(self, response, request): 623 """ 624 Transports storage from response to request 625 This method can be overriden by subclasses 626 """ 627 628 def __read_messages(self, storage, response):#simulate next call to render messages 629 """ 630 Simulates iterating storage in template 631 Returns messages from that iteration that would be returned 632 """ 633 messages = self.read_storage(storage) 634 storage.update(response) 635 self.transport_storage (response, storage.request) 636 storage.used = False 637 storage._queued_messages = [] 638 del storage._loaded_data 639 return messages 640 -
contrib/messages/tests/__init__.py
1 from django.contrib.messages.tests.session import SessionTest 1 2 from django.contrib.messages.tests.cookie import CookieTest 2 3 from django.contrib.messages.tests.fallback import FallbackTest 3 from django.contrib.messages.tests. middleware import MiddlewareTest4 from django.contrib.messages.tests. session import SessionTest4 from django.contrib.messages.tests.restrictions import RestrictionsTest 5 from django.contrib.messages.tests.message import MessageTest 5 6 from django.contrib.messages.tests.user_messages import \ 6 7 UserMessagesTest, LegacyFallbackTest 8 9 from django.contrib.messages.tests.middleware import MiddlewareTest 10 -
contrib/messages/tests/fallback.py
1 1 from django.contrib.messages import constants 2 from django.contrib.messages.storage.base import Message 2 3 from django.contrib.messages.storage.fallback import FallbackStorage, \ 3 4 CookieStorage 4 5 from django.contrib.messages.tests.base import BaseTest 5 6 from django.contrib.messages.tests.cookie import set_cookie_data, \ 6 7 stored_cookie_messages_count 8 from django.contrib.messages.restrictions import AmountRestriction 7 9 from django.contrib.messages.tests.session import set_session_data, \ 8 10 stored_session_messages_count 9 11 … … 44 46 cookie_storage = self.get_cookie_storage(storage) 45 47 46 48 # 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)] 48 51 set_cookie_data(cookie_storage, example_messages) 49 52 50 53 # Overwrite the _get method of the fallback storage to prove it is not … … 52 55 self.get_session_storage(storage)._get = None 53 56 54 57 # Test that the message actually contains what we expect. 55 self.assertEqual(list(storage), ex ample_messages)58 self.assertEqual(list(storage), expected_messages) 56 59 57 60 def test_get_empty(self): 58 61 request = self.get_request() … … 72 75 session_storage = self.get_session_storage(storage) 73 76 74 77 # 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)] 76 80 set_cookie_data(cookie_storage, example_messages[:4] + 77 81 [CookieStorage.not_finished]) 78 82 set_session_data(session_storage, example_messages[4:]) 79 83 80 84 # Test that the message actually contains what we expect. 81 self.assertEqual(list(storage), ex ample_messages)85 self.assertEqual(list(storage), expected_messages) 82 86 83 87 def test_get_fallback_only(self): 84 88 request = self.get_request() … … 87 91 session_storage = self.get_session_storage(storage) 88 92 89 93 # 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)] 91 95 set_cookie_data(cookie_storage, [CookieStorage.not_finished], 92 96 encode_empty=True) 93 97 set_session_data(session_storage, example_messages) … … 102 106 session_storage = self.get_session_storage(storage) 103 107 104 108 # 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')]) 107 111 108 112 # When updating, previously used but no longer needed backends are 109 113 # flushed. … … 173 177 self.assertEqual(cookie_storing, 0) 174 178 session_storing = self.stored_session_messages_count(storage, response) 175 179 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
1 1 from django.contrib.messages.tests.base import BaseTest 2 2 from django.contrib.messages.storage.session import SessionStorage 3 from django.contrib.messages.storage.base import Message 3 4 4 5 5 6 def set_session_data(storage, messages): … … 32 33 def test_get(self): 33 34 storage = self.storage_class(self.get_request()) 34 35 # Set initial data. 35 example_messages = [ 'test', 'me']36 example_messages = [Message(1, 'test') , Message(1, 'me')] 36 37 set_session_data(storage, example_messages) 37 38 # Test that the message actually contains what we expect. 38 39 self.assertEqual(list(storage), example_messages) -
contrib/messages/tests/message.py
1 from django.test import TestCase 2 from django.contrib.messages.storage.base import Message 3 from django.contrib.messages import restrictions 4 from django.contrib.messages.restrictions import AmountRestriction, TimeRestriction, time_provider 5 from django.contrib.messages.tests.time_provider import TestTimeProvider 6 from django.contrib.messages import constants 7 8 9 class 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_display() 20 self.assertFalse(msg.active()) 21 msg.on_display() 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_display() 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_display() 57 self.assertFalse(msg.active()) 58 59 msg = get_msg() 60 self.assertTrue(msg.active()) 61 msg.on_display() 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_display() 68 69 -
contrib/messages/tests/user_messages.py
1 1 from django import http 2 2 from django.contrib.auth.models import User 3 from django.contrib.messages import constants 4 from django.contrib.messages.storage.base import Message 3 5 from django.contrib.messages.storage.user_messages import UserMessagesStorage,\ 4 6 LegacyFallbackStorage 5 7 from django.contrib.messages.tests.base import skipUnlessAuthIsInstalled … … 60 62 storage = self.storage_class(request) 61 63 cookie_storage = self.get_cookie_storage(storage) 62 64 self.user.message_set.create(message='user message') 63 set_cookie_data(cookie_storage, [ 'cookie'])65 set_cookie_data(cookie_storage, [Message(constants.INFO,'cookie')]) 64 66 65 67 # Test that the message actually contains what we expect. 66 68 self.assertEqual(len(storage), 2) 67 69 self.assertEqual(list(storage)[0].message, 'user message') 68 self.assertEqual(list(storage)[1] , 'cookie')70 self.assertEqual(list(storage)[1].message, 'cookie') 69 71 70 72 LegacyFallbackTest = skipUnlessAuthIsInstalled(LegacyFallbackTest) -
contrib/messages/storage/cookie.py
1 from pdb import set_trace 1 2 from django.conf import settings 2 3 from django.contrib.messages import constants 3 from django.contrib.messages.storage.base import BaseStorage, Message 4 from django.contrib.messages.storage.base import BaseStorage, Message, RestrictionsContainer 4 5 from django.http import SimpleCookie 5 6 from django.utils import simplejson as json 6 7 from django.utils.crypto import salted_hmac, constant_time_compare 7 8 9 from django.contrib.messages.restrictions import AmountRestriction, TimeRestriction 8 10 9 11 class MessageEncoder(json.JSONEncoder): 10 12 """ … … 12 14 """ 13 15 message_key = '__json_message' 14 16 17 15 18 def default(self, obj): 16 19 if isinstance(obj, Message): 17 20 message = [self.message_key, obj.level, obj.message] 18 21 if obj.extra_tags: 19 22 message.append(obj.extra_tags) 23 message.append (obj.restrictions.to_json_obj()) 20 24 return message 21 25 return super(MessageEncoder, self).default(obj) 22 26 … … 26 30 Decodes JSON that includes serialized ``Message`` instances. 27 31 """ 28 32 33 34 def create_message(self, vars): 35 ''' creates message on the basis of encoded data ''' 36 args = vars[:-1] 37 restrictions = vars[-1] 38 restrictions = RestrictionsContainer.create_from_josn(restrictions) 39 return Message(*args, **{'restrictions': restrictions}) 40 29 41 def process_messages(self, obj): 30 42 if isinstance(obj, list) and obj: 31 43 if obj[0] == MessageEncoder.message_key: 32 return Message(*obj[1:])44 return self.create_message (obj[1:]) 33 45 return [self.process_messages(item) for item in obj] 34 46 if isinstance(obj, dict): 35 47 return dict([(key, self.process_messages(value)) -
contrib/messages/storage/base.py
1 from pdb import set_trace 1 2 from django.conf import settings 2 3 from django.utils.encoding import force_unicode, StrAndUnicode 3 from django.contrib.messages import constants, utils 4 from django.contrib.messages import constants, utils, restrictions as res 4 5 5 6 6 7 LEVEL_TAGS = utils.get_level_tags() 7 8 9 10 class RestrictionsContainer(list): 11 res_map = {res.AmountRestriction.JSON_TYPE_CODE: res.AmountRestriction, 12 res.TimeRestriction.JSON_TYPE_CODE: res.TimeRestriction} 8 13 14 def to_json_obj(self): 15 return [r.to_json() for r in self] 16 17 @classmethod 18 def create_from_josn(cls, enc_restrictions): 19 #set_trace() 20 ret = [] 21 for r in enc_restrictions: 22 restriction_type, values = r.split(res.Restriction.JSON_SEPARATOR) 23 ret.append(cls.res_map[restriction_type].from_json_param(values)) 24 return RestrictionsContainer(ret) 25 26 def __eq__(self, other): 27 return set(self) == set(other) 28 9 29 class Message(StrAndUnicode): 10 30 """ 11 31 Represents an actual message that can be stored in any of the supported … … 13 33 or template. 14 34 """ 15 35 16 def __init__(self, level, message, extra_tags=None ):36 def __init__(self, level, message, extra_tags=None, restrictions = []): 17 37 self.level = int(level) 18 38 self.message = message 19 39 self.extra_tags = extra_tags 20 40 21 def _prepare(self): 41 self.restrictions = restrictions or list([res.AmountRestriction(1)]) 42 self.restrictions = RestrictionsContainer(self.restrictions) 43 # if not given any restriction - one show by default 44 45 def _prepare(self): # todo: slef.restrictions = 22 46 """ 23 47 Prepares the message for serialization by forcing the ``message`` 24 48 and ``extra_tags`` to unicode in case they are lazy translations. … … 31 55 32 56 def __eq__(self, other): 33 57 return isinstance(other, Message) and self.level == other.level and \ 34 self.message == other.message 58 self.message == other.message and \ 59 self.restrictions == other.restrictions 35 60 36 61 def __unicode__(self): 37 return force_unicode(self.message) 62 return force_unicode(self.message) + ':' + unicode('CFVB') 38 63 64 39 65 def _get_tags(self): 40 66 label_tag = force_unicode(LEVEL_TAGS.get(self.level, ''), 41 67 strings_only=True) … … 50 76 tags = property(_get_tags) 51 77 52 78 79 def active (self): 80 for r in self.restrictions: 81 if r.is_expired(): return False 82 return True 83 84 85 def on_display (self): 86 for r in self.restrictions: 87 r.on_display () 88 89 53 90 class BaseStorage(object): 54 91 """ 55 92 This is the base backend for temporary message storage. … … 60 97 61 98 def __init__(self, request, *args, **kwargs): 62 99 self.request = request 100 self.used = False 63 101 self._queued_messages = [] 64 self.used = False65 102 self.added_new = False 66 103 super(BaseStorage, self).__init__(*args, **kwargs) 67 104 … … 69 106 return len(self._loaded_messages) + len(self._queued_messages) 70 107 71 108 def __iter__(self): 72 self.used = True73 if self._queued_messages:74 self._loaded_messages.extend(self._queued_messages)75 self._queued_messages = []76 return iter(self._loaded_messages)109 if not self.used: 110 self.used = True 111 if self._queued_messages: 112 self._loaded_messages.extend(self._queued_messages) 113 self._queued_messages = [] 77 114 115 active_messages = [x for x in self._loaded_messages if x.active ()] 116 for x in active_messages: 117 x.on_display () 118 self._queued_messages.extend (active_messages) 119 return iter(self._queued_messages) 120 121 78 122 def __contains__(self, item): 79 123 return item in self._loaded_messages or item in self._queued_messages 80 124 … … 104 148 """ 105 149 raise NotImplementedError() 106 150 151 def filter_store(self, messages, response, *args, **kwargs): 152 ''' stores only active messages from given messages in storage ''' 153 filtered_messages = [x for x in messages if x.active ()] 154 return self._store(filtered_messages, response, *args, **kwargs) 155 156 107 157 def _store(self, messages, response, *args, **kwargs): 108 158 """ 109 159 Stores a list of messages, returning a list of any messages which could … … 130 180 be stored again. Otherwise, only messages added after the last 131 181 iteration will be stored. 132 182 """ 183 # if used or used and added, then _queued_messages contains all messages that should be saved 184 # if added, then save: all messages currently stored and added ones 133 185 self._prepare_messages(self._queued_messages) 134 186 if self.used: 135 return self. _store(self._queued_messages, response)187 return self.filter_store(self._queued_messages, response) 136 188 elif self.added_new: 137 189 messages = self._loaded_messages + self._queued_messages 138 return self. _store(messages, response)190 return self.filter_store(messages, response) 139 191 140 def add(self, level, message, extra_tags='' ):192 def add(self, level, message, extra_tags='', restrictions = []): 141 193 """ 142 194 Queues a message to be stored. 143 195 … … 152 204 return 153 205 # Add the message. 154 206 self.added_new = True 155 message = Message(level, message, extra_tags=extra_tags )207 message = Message(level, message, extra_tags=extra_tags, restrictions = restrictions) 156 208 self._queued_messages.append(message) 157 209 158 210 def _get_level(self):