autocommand.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. # Copyright 2014-2015 Nathan West
  2. #
  3. # This file is part of autocommand.
  4. #
  5. # autocommand is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU Lesser General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # autocommand is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU Lesser General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Lesser General Public License
  16. # along with autocommand. If not, see <http://www.gnu.org/licenses/>.
  17. from .autoparse import autoparse
  18. from .automain import automain
  19. try:
  20. from .autoasync import autoasync
  21. except ImportError: # pragma: no cover
  22. pass
  23. def autocommand(
  24. module, *,
  25. description=None,
  26. epilog=None,
  27. add_nos=False,
  28. parser=None,
  29. loop=None,
  30. forever=False,
  31. pass_loop=False):
  32. if callable(module):
  33. raise TypeError('autocommand requires a module name argument')
  34. def autocommand_decorator(func):
  35. # Step 1: if requested, run it all in an asyncio event loop. autoasync
  36. # patches the __signature__ of the decorated function, so that in the
  37. # event that pass_loop is True, the `loop` parameter of the original
  38. # function will *not* be interpreted as a command-line argument by
  39. # autoparse
  40. if loop is not None or forever or pass_loop:
  41. func = autoasync(
  42. func,
  43. loop=None if loop is True else loop,
  44. pass_loop=pass_loop,
  45. forever=forever)
  46. # Step 2: create parser. We do this second so that the arguments are
  47. # parsed and passed *before* entering the asyncio event loop, if it
  48. # exists. This simplifies the stack trace and ensures errors are
  49. # reported earlier. It also ensures that errors raised during parsing &
  50. # passing are still raised if `forever` is True.
  51. func = autoparse(
  52. func,
  53. description=description,
  54. epilog=epilog,
  55. add_nos=add_nos,
  56. parser=parser)
  57. # Step 3: call the function automatically if __name__ == '__main__' (or
  58. # if True was provided)
  59. func = automain(module)(func)
  60. return func
  61. return autocommand_decorator