extension.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. class Extension(object):
  2. name = ''
  3. rsv1 = False
  4. rsv2 = False
  5. rsv3 = False
  6. opcodes = []
  7. defaults = {}
  8. request = {}
  9. def __init__(self, defaults={}, request={}):
  10. for param in defaults.keys() + request.keys():
  11. if param not in self.defaults:
  12. raise KeyError('unrecognized parameter "%s"' % param)
  13. # Copy dict first to avoid duplicate references to the same object
  14. self.defaults = dict(self.__class__.defaults)
  15. self.defaults.update(defaults)
  16. self.request = dict(self.__class__.request)
  17. self.request.update(request)
  18. def __str__(self):
  19. return '<Extension "%s" defaults=%s request=%s>' \
  20. % (self.name, self.defaults, self.request)
  21. def create_hook(self, **kwargs):
  22. params = {}
  23. params.update(self.defaults)
  24. params.update(kwargs)
  25. return self.Hook(self, **params)
  26. class Hook:
  27. def __init__(self, extension, **kwargs):
  28. self.extension = extension
  29. for param, value in kwargs.iteritems():
  30. setattr(self, param, value)
  31. def send(self, frame):
  32. return frame
  33. def recv(self, frame):
  34. return frame
  35. def filter_extensions(extensions):
  36. """
  37. Remove extensions that use conflicting rsv bits and/or opcodes, with the
  38. first options being the most preferable.
  39. """
  40. rsv1_reserved = False
  41. rsv2_reserved = False
  42. rsv3_reserved = False
  43. opcodes_reserved = []
  44. compat = []
  45. for ext in extensions:
  46. if ext.rsv1 and rsv1_reserved \
  47. or ext.rsv2 and rsv2_reserved \
  48. or ext.rsv3 and rsv3_reserved \
  49. or len(set(ext.opcodes) & set(opcodes_reserved)):
  50. continue
  51. rsv1_reserved |= ext.rsv1
  52. rsv2_reserved |= ext.rsv2
  53. rsv3_reserved |= ext.rsv3
  54. opcodes_reserved.extend(ext.opcodes)
  55. compat.append(ext)
  56. return compat