Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pack_manager.py Source File

pack_manager.py

00001 from __future__ import print_function, division, absolute_import
00002 import argparse
00003 from os.path import basename
00004 from tools.arm_pack_manager import Cache
00005 from os.path import basename, join, dirname, exists
00006 from os import makedirs
00007 from itertools import takewhile
00008 from fuzzywuzzy import process
00009 from .arm_pack_manager import Cache
00010 
00011 parser = argparse.ArgumentParser(description='A Handy little utility for keeping your cache of pack files up to date.')
00012 subparsers = parser.add_subparsers(title="Commands")
00013 
00014 def subcommand(name, *args, **kwargs):
00015     def subcommand(command):
00016         subparser = subparsers.add_parser(name, **kwargs)
00017 
00018         for arg in args:
00019             arg = dict(arg)
00020             opt = arg['name']
00021             del arg['name']
00022 
00023             if isinstance(opt, basestring):
00024                 subparser.add_argument(opt, **arg)
00025             else:
00026                 subparser.add_argument(*opt, **arg)
00027 
00028         subparser.add_argument("-v", "--verbose", action="store_true", dest="verbose", help="Verbose diagnostic output")
00029         subparser.add_argument("-vv", "--very_verbose", action="store_true", dest="very_verbose", help="Very verbose diagnostic output")
00030         subparser.add_argument("--no-timeouts", action="store_true", help="Remove all timeouts and try to download unconditionally")
00031         subparser.add_argument("--and", action="store_true", dest="intersection", help="combine search terms as if with an and")
00032         subparser.add_argument("--or", action="store_false", dest="intersection", help="combine search terms as if with an or")
00033         subparser.add_argument("--union", action="store_false", dest="intersection", help="combine search terms as if with a set union")
00034         subparser.add_argument("--intersection", action="store_true", dest="intersection", help="combine search terms as if with a set intersection")
00035         
00036         def thunk(parsed_args):
00037             cache = Cache(not parsed_args.verbose, parsed_args.no_timeouts)
00038             argv = [arg['dest'] if 'dest' in arg else arg['name'] for arg in args]
00039             argv = [(arg if isinstance(arg, basestring) else arg[-1]).strip('-')
00040                     for arg in argv]
00041             argv = {arg: vars(parsed_args)[arg] for arg in argv
00042                     if vars(parsed_args)[arg] is not None}
00043 
00044             return command(cache, **argv)
00045 
00046         subparser.set_defaults(command=thunk)
00047         return command
00048     return subcommand
00049 
00050 def user_selection (message, options) :
00051     print(message)
00052     for choice, index in zip(options, range(len(options))) :
00053         print("({}) {}".format(index, choice))
00054     pick = None
00055     while pick is None :
00056         stdout.write("please select an integer from 0 to {} or \"all\"".format(len(options)-1))
00057         input = raw_input()
00058         try :
00059             if input == "all" :
00060                 pick = options
00061             else :
00062                 pick = [options[int(input)]]
00063         except ValueError :
00064             print("I did not understand your input")
00065     return pick
00066 
00067 def fuzzy_find(matches, urls) :
00068     choices = {}
00069     for match in matches :
00070         for key, value in process.extract(match, urls, limit=None) :
00071             choices.setdefault(key, 0)
00072             choices[key] += value
00073     choices = sorted([(v, k) for k, v in choices.items()], reverse=True)
00074     if not choices : return []
00075     elif len(choices) == 1 : return [choices[0][1]]
00076     elif choices[0][0] > choices[1][0] : choices = choices[:1]
00077     else : choices = list(takewhile(lambda t: t[0] == choices[0][0], choices))
00078     return [v for k,v in choices]
00079 
00080 @subcommand('cache',
00081             dict(name='matches', nargs="*",
00082                  help="a bunch of things to search for in part names"),
00083             dict(name=['-e','--everything'], action="store_true",
00084                  help="download everything possible"),
00085             dict(name=['-d','--descriptors'], action="store_true",
00086                  help="download all descriptors"),
00087             dict(name=["-b","--batch"], action="store_true",
00088                  help="don't ask for user input and assume download all"),
00089             help="Cache a group of PACK or PDSC files")
00090 def command_cache (cache, matches, everything=False, descriptors=False, batch=False, verbose= False, intersection=True) :
00091     if everything :
00092         cache.cache_everything()
00093         return True
00094     if descriptors :
00095         cache.cache_descriptors()
00096         return True
00097     if not matches :
00098         print("No action specified nothing to do")
00099     else :
00100         urls = cache.get_urls()
00101         if intersection :
00102             choices = fuzzy_find(matches, map(basename, urls))
00103         else :
00104             choices = sum([fuzzy_find([m], map(basename, urls)) for m in matches], [])
00105         if not batch and len(choices) > 1 :
00106             choices = user_selection("Please select a file to cache", choices)
00107         to_download = []
00108         for choice in choices :
00109             for url in urls :
00110                 if choice in url :
00111                     to_download.append(url)
00112         cache.cache_pack_list(to_download)
00113         return True
00114 
00115 
00116 @subcommand('find-part',
00117             dict(name='matches', nargs="+", help="words to match to processors"),
00118             dict(name=['-l',"--long"], action="store_true",
00119                  help="print out part details with part"),
00120             dict(name=['-p', '--parts-only'], action="store_false", dest="print_aliases"),
00121             dict(name=['-a', '--aliases-only'], action="store_false", dest="print_parts"),
00122             help="Find a Part and it's description within the cache")
00123 def command_find_part (cache, matches, long=False, intersection=True,
00124                        print_aliases=True, print_parts=True) :
00125     if long :
00126         import pprint
00127         pp = pprint.PrettyPrinter()
00128     parts = cache.index
00129     if intersection :
00130         choices = fuzzy_find(matches, parts.keys())
00131         aliases = fuzzy_find(matches, cache.aliases.keys())
00132     else :
00133         choices = sum([fuzzy_find([m], parts.keys()) for m in matches], [])
00134         aliases = sum([fuzzy_find([m], cache.aliases.keys()) for m in matches], [])
00135     if print_parts:
00136         for part in choices :
00137             print(part)
00138             if long :
00139                 pp.pprint(cache.index[part])
00140     if print_aliases:
00141         for alias in aliases :
00142             print(alias)
00143             if long :
00144                 pp.pprint(cache.index[cache.aliases[alias]])
00145 
00146 @subcommand('dump-parts',
00147             dict(name='out', help='directory to dump to'),
00148             dict(name='parts', nargs='+', help='parts to dump'),
00149             help='Create a directory with an index.json describing the part and all of their associated flashing algorithms.'
00150 )
00151 def command_dump_parts (cache, out, parts, intersection=False) :
00152     index = {}
00153     if intersection :
00154         for part in fuzzy_find(parts, cache.index):
00155             index.update(cache.index[part])
00156     else :
00157         for part in parts :
00158             index.update(dict(cache.find_device(part)))
00159     for n, p in index.items() :
00160         try :
00161             if not exists(join(out, dirname(p['algorithm']['file']))) :
00162                 makedirs(join(out, dirname(p['algorithm']['file'])))
00163             with open(join(out, p['algorithm']['file']), "wb+") as fd :
00164                 fd.write(cache.get_flash_algorthim_binary(n).read())
00165         except KeyError:
00166             print("[Warning] {} does not have an associated flashing algorithm".format(n))
00167     with open(join(out, "index.json"), "wb+") as fd :
00168         dump(index,fd)
00169 
00170 
00171 @subcommand('cache-part',
00172             dict(name='matches', nargs="+", help="words to match to devices"),
00173             help='Cache PACK files associated with the parts matching the provided words')
00174 def command_cache_part (cache, matches, intersection=True) :
00175     index = cache.index
00176     if intersection :
00177         choices = fuzzy_find(matches, index.keys())
00178         aliases = fuzzy_find(matches, cache.aliases.keys())
00179     else :
00180         choices = sum([fuzzy_find([m], index.keys()) for m in matches], [])
00181         aliases = sum([fuzzy_find([m], cache.aliases.keys()) for m in matches], [])
00182     urls = set([index[c]['pdsc_file'] for c in choices])
00183     urls += set([index[cache.aliasse[a]] for a in aliases])
00184     cache.cache_pack_list(list(urls))
00185 
00186 def get_argparse() :
00187     return parser
00188 
00189 def main() :
00190     args = parser.parse_args()
00191     args.command(args)
00192