| 274 | |
| 275 | |
| 276 | class Dispatcher(DispatcherInterface): |
| 277 | _context_cache = dict() |
| 278 | |
| 279 | def __init__(self, context_code=""): |
| 280 | self._parser_cache = dict() |
| 281 | context_ast = getattr(self._context_cache, context_code, None) |
| 282 | if context_ast is None: |
| 283 | context_ast = self._context_cache[context_code] = self.parse(context_code)[ |
| 284 | 1 |
| 285 | ] |
| 286 | self.context_mappings = self._getx(FunctionParser, "mappings", context_ast) |
| 287 | |
| 288 | def find(self, name, node, *args, **kwargs): |
| 289 | return getattr(self, name)(node) |
| 290 | |
| 291 | def parse(self, code): |
| 292 | res = asttokens.ASTTokens(code, parse=True) |
| 293 | return res, res.tree |
| 294 | |
| 295 | # add methods for retrieving parser outputs -------------------------- |
| 296 | def _getx(self, Parser, ext_attr, tree): |
| 297 | """getter for Parser outputs""" |
| 298 | # return cached output if possible |
| 299 | cache_key = Parser.__name__ + str(hash(tree)) |
| 300 | if self._parser_cache.get(cache_key): |
| 301 | p = self._parser_cache[cache_key] |
| 302 | else: |
| 303 | # otherwise, run parser over tree |
| 304 | p = Parser() |
| 305 | # set mappings for parsers that inspect attribute access |
| 306 | if ext_attr != "mappings" and Parser in [ |
| 307 | FunctionParser, |
| 308 | ObjectAccessParser, |
| 309 | ]: |
| 310 | p.mappings = self.context_mappings.copy() |
| 311 | # run parser |
| 312 | p.visit(tree) |
| 313 | # cache |
| 314 | self._parser_cache[cache_key] = p |
| 315 | return getattr(p, ext_attr) |
| 316 | |
| 317 | |
| 318 | # put a function on the dispatcher |
no outgoing calls