/zulip_bots/zulip_bots/provision.py

https://github.com/zulip/python-zulip-api
Python | 80 lines | 62 code | 16 blank | 2 comment | 7 complexity | 5e601badecd42a42e6dd7fc86035462f MD5 | raw file
  1. #!/usr/bin/env python3
  2. import argparse
  3. import logging
  4. import os
  5. import sys
  6. import subprocess
  7. import glob
  8. from typing import Iterator
  9. def get_bot_paths() -> Iterator[str]:
  10. current_dir = os.path.dirname(os.path.abspath(__file__))
  11. bots_dir = os.path.join(current_dir, "bots")
  12. bots_subdirs = map(lambda d: os.path.abspath(d), glob.glob(bots_dir + '/*'))
  13. paths = filter(lambda d: os.path.isdir(d), bots_subdirs)
  14. return paths
  15. def provision_bot(path_to_bot: str, force: bool) -> None:
  16. req_path = os.path.join(path_to_bot, 'requirements.txt')
  17. if os.path.isfile(req_path):
  18. bot_name = os.path.basename(path_to_bot)
  19. logging.info('Installing dependencies for {}...'.format(bot_name))
  20. # pip install -r $BASEDIR/requirements.txt -t $BASEDIR/bot_dependencies --quiet
  21. rcode = subprocess.call(['pip', 'install', '-r', req_path])
  22. if rcode != 0:
  23. logging.error('Error. Check output of `pip install` above for details.')
  24. if not force:
  25. logging.error('Use --force to try running anyway.')
  26. sys.exit(rcode) # Use pip's exit code
  27. else:
  28. logging.info('Installed dependencies successfully.')
  29. def parse_args(available_bots: Iterator[str]) -> argparse.Namespace:
  30. usage = """
  31. Installs dependencies of bots in the bots/<bot_name>
  32. directories. Add a requirements.txt file in a bot's folder
  33. before provisioning.
  34. To provision all bots, use:
  35. ./provision.py
  36. To provision specific bots, use:
  37. ./provision.py [names of bots]
  38. Example: ./provision.py helloworld xkcd wikipedia
  39. """
  40. parser = argparse.ArgumentParser(usage=usage)
  41. parser.add_argument('bots_to_provision',
  42. metavar='bots',
  43. nargs='*',
  44. default=available_bots,
  45. help='specific bots to provision (default is all)')
  46. parser.add_argument('--force',
  47. default=False,
  48. action="store_true",
  49. help='Continue installation despite pip errors.')
  50. parser.add_argument('--quiet', '-q',
  51. action='store_true',
  52. default=False,
  53. help='Turn off logging output.')
  54. return parser.parse_args()
  55. def main() -> None:
  56. options = parse_args(available_bots=get_bot_paths())
  57. if not options.quiet:
  58. logging.basicConfig(stream=sys.stdout, level=logging.INFO)
  59. for bot in options.bots_to_provision:
  60. provision_bot(bot, options.force)
  61. if __name__ == '__main__':
  62. main()