skeleton.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. """
  2. This is a skeleton file that can serve as a starting point for a Python
  3. console script. To run this script uncomment the following lines in the
  4. ``[options.entry_points]`` section in ``setup.cfg``::
  5. console_scripts =
  6. fibonacci = rfidacd.skeleton:run
  7. Then run ``pip install .`` (or ``pip install -e .`` for editable mode)
  8. which will install the command ``fibonacci`` inside your current environment.
  9. Besides console scripts, the header (i.e. until ``_logger``...) of this file can
  10. also be used as template for Python modules.
  11. Note:
  12. This skeleton file can be safely removed if not needed!
  13. References:
  14. - https://setuptools.readthedocs.io/en/latest/userguide/entry_point.html
  15. - https://pip.pypa.io/en/stable/reference/pip_install
  16. """
  17. import argparse
  18. import logging
  19. import sys
  20. from rfidacd import __version__
  21. __author__ = "Thomas Verchow"
  22. __copyright__ = "Thomas Verchow"
  23. __license__ = "MIT"
  24. _logger = logging.getLogger(__name__)
  25. # ---- Python API ----
  26. # The functions defined in this section can be imported by users in their
  27. # Python scripts/interactive interpreter, e.g. via
  28. # `from rfidacd.skeleton import fib`,
  29. # when using this Python module as a library.
  30. def fib(n):
  31. """Fibonacci example function
  32. Args:
  33. n (int): integer
  34. Returns:
  35. int: n-th Fibonacci number
  36. """
  37. assert n > 0
  38. a, b = 1, 1
  39. for i in range(n - 1):
  40. a, b = b, a + b
  41. return a
  42. # ---- CLI ----
  43. # The functions defined in this section are wrappers around the main Python
  44. # API allowing them to be called directly from the terminal as a CLI
  45. # executable/script.
  46. def parse_args(args):
  47. """Parse command line parameters
  48. Args:
  49. args (List[str]): command line parameters as list of strings
  50. (for example ``["--help"]``).
  51. Returns:
  52. :obj:`argparse.Namespace`: command line parameters namespace
  53. """
  54. parser = argparse.ArgumentParser(description="Just a Fibonacci demonstration")
  55. parser.add_argument(
  56. "--version",
  57. action="version",
  58. version="rfidacd {ver}".format(ver=__version__),
  59. )
  60. parser.add_argument(dest="n", help="n-th Fibonacci number", type=int, metavar="INT")
  61. parser.add_argument(
  62. "-v",
  63. "--verbose",
  64. dest="loglevel",
  65. help="set loglevel to INFO",
  66. action="store_const",
  67. const=logging.INFO,
  68. )
  69. parser.add_argument(
  70. "-vv",
  71. "--very-verbose",
  72. dest="loglevel",
  73. help="set loglevel to DEBUG",
  74. action="store_const",
  75. const=logging.DEBUG,
  76. )
  77. return parser.parse_args(args)
  78. def setup_logging(loglevel):
  79. """Setup basic logging
  80. Args:
  81. loglevel (int): minimum loglevel for emitting messages
  82. """
  83. logformat = "[%(asctime)s] %(levelname)s:%(name)s:%(message)s"
  84. logging.basicConfig(
  85. level=loglevel, stream=sys.stdout, format=logformat, datefmt="%Y-%m-%d %H:%M:%S"
  86. )
  87. def main(args):
  88. """Wrapper allowing :func:`fib` to be called with string arguments in a CLI fashion
  89. Instead of returning the value from :func:`fib`, it prints the result to the
  90. ``stdout`` in a nicely formated message.
  91. Args:
  92. args (List[str]): command line parameters as list of strings
  93. (for example ``["--verbose", "42"]``).
  94. """
  95. args = parse_args(args)
  96. setup_logging(args.loglevel)
  97. _logger.debug("Starting crazy calculations...")
  98. print("The {}-th Fibonacci number is {}".format(args.n, fib(args.n)))
  99. _logger.info("Script ends here")
  100. def run():
  101. """Calls :func:`main` passing the CLI arguments extracted from :obj:`sys.argv`
  102. This function can be used as entry point to create console scripts with setuptools.
  103. """
  104. main(sys.argv[1:])
  105. if __name__ == "__main__":
  106. # ^ This is a guard statement that will prevent the following code from
  107. # being executed in the case someone imports this file instead of
  108. # executing it as a script.
  109. # https://docs.python.org/3/library/__main__.html
  110. # After installing your project with pip, users can also run your Python
  111. # modules as scripts via the ``-m`` flag, as defined in PEP 338::
  112. #
  113. # python -m rfidacd.skeleton 42
  114. #
  115. run()