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.

abstract.py 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. """
  2. kombu.abstract
  3. ==============
  4. Object utilities.
  5. """
  6. from __future__ import absolute_import
  7. from copy import copy
  8. from .connection import maybe_channel
  9. from .exceptions import NotBoundError
  10. from .utils import ChannelPromise
  11. __all__ = ['Object', 'MaybeChannelBound']
  12. def unpickle_dict(cls, kwargs):
  13. return cls(**kwargs)
  14. def _any(v):
  15. return v
  16. class Object(object):
  17. """Common base class supporting automatic kwargs->attributes handling,
  18. and cloning."""
  19. attrs = ()
  20. def __init__(self, *args, **kwargs):
  21. for name, type_ in self.attrs:
  22. value = kwargs.get(name)
  23. if value is not None:
  24. setattr(self, name, (type_ or _any)(value))
  25. else:
  26. try:
  27. getattr(self, name)
  28. except AttributeError:
  29. setattr(self, name, None)
  30. def as_dict(self, recurse=False):
  31. def f(obj, type):
  32. if recurse and isinstance(obj, Object):
  33. return obj.as_dict(recurse=True)
  34. return type(obj) if type else obj
  35. return dict(
  36. (attr, f(getattr(self, attr), type)) for attr, type in self.attrs
  37. )
  38. def __reduce__(self):
  39. return unpickle_dict, (self.__class__, self.as_dict())
  40. def __copy__(self):
  41. return self.__class__(**self.as_dict())
  42. class MaybeChannelBound(Object):
  43. """Mixin for classes that can be bound to an AMQP channel."""
  44. _channel = None
  45. _is_bound = False
  46. #: Defines whether maybe_declare can skip declaring this entity twice.
  47. can_cache_declaration = False
  48. def __call__(self, channel):
  49. """`self(channel) -> self.bind(channel)`"""
  50. return self.bind(channel)
  51. def bind(self, channel):
  52. """Create copy of the instance that is bound to a channel."""
  53. return copy(self).maybe_bind(channel)
  54. def maybe_bind(self, channel):
  55. """Bind instance to channel if not already bound."""
  56. if not self.is_bound and channel:
  57. self._channel = maybe_channel(channel)
  58. self.when_bound()
  59. self._is_bound = True
  60. return self
  61. def revive(self, channel):
  62. """Revive channel after the connection has been re-established.
  63. Used by :meth:`~kombu.Connection.ensure`.
  64. """
  65. if self.is_bound:
  66. self._channel = channel
  67. self.when_bound()
  68. def when_bound(self):
  69. """Callback called when the class is bound."""
  70. pass
  71. def __repr__(self, item=''):
  72. item = item or type(self).__name__
  73. if self.is_bound:
  74. return '<{0} bound to chan:{1}>'.format(
  75. item or type(self).__name__, self.channel.channel_id)
  76. return '<unbound {0}>'.format(item)
  77. @property
  78. def is_bound(self):
  79. """Flag set if the channel is bound."""
  80. return self._is_bound and self._channel is not None
  81. @property
  82. def channel(self):
  83. """Current channel if the object is bound."""
  84. channel = self._channel
  85. if channel is None:
  86. raise NotBoundError(
  87. "Can't call method on {0} not bound to a channel".format(
  88. type(self).__name__))
  89. if isinstance(channel, ChannelPromise):
  90. channel = self._channel = channel()
  91. return channel