Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mapping.py 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. ##############################################################################
  2. #
  3. # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
  4. # All Rights Reserved.
  5. #
  6. # This software is subject to the provisions of the Zope Public License,
  7. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  8. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  9. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  10. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  11. # FOR A PARTICULAR PURPOSE
  12. #
  13. ##############################################################################
  14. """Python implementation of persistent base types
  15. $Id$"""
  16. import persistent
  17. from persistent._compat import IterableUserDict
  18. class default(object):
  19. def __init__(self, func):
  20. self.func = func
  21. def __get__(self, inst, class_):
  22. if inst is None:
  23. return self
  24. return self.func(inst)
  25. class PersistentMapping(IterableUserDict, persistent.Persistent):
  26. """A persistent wrapper for mapping objects.
  27. This class allows wrapping of mapping objects so that object
  28. changes are registered. As a side effect, mapping objects may be
  29. subclassed.
  30. A subclass of PersistentMapping or any code that adds new
  31. attributes should not create an attribute named _container. This
  32. is reserved for backwards compatibility reasons.
  33. """
  34. # UserDict provides all of the mapping behavior. The
  35. # PersistentMapping class is responsible marking the persistent
  36. # state as changed when a method actually changes the state. At
  37. # the mapping API evolves, we may need to add more methods here.
  38. __super_delitem = IterableUserDict.__delitem__
  39. __super_setitem = IterableUserDict.__setitem__
  40. __super_clear = IterableUserDict.clear
  41. __super_update = IterableUserDict.update
  42. __super_setdefault = IterableUserDict.setdefault
  43. __super_pop = IterableUserDict.pop
  44. __super_popitem = IterableUserDict.popitem
  45. def __delitem__(self, key):
  46. self.__super_delitem(key)
  47. self._p_changed = 1
  48. def __setitem__(self, key, v):
  49. self.__super_setitem(key, v)
  50. self._p_changed = 1
  51. def clear(self):
  52. self.__super_clear()
  53. self._p_changed = 1
  54. def update(self, b):
  55. self.__super_update(b)
  56. self._p_changed = 1
  57. def setdefault(self, key, failobj=None):
  58. # We could inline all of UserDict's implementation into the
  59. # method here, but I'd rather not depend at all on the
  60. # implementation in UserDict (simple as it is).
  61. if not key in self.data:
  62. self._p_changed = 1
  63. return self.__super_setdefault(key, failobj)
  64. def pop(self, key, *args):
  65. self._p_changed = 1
  66. return self.__super_pop(key, *args)
  67. def popitem(self):
  68. self._p_changed = 1
  69. return self.__super_popitem()
  70. # Old implementations used _container rather than data.
  71. # Use a descriptor to provide data when we have _container instead
  72. @default
  73. def data(self):
  74. # We don't want to cause a write on read, so wer're careful not to
  75. # do anything that would cause us to become marked as changed, however,
  76. # if we're modified, then the saved record will have data, not
  77. # _container.
  78. data = self.__dict__.pop('_container')
  79. self.__dict__['data'] = data
  80. return data