Returns a (possibly cached) factory for the converted result of entity.
(entity, program_ctx, free_nonglobal_var_names)
| 208 | |
| 209 | |
| 210 | def _convert_with_cache(entity, program_ctx, free_nonglobal_var_names): |
| 211 | """Returns a (possibly cached) factory for the converted result of entity.""" |
| 212 | # The cache key is the entity's code object if it defined one, otherwise it's |
| 213 | # the entity itself. Keying by the code object allows caching of functions |
| 214 | # that are dynamically created e.g. in a loop. |
| 215 | if hasattr(entity, '__code__'): |
| 216 | key = entity.__code__ |
| 217 | else: |
| 218 | key = entity |
| 219 | |
| 220 | # The cache subkey encompases any conversion options on which the generated |
| 221 | # code may depend. |
| 222 | # The cached factory includes the necessary definitions to distinguish |
| 223 | # between the global and non-global free variables. For this reason, the |
| 224 | # cache subkey includes the names of the free non-globals. |
| 225 | subkey = (program_ctx.options, frozenset(free_nonglobal_var_names)) |
| 226 | |
| 227 | with _CACHE_LOCK: |
| 228 | # The cache values are _ConvertedEntityFactoryInfo objects. |
| 229 | if _CACHE.has(key, subkey): |
| 230 | # TODO(mdan): Check whether the module is still loaded. |
| 231 | converted_entity_info = _CACHE[key][subkey] |
| 232 | logging.log(3, 'Cache hit for entity %s key %s subkey %s: %s', entity, |
| 233 | key, subkey, converted_entity_info) |
| 234 | return converted_entity_info |
| 235 | |
| 236 | logging.log(1, 'Entity %s is not cached for key %s subkey %s', entity, key, |
| 237 | subkey) |
| 238 | |
| 239 | nodes, converted_name, entity_info = convert_entity_to_ast( |
| 240 | entity, program_ctx) |
| 241 | |
| 242 | namer = naming.Namer(entity_info.namespace) |
| 243 | factory_factory_name = namer.new_symbol('create_converted_entity_factory', |
| 244 | ()) |
| 245 | factory_name = namer.new_symbol('create_converted_entity', ()) |
| 246 | nodes = _wrap_into_dynamic_factory(nodes, converted_name, |
| 247 | factory_factory_name, factory_name, |
| 248 | free_nonglobal_var_names, |
| 249 | entity_info.future_features) |
| 250 | |
| 251 | module, _, source_map = compiler.ast_to_object( |
| 252 | nodes, include_source_map=True) |
| 253 | module_name = module.__name__ |
| 254 | |
| 255 | converted_entity_info = _ConvertedEntityFactoryInfo( |
| 256 | module_name=module_name, |
| 257 | converted_name=converted_name, |
| 258 | factory_factory_name=factory_factory_name, |
| 259 | source_map=source_map) |
| 260 | _CACHE[key][subkey] = converted_entity_info |
| 261 | return converted_entity_info |
| 262 | |
| 263 | |
| 264 | def _instantiate(entity, converted_entity_info, free_nonglobal_var_names): |
no test coverage detected