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.

151 lines
4.2 KiB

4 years ago
  1. import abc
  2. from collections.abc import Sequence
  3. import attr
  4. from . import hdrs
  5. __all__ = ('AbstractRouteDef', 'RouteDef', 'StaticDef', 'RouteTableDef',
  6. 'head', 'options', 'get', 'post', 'patch', 'put', 'delete',
  7. 'route', 'view', 'static')
  8. class AbstractRouteDef(abc.ABC):
  9. @abc.abstractmethod
  10. def register(self, router):
  11. pass # pragma: no cover
  12. @attr.s(frozen=True, repr=False, slots=True)
  13. class RouteDef(AbstractRouteDef):
  14. method = attr.ib(type=str)
  15. path = attr.ib(type=str)
  16. handler = attr.ib()
  17. kwargs = attr.ib()
  18. def __repr__(self):
  19. info = []
  20. for name, value in sorted(self.kwargs.items()):
  21. info.append(", {}={!r}".format(name, value))
  22. return ("<RouteDef {method} {path} -> {handler.__name__!r}"
  23. "{info}>".format(method=self.method, path=self.path,
  24. handler=self.handler, info=''.join(info)))
  25. def register(self, router):
  26. if self.method in hdrs.METH_ALL:
  27. reg = getattr(router, 'add_'+self.method.lower())
  28. reg(self.path, self.handler, **self.kwargs)
  29. else:
  30. router.add_route(self.method, self.path, self.handler,
  31. **self.kwargs)
  32. @attr.s(frozen=True, repr=False, slots=True)
  33. class StaticDef(AbstractRouteDef):
  34. prefix = attr.ib(type=str)
  35. path = attr.ib(type=str)
  36. kwargs = attr.ib()
  37. def __repr__(self):
  38. info = []
  39. for name, value in sorted(self.kwargs.items()):
  40. info.append(", {}={!r}".format(name, value))
  41. return ("<StaticDef {prefix} -> {path}"
  42. "{info}>".format(prefix=self.prefix, path=self.path,
  43. info=''.join(info)))
  44. def register(self, router):
  45. router.add_static(self.prefix, self.path, **self.kwargs)
  46. def route(method, path, handler, **kwargs):
  47. return RouteDef(method, path, handler, kwargs)
  48. def head(path, handler, **kwargs):
  49. return route(hdrs.METH_HEAD, path, handler, **kwargs)
  50. def options(path, handler, **kwargs):
  51. return route(hdrs.METH_OPTIONS, path, handler, **kwargs)
  52. def get(path, handler, *, name=None, allow_head=True, **kwargs):
  53. return route(hdrs.METH_GET, path, handler, name=name,
  54. allow_head=allow_head, **kwargs)
  55. def post(path, handler, **kwargs):
  56. return route(hdrs.METH_POST, path, handler, **kwargs)
  57. def put(path, handler, **kwargs):
  58. return route(hdrs.METH_PUT, path, handler, **kwargs)
  59. def patch(path, handler, **kwargs):
  60. return route(hdrs.METH_PATCH, path, handler, **kwargs)
  61. def delete(path, handler, **kwargs):
  62. return route(hdrs.METH_DELETE, path, handler, **kwargs)
  63. def view(path, handler, **kwargs):
  64. return route(hdrs.METH_ANY, path, handler, **kwargs)
  65. def static(prefix, path, **kwargs):
  66. return StaticDef(prefix, path, kwargs)
  67. class RouteTableDef(Sequence):
  68. """Route definition table"""
  69. def __init__(self):
  70. self._items = []
  71. def __repr__(self):
  72. return "<RouteTableDef count={}>".format(len(self._items))
  73. def __getitem__(self, index):
  74. return self._items[index]
  75. def __iter__(self):
  76. return iter(self._items)
  77. def __len__(self):
  78. return len(self._items)
  79. def __contains__(self, item):
  80. return item in self._items
  81. def route(self, method, path, **kwargs):
  82. def inner(handler):
  83. self._items.append(RouteDef(method, path, handler, kwargs))
  84. return handler
  85. return inner
  86. def head(self, path, **kwargs):
  87. return self.route(hdrs.METH_HEAD, path, **kwargs)
  88. def get(self, path, **kwargs):
  89. return self.route(hdrs.METH_GET, path, **kwargs)
  90. def post(self, path, **kwargs):
  91. return self.route(hdrs.METH_POST, path, **kwargs)
  92. def put(self, path, **kwargs):
  93. return self.route(hdrs.METH_PUT, path, **kwargs)
  94. def patch(self, path, **kwargs):
  95. return self.route(hdrs.METH_PATCH, path, **kwargs)
  96. def delete(self, path, **kwargs):
  97. return self.route(hdrs.METH_DELETE, path, **kwargs)
  98. def view(self, path, **kwargs):
  99. return self.route(hdrs.METH_ANY, path, **kwargs)
  100. def static(self, prefix, path, **kwargs):
  101. self._items.append(StaticDef(prefix, path, kwargs))