Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-sdk-tools by
arm_pack_manager/__init__.py@32:8ea194f6145b, 2017-01-04 (annotated)
- Committer:
- The Other Jimmy
- Date:
- Wed Jan 04 11:58:24 2017 -0600
- Revision:
- 32:8ea194f6145b
Update tools to follow mbed-os tools release 5.3.1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
The Other Jimmy |
32:8ea194f6145b | 1 | from urllib2 import urlopen, URLError |
The Other Jimmy |
32:8ea194f6145b | 2 | from bs4 import BeautifulSoup |
The Other Jimmy |
32:8ea194f6145b | 3 | from os.path import join, dirname, basename |
The Other Jimmy |
32:8ea194f6145b | 4 | from os import makedirs |
The Other Jimmy |
32:8ea194f6145b | 5 | from errno import EEXIST |
The Other Jimmy |
32:8ea194f6145b | 6 | from threading import Thread |
The Other Jimmy |
32:8ea194f6145b | 7 | from Queue import Queue |
The Other Jimmy |
32:8ea194f6145b | 8 | from re import compile, sub |
The Other Jimmy |
32:8ea194f6145b | 9 | from sys import stderr, stdout |
The Other Jimmy |
32:8ea194f6145b | 10 | from fuzzywuzzy import process |
The Other Jimmy |
32:8ea194f6145b | 11 | from itertools import takewhile |
The Other Jimmy |
32:8ea194f6145b | 12 | import argparse |
The Other Jimmy |
32:8ea194f6145b | 13 | from json import dump, load |
The Other Jimmy |
32:8ea194f6145b | 14 | from zipfile import ZipFile |
The Other Jimmy |
32:8ea194f6145b | 15 | from tempfile import gettempdir |
The Other Jimmy |
32:8ea194f6145b | 16 | |
The Other Jimmy |
32:8ea194f6145b | 17 | RootPackURL = "http://www.keil.com/pack/index.idx" |
The Other Jimmy |
32:8ea194f6145b | 18 | |
The Other Jimmy |
32:8ea194f6145b | 19 | LocalPackDir = dirname(__file__) |
The Other Jimmy |
32:8ea194f6145b | 20 | LocalPackIndex = join(LocalPackDir, "index.json") |
The Other Jimmy |
32:8ea194f6145b | 21 | LocalPackAliases = join(LocalPackDir, "aliases.json") |
The Other Jimmy |
32:8ea194f6145b | 22 | |
The Other Jimmy |
32:8ea194f6145b | 23 | |
The Other Jimmy |
32:8ea194f6145b | 24 | protocol_matcher = compile("\w*://") |
The Other Jimmy |
32:8ea194f6145b | 25 | def strip_protocol(url) : |
The Other Jimmy |
32:8ea194f6145b | 26 | return protocol_matcher.sub("", str(url)) |
The Other Jimmy |
32:8ea194f6145b | 27 | |
The Other Jimmy |
32:8ea194f6145b | 28 | def largest_version(content) : |
The Other Jimmy |
32:8ea194f6145b | 29 | return sorted([t['version'] for t in content.package.releases('release')], reverse=True)[0] |
The Other Jimmy |
32:8ea194f6145b | 30 | |
The Other Jimmy |
32:8ea194f6145b | 31 | def do_queue(Class, function, interable) : |
The Other Jimmy |
32:8ea194f6145b | 32 | q = Queue() |
The Other Jimmy |
32:8ea194f6145b | 33 | threads = [Class(q, function) for each in range(20)] |
The Other Jimmy |
32:8ea194f6145b | 34 | for each in threads : |
The Other Jimmy |
32:8ea194f6145b | 35 | each.setDaemon(True) |
The Other Jimmy |
32:8ea194f6145b | 36 | each.start() |
The Other Jimmy |
32:8ea194f6145b | 37 | for thing in interable : |
The Other Jimmy |
32:8ea194f6145b | 38 | q.put(thing) |
The Other Jimmy |
32:8ea194f6145b | 39 | q.join() |
The Other Jimmy |
32:8ea194f6145b | 40 | |
The Other Jimmy |
32:8ea194f6145b | 41 | class Reader (Thread) : |
The Other Jimmy |
32:8ea194f6145b | 42 | def __init__(self, queue, func) : |
The Other Jimmy |
32:8ea194f6145b | 43 | Thread.__init__(self) |
The Other Jimmy |
32:8ea194f6145b | 44 | self.queue = queue |
The Other Jimmy |
32:8ea194f6145b | 45 | self.func = func |
The Other Jimmy |
32:8ea194f6145b | 46 | def run(self) : |
The Other Jimmy |
32:8ea194f6145b | 47 | while True : |
The Other Jimmy |
32:8ea194f6145b | 48 | url = self.queue.get() |
The Other Jimmy |
32:8ea194f6145b | 49 | self.func(url) |
The Other Jimmy |
32:8ea194f6145b | 50 | self.queue.task_done() |
The Other Jimmy |
32:8ea194f6145b | 51 | |
The Other Jimmy |
32:8ea194f6145b | 52 | |
The Other Jimmy |
32:8ea194f6145b | 53 | class Cache () : |
The Other Jimmy |
32:8ea194f6145b | 54 | """ The Cache object is the only relevant API object at the moment |
The Other Jimmy |
32:8ea194f6145b | 55 | |
The Other Jimmy |
32:8ea194f6145b | 56 | Constructing the Cache object does not imply any caching. |
The Other Jimmy |
32:8ea194f6145b | 57 | A user of the API must explicitly call caching functions. |
The Other Jimmy |
32:8ea194f6145b | 58 | |
The Other Jimmy |
32:8ea194f6145b | 59 | :param silent: A boolean that, when True, significantly reduces the printing of this Object |
The Other Jimmy |
32:8ea194f6145b | 60 | :type silent: bool |
The Other Jimmy |
32:8ea194f6145b | 61 | :param no_timeouts: A boolean that, when True, disables the default connection timeout and low speed timeout for downloading things. |
The Other Jimmy |
32:8ea194f6145b | 62 | :type no_timeouts: bool |
The Other Jimmy |
32:8ea194f6145b | 63 | """ |
The Other Jimmy |
32:8ea194f6145b | 64 | def __init__ (self, silent, no_timeouts) : |
The Other Jimmy |
32:8ea194f6145b | 65 | self.silent = silent |
The Other Jimmy |
32:8ea194f6145b | 66 | self.counter = 0 |
The Other Jimmy |
32:8ea194f6145b | 67 | self.total = 1 |
The Other Jimmy |
32:8ea194f6145b | 68 | self._index = {} |
The Other Jimmy |
32:8ea194f6145b | 69 | self._aliases = {} |
The Other Jimmy |
32:8ea194f6145b | 70 | self.urls = None |
The Other Jimmy |
32:8ea194f6145b | 71 | self.no_timeouts = no_timeouts |
The Other Jimmy |
32:8ea194f6145b | 72 | self.data_path = gettempdir() |
The Other Jimmy |
32:8ea194f6145b | 73 | |
The Other Jimmy |
32:8ea194f6145b | 74 | def display_counter (self, message) : |
The Other Jimmy |
32:8ea194f6145b | 75 | stdout.write("{} {}/{}\r".format(message, self.counter, self.total)) |
The Other Jimmy |
32:8ea194f6145b | 76 | stdout.flush() |
The Other Jimmy |
32:8ea194f6145b | 77 | |
The Other Jimmy |
32:8ea194f6145b | 78 | def cache_file (self, url) : |
The Other Jimmy |
32:8ea194f6145b | 79 | """Low level interface to caching a single file. |
The Other Jimmy |
32:8ea194f6145b | 80 | |
The Other Jimmy |
32:8ea194f6145b | 81 | :param url: The URL to cache. |
The Other Jimmy |
32:8ea194f6145b | 82 | :type url: str |
The Other Jimmy |
32:8ea194f6145b | 83 | :rtype: None |
The Other Jimmy |
32:8ea194f6145b | 84 | """ |
The Other Jimmy |
32:8ea194f6145b | 85 | if not self.silent : print("Caching {}...".format(url)) |
The Other Jimmy |
32:8ea194f6145b | 86 | dest = join(self.data_path, strip_protocol(url)) |
The Other Jimmy |
32:8ea194f6145b | 87 | try : |
The Other Jimmy |
32:8ea194f6145b | 88 | makedirs(dirname(dest)) |
The Other Jimmy |
32:8ea194f6145b | 89 | except OSError as exc : |
The Other Jimmy |
32:8ea194f6145b | 90 | if exc.errno == EEXIST : pass |
The Other Jimmy |
32:8ea194f6145b | 91 | else : raise |
The Other Jimmy |
32:8ea194f6145b | 92 | try: |
The Other Jimmy |
32:8ea194f6145b | 93 | with open(dest, "wb+") as fd : |
The Other Jimmy |
32:8ea194f6145b | 94 | fd.write(urlopen(url).read()) |
The Other Jimmy |
32:8ea194f6145b | 95 | except URLError as e: |
The Other Jimmy |
32:8ea194f6145b | 96 | stderr.write(e.reason) |
The Other Jimmy |
32:8ea194f6145b | 97 | self.counter += 1 |
The Other Jimmy |
32:8ea194f6145b | 98 | self.display_counter("Caching Files") |
The Other Jimmy |
32:8ea194f6145b | 99 | |
The Other Jimmy |
32:8ea194f6145b | 100 | def pdsc_to_pack (self, url) : |
The Other Jimmy |
32:8ea194f6145b | 101 | """Find the URL of the specified pack file described by a PDSC. |
The Other Jimmy |
32:8ea194f6145b | 102 | |
The Other Jimmy |
32:8ea194f6145b | 103 | The PDSC is assumed to be cached and is looked up in the cache by its URL. |
The Other Jimmy |
32:8ea194f6145b | 104 | |
The Other Jimmy |
32:8ea194f6145b | 105 | :param url: The url used to look up the PDSC. |
The Other Jimmy |
32:8ea194f6145b | 106 | :type url: str |
The Other Jimmy |
32:8ea194f6145b | 107 | :return: The url of the PACK file. |
The Other Jimmy |
32:8ea194f6145b | 108 | :rtype: str |
The Other Jimmy |
32:8ea194f6145b | 109 | """ |
The Other Jimmy |
32:8ea194f6145b | 110 | content = self.pdsc_from_cache(url) |
The Other Jimmy |
32:8ea194f6145b | 111 | new_url = content.package.url.get_text() |
The Other Jimmy |
32:8ea194f6145b | 112 | if not new_url.endswith("/") : |
The Other Jimmy |
32:8ea194f6145b | 113 | new_url = new_url + "/" |
The Other Jimmy |
32:8ea194f6145b | 114 | return (new_url + content.package.vendor.get_text() + "." + |
The Other Jimmy |
32:8ea194f6145b | 115 | content.package.find('name').get_text() + "." + |
The Other Jimmy |
32:8ea194f6145b | 116 | largest_version(content) + ".pack") |
The Other Jimmy |
32:8ea194f6145b | 117 | |
The Other Jimmy |
32:8ea194f6145b | 118 | def cache_pdsc_and_pack (self, url) : |
The Other Jimmy |
32:8ea194f6145b | 119 | self.cache_file(url) |
The Other Jimmy |
32:8ea194f6145b | 120 | try : |
The Other Jimmy |
32:8ea194f6145b | 121 | self.cache_file(self.pdsc_to_pack(url)) |
The Other Jimmy |
32:8ea194f6145b | 122 | except AttributeError : |
The Other Jimmy |
32:8ea194f6145b | 123 | stderr.write("[ ERROR ] {} does not appear to be a conforming .pdsc file\n".format(url)) |
The Other Jimmy |
32:8ea194f6145b | 124 | self.counter += 1 |
The Other Jimmy |
32:8ea194f6145b | 125 | |
The Other Jimmy |
32:8ea194f6145b | 126 | def get_urls(self): |
The Other Jimmy |
32:8ea194f6145b | 127 | """Extract the URLs of all know PDSC files. |
The Other Jimmy |
32:8ea194f6145b | 128 | |
The Other Jimmy |
32:8ea194f6145b | 129 | Will pull the index from the internet if it is not cached. |
The Other Jimmy |
32:8ea194f6145b | 130 | |
The Other Jimmy |
32:8ea194f6145b | 131 | :return: A list of all PDSC URLs |
The Other Jimmy |
32:8ea194f6145b | 132 | :rtype: [str] |
The Other Jimmy |
32:8ea194f6145b | 133 | """ |
The Other Jimmy |
32:8ea194f6145b | 134 | if not self.urls : |
The Other Jimmy |
32:8ea194f6145b | 135 | try : root_data = self.pdsc_from_cache(RootPackURL) |
The Other Jimmy |
32:8ea194f6145b | 136 | except IOError : root_data = self.cache_and_parse(RootPackURL) |
The Other Jimmy |
32:8ea194f6145b | 137 | self.urls = ["/".join([pdsc.get('url').strip("/"), |
The Other Jimmy |
32:8ea194f6145b | 138 | pdsc.get('name').strip("/")]) |
The Other Jimmy |
32:8ea194f6145b | 139 | for pdsc in root_data.find_all("pdsc")] |
The Other Jimmy |
32:8ea194f6145b | 140 | return self.urls |
The Other Jimmy |
32:8ea194f6145b | 141 | |
The Other Jimmy |
32:8ea194f6145b | 142 | def _extract_dict(self, device, filename, pack) : |
The Other Jimmy |
32:8ea194f6145b | 143 | to_ret = dict(pdsc_file=filename, pack_file=pack) |
The Other Jimmy |
32:8ea194f6145b | 144 | try : to_ret["memory"] = dict([(m["id"], dict(start=m["start"], |
The Other Jimmy |
32:8ea194f6145b | 145 | size=m["size"])) |
The Other Jimmy |
32:8ea194f6145b | 146 | for m in device("memory")]) |
The Other Jimmy |
32:8ea194f6145b | 147 | except (KeyError, TypeError, IndexError) as e : pass |
The Other Jimmy |
32:8ea194f6145b | 148 | try: algorithms = device("algorithm") |
The Other Jimmy |
32:8ea194f6145b | 149 | except: |
The Other Jimmy |
32:8ea194f6145b | 150 | try: algorithms = device.parent("algorithm") |
The Other Jimmy |
32:8ea194f6145b | 151 | except: pass |
The Other Jimmy |
32:8ea194f6145b | 152 | else: |
The Other Jimmy |
32:8ea194f6145b | 153 | if not algorithms: |
The Other Jimmy |
32:8ea194f6145b | 154 | try: algorithms = device.parent("algorithm") |
The Other Jimmy |
32:8ea194f6145b | 155 | except: pass |
The Other Jimmy |
32:8ea194f6145b | 156 | try : to_ret["algorithm"] = dict([(algo.get("name").replace('\\','/'), |
The Other Jimmy |
32:8ea194f6145b | 157 | dict(start=algo["start"], |
The Other Jimmy |
32:8ea194f6145b | 158 | size=algo["size"], |
The Other Jimmy |
32:8ea194f6145b | 159 | ramstart=algo.get("ramstart",None), |
The Other Jimmy |
32:8ea194f6145b | 160 | ramsize=algo.get("ramsize",None), |
The Other Jimmy |
32:8ea194f6145b | 161 | default=algo.get("default",1))) |
The Other Jimmy |
32:8ea194f6145b | 162 | for algo in algorithms]) |
The Other Jimmy |
32:8ea194f6145b | 163 | except (KeyError, TypeError, IndexError) as e: pass |
The Other Jimmy |
32:8ea194f6145b | 164 | try: to_ret["debug"] = device.parent.parent.debug["svd"] |
The Other Jimmy |
32:8ea194f6145b | 165 | except (KeyError, TypeError, IndexError) as e : pass |
The Other Jimmy |
32:8ea194f6145b | 166 | try: to_ret["debug"] = device.parent.debug["svd"] |
The Other Jimmy |
32:8ea194f6145b | 167 | except (KeyError, TypeError, IndexError) as e : pass |
The Other Jimmy |
32:8ea194f6145b | 168 | try: to_ret["debug"] = device.debug["svd"] |
The Other Jimmy |
32:8ea194f6145b | 169 | except (KeyError, TypeError, IndexError) as e : pass |
The Other Jimmy |
32:8ea194f6145b | 170 | |
The Other Jimmy |
32:8ea194f6145b | 171 | to_ret["compile"] = {} |
The Other Jimmy |
32:8ea194f6145b | 172 | try: compile_l1 = device.parent("compile") |
The Other Jimmy |
32:8ea194f6145b | 173 | except (KeyError, TypeError, IndexError) as e : compile_l1 = [] |
The Other Jimmy |
32:8ea194f6145b | 174 | try: compile_l2 = device.parent.parent("compile") |
The Other Jimmy |
32:8ea194f6145b | 175 | except (KeyError, TypeError, IndexError) as e : compile_l2 = [] |
The Other Jimmy |
32:8ea194f6145b | 176 | compile = compile_l2 + compile_l1 |
The Other Jimmy |
32:8ea194f6145b | 177 | for c in compile: |
The Other Jimmy |
32:8ea194f6145b | 178 | try: to_ret["compile"]["header"] = c["header"] |
The Other Jimmy |
32:8ea194f6145b | 179 | except (KeyError, TypeError, IndexError) as e : pass |
The Other Jimmy |
32:8ea194f6145b | 180 | try: to_ret["compile"]["define"] = c["define"] |
The Other Jimmy |
32:8ea194f6145b | 181 | except (KeyError, TypeError, IndexError) as e : pass |
The Other Jimmy |
32:8ea194f6145b | 182 | |
The Other Jimmy |
32:8ea194f6145b | 183 | try: to_ret["core"] = device.parent.processor['dcore'] |
The Other Jimmy |
32:8ea194f6145b | 184 | except (KeyError, TypeError, IndexError) as e : pass |
The Other Jimmy |
32:8ea194f6145b | 185 | try: to_ret["core"] = device.parent.parent.processor['dcore'] |
The Other Jimmy |
32:8ea194f6145b | 186 | except (KeyError, TypeError, IndexError) as e : pass |
The Other Jimmy |
32:8ea194f6145b | 187 | |
The Other Jimmy |
32:8ea194f6145b | 188 | to_ret["processor"] = {} |
The Other Jimmy |
32:8ea194f6145b | 189 | try: proc_l1 = device("processor") |
The Other Jimmy |
32:8ea194f6145b | 190 | except (KeyError, TypeError, IndexError) as e: proc_l1 = [] |
The Other Jimmy |
32:8ea194f6145b | 191 | try: proc_l2 = device.parent("processor") |
The Other Jimmy |
32:8ea194f6145b | 192 | except (KeyError, TypeError, IndexError) as e: proc_l2 = [] |
The Other Jimmy |
32:8ea194f6145b | 193 | try: proc_l3 = device.parent.parent("processor") |
The Other Jimmy |
32:8ea194f6145b | 194 | except (KeyError, TypeError, IndexError) as e: proc_l3 = [] |
The Other Jimmy |
32:8ea194f6145b | 195 | proc = proc_l3 + proc_l2 + proc_l1 |
The Other Jimmy |
32:8ea194f6145b | 196 | for p in proc: |
The Other Jimmy |
32:8ea194f6145b | 197 | try: to_ret["processor"]["fpu"] = p['dfpu'] |
The Other Jimmy |
32:8ea194f6145b | 198 | except (KeyError, TypeError, IndexError) as e: pass |
The Other Jimmy |
32:8ea194f6145b | 199 | try: to_ret["processor"]["endianness"] = p['dendian'] |
The Other Jimmy |
32:8ea194f6145b | 200 | except (KeyError, TypeError, IndexError) as e: pass |
The Other Jimmy |
32:8ea194f6145b | 201 | try: to_ret["processor"]["clock"] = p['dclock'] |
The Other Jimmy |
32:8ea194f6145b | 202 | except (KeyError, TypeError, IndexError) as e: pass |
The Other Jimmy |
32:8ea194f6145b | 203 | |
The Other Jimmy |
32:8ea194f6145b | 204 | try: to_ret["vendor"] = device.parent['dvendor'] |
The Other Jimmy |
32:8ea194f6145b | 205 | except (KeyError, TypeError, IndexError) as e: pass |
The Other Jimmy |
32:8ea194f6145b | 206 | try: to_ret["vendor"] = device.parent.parent['dvendor'] |
The Other Jimmy |
32:8ea194f6145b | 207 | except (KeyError, TypeError, IndexError) as e: pass |
The Other Jimmy |
32:8ea194f6145b | 208 | |
The Other Jimmy |
32:8ea194f6145b | 209 | if not to_ret["processor"]: |
The Other Jimmy |
32:8ea194f6145b | 210 | del to_ret["processor"] |
The Other Jimmy |
32:8ea194f6145b | 211 | |
The Other Jimmy |
32:8ea194f6145b | 212 | if not to_ret["compile"]: |
The Other Jimmy |
32:8ea194f6145b | 213 | del to_ret["compile"] |
The Other Jimmy |
32:8ea194f6145b | 214 | |
The Other Jimmy |
32:8ea194f6145b | 215 | to_ret['debug-interface'] = [] |
The Other Jimmy |
32:8ea194f6145b | 216 | |
The Other Jimmy |
32:8ea194f6145b | 217 | return to_ret |
The Other Jimmy |
32:8ea194f6145b | 218 | |
The Other Jimmy |
32:8ea194f6145b | 219 | def _generate_index_helper(self, d) : |
The Other Jimmy |
32:8ea194f6145b | 220 | try : |
The Other Jimmy |
32:8ea194f6145b | 221 | pack = self.pdsc_to_pack(d) |
The Other Jimmy |
32:8ea194f6145b | 222 | self._index.update(dict([(dev['dname'], self._extract_dict(dev, d, pack)) for dev in |
The Other Jimmy |
32:8ea194f6145b | 223 | (self.pdsc_from_cache(d)("device"))])) |
The Other Jimmy |
32:8ea194f6145b | 224 | except AttributeError as e : |
The Other Jimmy |
32:8ea194f6145b | 225 | stderr.write("[ ERROR ] file {}\n".format(d)) |
The Other Jimmy |
32:8ea194f6145b | 226 | print(e) |
The Other Jimmy |
32:8ea194f6145b | 227 | self.counter += 1 |
The Other Jimmy |
32:8ea194f6145b | 228 | self.display_counter("Generating Index") |
The Other Jimmy |
32:8ea194f6145b | 229 | |
The Other Jimmy |
32:8ea194f6145b | 230 | def _generate_aliases_helper(self, d) : |
The Other Jimmy |
32:8ea194f6145b | 231 | try : |
The Other Jimmy |
32:8ea194f6145b | 232 | mydict = [] |
The Other Jimmy |
32:8ea194f6145b | 233 | for dev in self.pdsc_from_cache(d)("board"): |
The Other Jimmy |
32:8ea194f6145b | 234 | try : |
The Other Jimmy |
32:8ea194f6145b | 235 | mydict.append((dev['name'], dev.mounteddevice['dname'])) |
The Other Jimmy |
32:8ea194f6145b | 236 | except (KeyError, TypeError, IndexError) as e: |
The Other Jimmy |
32:8ea194f6145b | 237 | pass |
The Other Jimmy |
32:8ea194f6145b | 238 | self._aliases.update(dict(mydict)) |
The Other Jimmy |
32:8ea194f6145b | 239 | except (AttributeError, TypeError) as e : |
The Other Jimmy |
32:8ea194f6145b | 240 | pass |
The Other Jimmy |
32:8ea194f6145b | 241 | self.counter += 1 |
The Other Jimmy |
32:8ea194f6145b | 242 | self.display_counter("Scanning for Aliases") |
The Other Jimmy |
32:8ea194f6145b | 243 | |
The Other Jimmy |
32:8ea194f6145b | 244 | def get_flash_algorthim_binary(self, device_name) : |
The Other Jimmy |
32:8ea194f6145b | 245 | """Retrieve the flash algorithm file for a particular part. |
The Other Jimmy |
32:8ea194f6145b | 246 | |
The Other Jimmy |
32:8ea194f6145b | 247 | Assumes that both the PDSC and the PACK file associated with that part are in the cache. |
The Other Jimmy |
32:8ea194f6145b | 248 | |
The Other Jimmy |
32:8ea194f6145b | 249 | :param device_name: The exact name of a device |
The Other Jimmy |
32:8ea194f6145b | 250 | :type device_name: str |
The Other Jimmy |
32:8ea194f6145b | 251 | :return: A file-like object that, when read, is the ELF file that describes the flashing algorithm |
The Other Jimmy |
32:8ea194f6145b | 252 | :rtype: ZipExtFile |
The Other Jimmy |
32:8ea194f6145b | 253 | """ |
The Other Jimmy |
32:8ea194f6145b | 254 | pack = self.pack_from_cache(self.index[device_name]) |
The Other Jimmy |
32:8ea194f6145b | 255 | return pack.open(device['algorithm']['file']) |
The Other Jimmy |
32:8ea194f6145b | 256 | |
The Other Jimmy |
32:8ea194f6145b | 257 | def get_svd_file(self, device_name) : |
The Other Jimmy |
32:8ea194f6145b | 258 | """Retrieve the flash algorithm file for a particular part. |
The Other Jimmy |
32:8ea194f6145b | 259 | |
The Other Jimmy |
32:8ea194f6145b | 260 | Assumes that both the PDSC and the PACK file associated with that part are in the cache. |
The Other Jimmy |
32:8ea194f6145b | 261 | |
The Other Jimmy |
32:8ea194f6145b | 262 | :param device_name: The exact name of a device |
The Other Jimmy |
32:8ea194f6145b | 263 | :type device_name: str |
The Other Jimmy |
32:8ea194f6145b | 264 | :return: A file-like object that, when read, is the ELF file that describes the flashing algorithm |
The Other Jimmy |
32:8ea194f6145b | 265 | :rtype: ZipExtFile |
The Other Jimmy |
32:8ea194f6145b | 266 | """ |
The Other Jimmy |
32:8ea194f6145b | 267 | pack = self.pack_from_cache(self.index[device_name]) |
The Other Jimmy |
32:8ea194f6145b | 268 | return pack.open(device['debug']) |
The Other Jimmy |
32:8ea194f6145b | 269 | |
The Other Jimmy |
32:8ea194f6145b | 270 | def generate_index(self) : |
The Other Jimmy |
32:8ea194f6145b | 271 | self._index = {} |
The Other Jimmy |
32:8ea194f6145b | 272 | self.counter = 0 |
The Other Jimmy |
32:8ea194f6145b | 273 | do_queue(Reader, self._generate_index_helper, self.get_urls()) |
The Other Jimmy |
32:8ea194f6145b | 274 | with open(LocalPackIndex, "wb+") as out: |
The Other Jimmy |
32:8ea194f6145b | 275 | self._index["version"] = "0.1.0" |
The Other Jimmy |
32:8ea194f6145b | 276 | dump(self._index, out) |
The Other Jimmy |
32:8ea194f6145b | 277 | stdout.write("\n") |
The Other Jimmy |
32:8ea194f6145b | 278 | |
The Other Jimmy |
32:8ea194f6145b | 279 | def generate_aliases(self) : |
The Other Jimmy |
32:8ea194f6145b | 280 | self._aliases = {} |
The Other Jimmy |
32:8ea194f6145b | 281 | self.counter = 0 |
The Other Jimmy |
32:8ea194f6145b | 282 | do_queue(Reader, self._generate_aliases_helper, self.get_urls()) |
The Other Jimmy |
32:8ea194f6145b | 283 | with open(LocalPackAliases, "wb+") as out: |
The Other Jimmy |
32:8ea194f6145b | 284 | dump(self._aliases, out) |
The Other Jimmy |
32:8ea194f6145b | 285 | stdout.write("\n") |
The Other Jimmy |
32:8ea194f6145b | 286 | |
The Other Jimmy |
32:8ea194f6145b | 287 | def find_device(self, match) : |
The Other Jimmy |
32:8ea194f6145b | 288 | choices = process.extract(match, self.index.keys(), limit=len(self.index)) |
The Other Jimmy |
32:8ea194f6145b | 289 | choices = sorted([(v, k) for k, v in choices], reverse=True) |
The Other Jimmy |
32:8ea194f6145b | 290 | if choices : choices = list(takewhile(lambda t: t[0] == choices[0][0], choices)) |
The Other Jimmy |
32:8ea194f6145b | 291 | return [(v, self.index[v]) for k,v in choices] |
The Other Jimmy |
32:8ea194f6145b | 292 | |
The Other Jimmy |
32:8ea194f6145b | 293 | def dump_index_to_file(self, file) : |
The Other Jimmy |
32:8ea194f6145b | 294 | with open(file, "wb+") as out: |
The Other Jimmy |
32:8ea194f6145b | 295 | dump(self.index, out) |
The Other Jimmy |
32:8ea194f6145b | 296 | |
The Other Jimmy |
32:8ea194f6145b | 297 | @property |
The Other Jimmy |
32:8ea194f6145b | 298 | def index(self) : |
The Other Jimmy |
32:8ea194f6145b | 299 | """An index of most of the important data in all cached PDSC files. |
The Other Jimmy |
32:8ea194f6145b | 300 | |
The Other Jimmy |
32:8ea194f6145b | 301 | :Example: |
The Other Jimmy |
32:8ea194f6145b | 302 | |
The Other Jimmy |
32:8ea194f6145b | 303 | >>> from ArmPackManager import Cache |
The Other Jimmy |
32:8ea194f6145b | 304 | >>> a = Cache() |
The Other Jimmy |
32:8ea194f6145b | 305 | >>> a.index["LPC1768"] |
The Other Jimmy |
32:8ea194f6145b | 306 | {u'algorithm': {u'RAMsize': u'0x0FE0', |
The Other Jimmy |
32:8ea194f6145b | 307 | u'RAMstart': u'0x10000000', |
The Other Jimmy |
32:8ea194f6145b | 308 | u'name': u'Flash/LPC_IAP_512.FLM', |
The Other Jimmy |
32:8ea194f6145b | 309 | u'size': u'0x80000', |
The Other Jimmy |
32:8ea194f6145b | 310 | u'start': u'0x00000000'}, |
The Other Jimmy |
32:8ea194f6145b | 311 | u'compile': [u'Device/Include/LPC17xx.h', u'LPC175x_6x'], |
The Other Jimmy |
32:8ea194f6145b | 312 | u'debug': u'SVD/LPC176x5x.svd', |
The Other Jimmy |
32:8ea194f6145b | 313 | u'pdsc_file': u'http://www.keil.com/pack/Keil.LPC1700_DFP.pdsc', |
The Other Jimmy |
32:8ea194f6145b | 314 | u'memory': {u'IRAM1': {u'size': u'0x8000', u'start': u'0x10000000'}, |
The Other Jimmy |
32:8ea194f6145b | 315 | u'IRAM2': {u'size': u'0x8000', u'start': u'0x2007C000'}, |
The Other Jimmy |
32:8ea194f6145b | 316 | u'IROM1': {u'size': u'0x80000', u'start': u'0x00000000'}}} |
The Other Jimmy |
32:8ea194f6145b | 317 | |
The Other Jimmy |
32:8ea194f6145b | 318 | |
The Other Jimmy |
32:8ea194f6145b | 319 | """ |
The Other Jimmy |
32:8ea194f6145b | 320 | if not self._index : |
The Other Jimmy |
32:8ea194f6145b | 321 | with open(LocalPackIndex) as i : |
The Other Jimmy |
32:8ea194f6145b | 322 | self._index = load(i) |
The Other Jimmy |
32:8ea194f6145b | 323 | return self._index |
The Other Jimmy |
32:8ea194f6145b | 324 | @property |
The Other Jimmy |
32:8ea194f6145b | 325 | def aliases(self) : |
The Other Jimmy |
32:8ea194f6145b | 326 | """An index of most of the important data in all cached PDSC files. |
The Other Jimmy |
32:8ea194f6145b | 327 | |
The Other Jimmy |
32:8ea194f6145b | 328 | :Example: |
The Other Jimmy |
32:8ea194f6145b | 329 | |
The Other Jimmy |
32:8ea194f6145b | 330 | >>> from ArmPackManager import Cache |
The Other Jimmy |
32:8ea194f6145b | 331 | >>> a = Cache() |
The Other Jimmy |
32:8ea194f6145b | 332 | >>> a.index["LPC1768"] |
The Other Jimmy |
32:8ea194f6145b | 333 | {u'algorithm': {u'RAMsize': u'0x0FE0', |
The Other Jimmy |
32:8ea194f6145b | 334 | u'RAMstart': u'0x10000000', |
The Other Jimmy |
32:8ea194f6145b | 335 | u'name': u'Flash/LPC_IAP_512.FLM', |
The Other Jimmy |
32:8ea194f6145b | 336 | u'size': u'0x80000', |
The Other Jimmy |
32:8ea194f6145b | 337 | u'start': u'0x00000000'}, |
The Other Jimmy |
32:8ea194f6145b | 338 | u'compile': [u'Device/Include/LPC17xx.h', u'LPC175x_6x'], |
The Other Jimmy |
32:8ea194f6145b | 339 | u'debug': u'SVD/LPC176x5x.svd', |
The Other Jimmy |
32:8ea194f6145b | 340 | u'pdsc_file': u'http://www.keil.com/pack/Keil.LPC1700_DFP.pdsc', |
The Other Jimmy |
32:8ea194f6145b | 341 | u'memory': {u'IRAM1': {u'size': u'0x8000', u'start': u'0x10000000'}, |
The Other Jimmy |
32:8ea194f6145b | 342 | u'IRAM2': {u'size': u'0x8000', u'start': u'0x2007C000'}, |
The Other Jimmy |
32:8ea194f6145b | 343 | u'IROM1': {u'size': u'0x80000', u'start': u'0x00000000'}}} |
The Other Jimmy |
32:8ea194f6145b | 344 | |
The Other Jimmy |
32:8ea194f6145b | 345 | |
The Other Jimmy |
32:8ea194f6145b | 346 | """ |
The Other Jimmy |
32:8ea194f6145b | 347 | if not self._aliases : |
The Other Jimmy |
32:8ea194f6145b | 348 | with open(join(self.data_path, "aliases.json")) as i : |
The Other Jimmy |
32:8ea194f6145b | 349 | self._aliases = load(i) |
The Other Jimmy |
32:8ea194f6145b | 350 | return self._aliases |
The Other Jimmy |
32:8ea194f6145b | 351 | |
The Other Jimmy |
32:8ea194f6145b | 352 | def cache_everything(self) : |
The Other Jimmy |
32:8ea194f6145b | 353 | """Cache every PACK and PDSC file known. |
The Other Jimmy |
32:8ea194f6145b | 354 | |
The Other Jimmy |
32:8ea194f6145b | 355 | Generates an index afterwards. |
The Other Jimmy |
32:8ea194f6145b | 356 | |
The Other Jimmy |
32:8ea194f6145b | 357 | .. note:: This process may use 4GB of drive space and take upwards of 10 minutes to complete. |
The Other Jimmy |
32:8ea194f6145b | 358 | """ |
The Other Jimmy |
32:8ea194f6145b | 359 | self.cache_pack_list(self.get_urls()) |
The Other Jimmy |
32:8ea194f6145b | 360 | self.generate_index() |
The Other Jimmy |
32:8ea194f6145b | 361 | self.generate_aliases() |
The Other Jimmy |
32:8ea194f6145b | 362 | |
The Other Jimmy |
32:8ea194f6145b | 363 | def cache_descriptors(self) : |
The Other Jimmy |
32:8ea194f6145b | 364 | """Cache every PDSC file known. |
The Other Jimmy |
32:8ea194f6145b | 365 | |
The Other Jimmy |
32:8ea194f6145b | 366 | Generates an index afterwards. |
The Other Jimmy |
32:8ea194f6145b | 367 | |
The Other Jimmy |
32:8ea194f6145b | 368 | .. note:: This process may use 11MB of drive space and take upwards of 1 minute. |
The Other Jimmy |
32:8ea194f6145b | 369 | """ |
The Other Jimmy |
32:8ea194f6145b | 370 | self.cache_descriptor_list(self.get_urls()) |
The Other Jimmy |
32:8ea194f6145b | 371 | self.generate_index() |
The Other Jimmy |
32:8ea194f6145b | 372 | self.generate_aliases() |
The Other Jimmy |
32:8ea194f6145b | 373 | |
The Other Jimmy |
32:8ea194f6145b | 374 | def cache_descriptor_list(self, list) : |
The Other Jimmy |
32:8ea194f6145b | 375 | """Cache a list of PDSC files. |
The Other Jimmy |
32:8ea194f6145b | 376 | |
The Other Jimmy |
32:8ea194f6145b | 377 | :param list: URLs of PDSC files to cache. |
The Other Jimmy |
32:8ea194f6145b | 378 | :type list: [str] |
The Other Jimmy |
32:8ea194f6145b | 379 | """ |
The Other Jimmy |
32:8ea194f6145b | 380 | self.total = len(list) |
The Other Jimmy |
32:8ea194f6145b | 381 | self.display_counter("Caching Files") |
The Other Jimmy |
32:8ea194f6145b | 382 | do_queue(Reader, self.cache_file, list) |
The Other Jimmy |
32:8ea194f6145b | 383 | stdout.write("\n") |
The Other Jimmy |
32:8ea194f6145b | 384 | |
The Other Jimmy |
32:8ea194f6145b | 385 | def cache_pack_list(self, list) : |
The Other Jimmy |
32:8ea194f6145b | 386 | """Cache a list of PACK files, referenced by their PDSC URL |
The Other Jimmy |
32:8ea194f6145b | 387 | |
The Other Jimmy |
32:8ea194f6145b | 388 | :param list: URLs of PDSC files to cache. |
The Other Jimmy |
32:8ea194f6145b | 389 | :type list: [str] |
The Other Jimmy |
32:8ea194f6145b | 390 | """ |
The Other Jimmy |
32:8ea194f6145b | 391 | self.total = len(list) * 2 |
The Other Jimmy |
32:8ea194f6145b | 392 | self.display_counter("Caching Files") |
The Other Jimmy |
32:8ea194f6145b | 393 | do_queue(Reader, self.cache_pdsc_and_pack, list) |
The Other Jimmy |
32:8ea194f6145b | 394 | stdout.write("\n") |
The Other Jimmy |
32:8ea194f6145b | 395 | |
The Other Jimmy |
32:8ea194f6145b | 396 | def pdsc_from_cache(self, url) : |
The Other Jimmy |
32:8ea194f6145b | 397 | """Low level inteface for extracting a PDSC file from the cache. |
The Other Jimmy |
32:8ea194f6145b | 398 | |
The Other Jimmy |
32:8ea194f6145b | 399 | Assumes that the file specified is a PDSC file and is in the cache. |
The Other Jimmy |
32:8ea194f6145b | 400 | |
The Other Jimmy |
32:8ea194f6145b | 401 | :param url: The URL of a PDSC file. |
The Other Jimmy |
32:8ea194f6145b | 402 | :type url: str |
The Other Jimmy |
32:8ea194f6145b | 403 | :return: A parsed representation of the PDSC file. |
The Other Jimmy |
32:8ea194f6145b | 404 | :rtype: BeautifulSoup |
The Other Jimmy |
32:8ea194f6145b | 405 | """ |
The Other Jimmy |
32:8ea194f6145b | 406 | dest = join(self.data_path, strip_protocol(url)) |
The Other Jimmy |
32:8ea194f6145b | 407 | with open(dest, "r") as fd : |
The Other Jimmy |
32:8ea194f6145b | 408 | return BeautifulSoup(fd, "html.parser") |
The Other Jimmy |
32:8ea194f6145b | 409 | |
The Other Jimmy |
32:8ea194f6145b | 410 | def pack_from_cache(self, url) : |
The Other Jimmy |
32:8ea194f6145b | 411 | """Low level inteface for extracting a PACK file from the cache. |
The Other Jimmy |
32:8ea194f6145b | 412 | |
The Other Jimmy |
32:8ea194f6145b | 413 | Assumes that the file specified is a PACK file and is in the cache. |
The Other Jimmy |
32:8ea194f6145b | 414 | |
The Other Jimmy |
32:8ea194f6145b | 415 | :param url: The URL of a PACK file. |
The Other Jimmy |
32:8ea194f6145b | 416 | :type url: str |
The Other Jimmy |
32:8ea194f6145b | 417 | :return: A parsed representation of the PACK file. |
The Other Jimmy |
32:8ea194f6145b | 418 | :rtype: ZipFile |
The Other Jimmy |
32:8ea194f6145b | 419 | """ |
The Other Jimmy |
32:8ea194f6145b | 420 | return ZipFile(join(self.data_path, |
The Other Jimmy |
32:8ea194f6145b | 421 | strip_protocol(device['pack_file']))) |
The Other Jimmy |
32:8ea194f6145b | 422 | |
The Other Jimmy |
32:8ea194f6145b | 423 | def gen_dict_from_cache() : |
The Other Jimmy |
32:8ea194f6145b | 424 | pdsc_files = pdsc_from_cache(RootPackUrl) |
The Other Jimmy |
32:8ea194f6145b | 425 | |
The Other Jimmy |
32:8ea194f6145b | 426 | def cache_and_parse(self, url) : |
The Other Jimmy |
32:8ea194f6145b | 427 | """A low level shortcut that Caches and Parses a PDSC file. |
The Other Jimmy |
32:8ea194f6145b | 428 | |
The Other Jimmy |
32:8ea194f6145b | 429 | :param url: The URL of the PDSC file. |
The Other Jimmy |
32:8ea194f6145b | 430 | :type url: str |
The Other Jimmy |
32:8ea194f6145b | 431 | :return: A parsed representation of the PDSC file. |
The Other Jimmy |
32:8ea194f6145b | 432 | :rtype: BeautifulSoup |
The Other Jimmy |
32:8ea194f6145b | 433 | """ |
The Other Jimmy |
32:8ea194f6145b | 434 | self.cache_file(url) |
The Other Jimmy |
32:8ea194f6145b | 435 | return self.pdsc_from_cache(url) |
The Other Jimmy |
32:8ea194f6145b | 436 |