bots: Add dependencies management.
Adds the file api/bots_api/provision.py that installs dependencies for bots using pip. This file is also used by run.py when running a bot. However, for testing, you need to separately provision the bots.
This commit is contained in:
		
							parent
							
								
									bafbd3689b
								
							
						
					
					
						commit
						2645c97276
					
				
					 6 changed files with 90 additions and 9 deletions
				
			
		
							
								
								
									
										1
									
								
								bots/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								bots/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| bot_dependencies | ||||
							
								
								
									
										1
									
								
								bots/thesaurus/requirements.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								bots/thesaurus/requirements.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| PyDictionary | ||||
|  | @ -2,11 +2,7 @@ | |||
| from __future__ import print_function | ||||
| import sys | ||||
| import logging | ||||
| try: | ||||
|     from PyDictionary import PyDictionary as Dictionary | ||||
| except ImportError: | ||||
|     logging.error("Dependency Missing!") | ||||
|     sys.exit(0) | ||||
| from PyDictionary import PyDictionary as Dictionary | ||||
| 
 | ||||
| #Uses Python's Dictionary module | ||||
| #  pip install PyDictionary | ||||
|  |  | |||
							
								
								
									
										67
									
								
								bots_api/provision.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										67
									
								
								bots_api/provision.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,67 @@ | |||
| #!/usr/bin/env python | ||||
| 
 | ||||
| from __future__ import absolute_import | ||||
| from __future__ import print_function | ||||
| 
 | ||||
| import argparse | ||||
| import os | ||||
| import sys | ||||
| import pip | ||||
| 
 | ||||
| def provision_bot(path_to_bot, force): | ||||
|     # type: (str, bool) -> None | ||||
|     req_path = os.path.join(path_to_bot, 'requirements.txt') | ||||
|     install_path = os.path.join(path_to_bot, 'bot_dependencies') | ||||
|     if os.path.isfile(req_path): | ||||
|         print('Installing dependencies...') | ||||
|         if not os.path.isdir(install_path): | ||||
|             os.makedirs(install_path) | ||||
|         # pip install -r $BASEDIR/requirements.txt -t $BASEDIR/bot_dependencies --quiet | ||||
|         rcode = pip.main(['install', '-r', req_path, '-t', install_path, '--quiet']) | ||||
|         if not rcode == 0: | ||||
|             print('Error. Check output of `pip install` above for details.') | ||||
|             if not force: | ||||
|                 print('Use --force to try running anyway.') | ||||
|                 sys.exit(rcode)  # Use pip's exit code | ||||
|         else: | ||||
|             print('Installed.') | ||||
|         sys.path.insert(0, install_path) | ||||
| 
 | ||||
| def dir_join(dir1, dir2): | ||||
|     # type: (str, str) -> str | ||||
|     return os.path.abspath(os.path.join(dir1, dir2)) | ||||
| 
 | ||||
| def run(): | ||||
|     # type: () -> None | ||||
|     usage = ''' | ||||
|         Installs dependencies of bots in api/bots directory. Add a | ||||
|         reuirements.txt file in a bot's folder before provisioning. | ||||
| 
 | ||||
|         To provision all bots, use: | ||||
|         ./provision.py | ||||
| 
 | ||||
|         To provision specific bots, use: | ||||
|         ./provision.py [names of bots] | ||||
|         Example: ./provision.py helloworld xkcd wikipedia | ||||
| 
 | ||||
|         ''' | ||||
| 
 | ||||
|     bots_dir = dir_join(os.path.dirname(os.path.abspath(__file__)), '../bots') | ||||
|     available_bots = [b for b in os.listdir(bots_dir) if os.path.isdir(dir_join(bots_dir, b))] | ||||
| 
 | ||||
|     parser = argparse.ArgumentParser(usage=usage) | ||||
|     parser.add_argument('bots_to_provision', | ||||
|                         metavar='bots', | ||||
|                         nargs='*', | ||||
|                         default=available_bots, | ||||
|                         help='specific bots to provision (default is all)') | ||||
|     parser.add_argument('--force', | ||||
|                         default=False, | ||||
|                         action="store_true", | ||||
|                         help='Continue installation despite pip errors.') | ||||
|     options = parser.parse_args() | ||||
|     for bot in options.bots_to_provision: | ||||
|         provision_bot(os.path.join(dir_join(bots_dir, bot)), options.force) | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     run() | ||||
|  | @ -7,6 +7,7 @@ import logging | |||
| import optparse | ||||
| import os | ||||
| import sys | ||||
| import provision | ||||
| from types import ModuleType | ||||
| 
 | ||||
| our_dir = os.path.dirname(os.path.abspath(__file__)) | ||||
|  | @ -14,8 +15,8 @@ sys.path.insert(0, our_dir) | |||
| 
 | ||||
| from bot_lib import run_message_handler_for_bot | ||||
| 
 | ||||
| def get_lib_module(bots_fn): | ||||
|     # type: (str) -> ModuleType | ||||
| def validate_path(bots_fn): | ||||
|     # type: (str) -> None | ||||
|     bots_fn = os.path.realpath(bots_fn) | ||||
|     if not os.path.dirname(bots_fn).startswith(os.path.normpath(os.path.join(our_dir, "../bots"))): | ||||
|         print('Sorry, we will only import code from api/bots.') | ||||
|  | @ -24,6 +25,9 @@ def get_lib_module(bots_fn): | |||
|     if not bots_fn.endswith('.py'): | ||||
|         print('Please use a .py extension for library files.') | ||||
|         sys.exit(1) | ||||
| 
 | ||||
| def get_lib_module(bots_fn): | ||||
|     # type: (str) -> ModuleType | ||||
|     base_bots_fn = os.path.basename(os.path.splitext(bots_fn)[0]) | ||||
|     sys.path.insert(1, os.path.dirname(bots_fn)) | ||||
|     module_name = base_bots_fn | ||||
|  | @ -51,14 +55,24 @@ def run(): | |||
|     parser.add_option('--config-file', | ||||
|                       action='store', | ||||
|                       help='(alternate config file to ~/.zuliprc)') | ||||
|     parser.add_option('--provision', | ||||
|                       action='store_true', | ||||
|                       help='Install dependencies for the bot') | ||||
|     parser.add_option('--force', | ||||
|                       action='store_true', | ||||
|                       help='Try running the bot even if dependencies install fails.') | ||||
|     (options, args) = parser.parse_args() | ||||
| 
 | ||||
|     if len(args) == 0: | ||||
|         print('You must specify a library!') | ||||
|         sys.exit(1) | ||||
|     bots_fn = args[0] | ||||
| 
 | ||||
|     lib_module = get_lib_module(bots_fn=args[0]) | ||||
| 
 | ||||
|     validate_path(bots_fn) | ||||
|     if options.provision: | ||||
|         print("Provisioning") | ||||
|         provision.provision_bot(os.path.dirname(bots_fn), options.force) | ||||
|     lib_module = get_lib_module(bots_fn) | ||||
|     if not options.quiet: | ||||
|         logging.basicConfig(stream=sys.stdout, level=logging.INFO) | ||||
| 
 | ||||
|  |  | |||
|  | @ -53,6 +53,8 @@ if __name__ == '__main__': | |||
| 
 | ||||
|     suites = [] | ||||
|     for bot_to_test in args.bots_to_test: | ||||
|         dep_path = os.path.join(bots_test_dir, bot_to_test, 'bot_dependencies') | ||||
|         sys.path.insert(0, dep_path) | ||||
|         try: | ||||
|             suites.append(loader.discover(start_dir = dir_join(bots_test_dir, bot_to_test), | ||||
|                                           top_level_dir = root_dir)) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Rohitt Vashishtha
						Rohitt Vashishtha