Ejemplo n.º 1
0
def function_to_graph(f, conversion_map, arg_values, arg_types,
                      owner_type=None):
  """Specialization of `entity_to_graph` for callable functions."""
  node, source = parser.parse_entity(f)
  node = node.body[0]

  namespace = inspect_utils.getnamespace(f)
  _add_self_references(namespace, conversion_map.api_module)
  namer = conversion_map.new_namer(namespace)

  ctx = context.EntityContext(
      namer=namer,
      source_code=source,
      source_file='<fragment>',
      namespace=namespace,
      arg_values=arg_values,
      arg_types=arg_types,
      owner_type=owner_type,
      recursive=conversion_map.recursive,
      type_annotation_func=type_hints.set_element_type)
  node, deps = node_to_graph(node, ctx, conversion_map.nocompile_decorators)

  # TODO(mdan): This somewhat duplicates the call rename logic in call_treest.py
  new_name, did_rename = namer.compiled_function_name(f.__name__, f, owner_type)
  if not did_rename:
    new_name = f.__name__
    if node.name != f.__name__:
      raise NotImplementedError('Strange corner case. Send us offending code!')

  node.name = new_name
  conversion_map.update_name_map(namer)
  # TODO(mdan): Use this at compilation.
  conversion_map.additional_imports.update(deps)

  return node, new_name, namespace
Ejemplo n.º 2
0
 def parse_and_analyze(self,
                       test_fn,
                       namespace,
                       namer=None,
                       arg_types=None,
                       include_type_analysis=True,
                       owner_type=None,
                       recursive=True):
     node, source = parser.parse_entity(test_fn)
     ctx = context.EntityContext(
         namer=namer or FakeNamer(),
         source_code=source,
         source_file=None,
         namespace=namespace,
         arg_values=None,
         arg_types=arg_types,
         owner_type=owner_type,
         recursive=recursive,
         type_annotation_func=utils.set_element_type)
     node = qual_names.resolve(node)
     node = activity.resolve(node, ctx)
     node = live_values.resolve(node, ctx, {})
     if include_type_analysis:
         node = type_info.resolve(node, ctx)
         node = live_values.resolve(node, ctx, {})
     self.ctx = ctx
     return node
Ejemplo n.º 3
0
 def _context_for_nodetesting(self):
     return context.EntityContext(namer=None,
                                  source_code=None,
                                  source_file=None,
                                  namespace=None,
                                  arg_values=None,
                                  arg_types=None,
                                  owner_type=None,
                                  recursive=False)
Ejemplo n.º 4
0
 def _parse_and_analyze(self, test_fn, namespace, arg_types=None):
     arg_types = arg_types or {}
     node, source = parser.parse_entity(test_fn)
     ctx = context.EntityContext(namer=None,
                                 source_code=source,
                                 source_file=None,
                                 namespace=namespace,
                                 arg_values=None,
                                 arg_types=arg_types,
                                 owner_type=None,
                                 recursive=True)
     node = qual_names.resolve(node)
     return node, ctx
    def test_entity_scope_tracking(self):
        class TestTransformer(transformer.Base):

            # The choice of note to assign to is arbitrary. Using Assign because it's
            # easy to find in the tree.
            def visit_Assign(self, node):
                anno.setanno(node, 'enclosing_entities',
                             self.enclosing_entities)
                return self.generic_visit(node)

            # This will show up in the lambda function.
            def visit_BinOp(self, node):
                anno.setanno(node, 'enclosing_entities',
                             self.enclosing_entities)
                return self.generic_visit(node)

        tr = TestTransformer(
            context.EntityContext(namer=None,
                                  source_code=None,
                                  source_file=None,
                                  namespace=None,
                                  arg_values=None,
                                  arg_types=None,
                                  owner_type=None,
                                  recursive=False))

        def test_function():
            a = 0

            class TestClass(object):
                def test_method(self):
                    b = 0

                    def inner_function(x):
                        c = 0
                        d = lambda y: (x + y)
                        return c, d

                    return b, inner_function

            return a, TestClass

        node, _ = parser.parse_entity(test_function)
        node = tr.visit(node)

        test_function_node = node.body[0]
        test_class = test_function_node.body[1]
        test_method = test_class.body[0]
        inner_function = test_method.body[1]
        lambda_node = inner_function.body[1].value

        a = test_function_node.body[0]
        b = test_method.body[0]
        c = inner_function.body[0]
        lambda_expr = lambda_node.body

        self.assertEqual((test_function_node, ),
                         anno.getanno(a, 'enclosing_entities'))
        self.assertEqual((test_function_node, test_class, test_method),
                         anno.getanno(b, 'enclosing_entities'))
        self.assertEqual(
            (test_function_node, test_class, test_method, inner_function),
            anno.getanno(c, 'enclosing_entities'))
        self.assertEqual((test_function_node, test_class, test_method,
                          inner_function, lambda_node),
                         anno.getanno(lambda_expr, 'enclosing_entities'))