code: def _find_syntax_node_name(evaluator, access_handle):
      # TODO accessing this is bad, but it probably doesn't matter that much,
      # because we're working with interpreteters only here.
      python_object = access_handle.access._obj
      try:
          python_object = _get_object_to_check(python_object)
          path = inspect.getsourcefile(python_object)
      except TypeError:
          # The type might not be known (e.g. class_with_dict.__weakref__)
          return None
      if path is None or not os.path.exists(path):
          # The path might not exist or be e.g. <stdin>.
          return None
  
      module_node = _load_module(evaluator, path)
  
      if inspect.ismodule(python_object):
          # We don't need to check names for modules, because there's not really
          # a way to write a module in a module in Python (and also __name__ can
          # be something like ``email.utils``).
          code_lines = get_cached_code_lines(evaluator.grammar, path)
          return module_node, module_node, path, code_lines
  
      try:
          name_str = python_object.__name__
      except AttributeError:
          # Stuff like python_function.__code__.
          return None
  
      if name_str == "<lambda>":
          return None  # It's too hard to find lambdas.
  
      # Doesn't always work (e.g. os.stat_result)
      names = module_node.get_used_names().get(name_str, [])
      names = [n for n in names if n.is_definition()]
      if not names:
          return None
  
      try:
          code = python_object.__code__
          # By using the line number of a code object we make the lookup in a
          # file pretty easy. There's still a possibility of people defining
          # stuff like ``a = 3; foo(a); a = 4`` on the same line, but if people
          # do so we just don't care.
          line_nr = code.co_firstlineno
      except AttributeError:
          pass
      else:
          line_names = [
              name for name in names if name.start_pos[0] == line_nr
          ]
          # There's a chance that the object is not available anymore, because
          # the code has changed in the background.
          if line_names:
              names = line_names
  
      code_lines = get_cached_code_lines(evaluator.grammar, path)
      # It's really hard to actually get the right definition, here as a last
      # resort we just return the last one. This chance might lead to odd
      # completions at some points but will lead to mostly correct type
      # inference, because people tend to define a public name in a module only
      # once.
      return module_node, names[-1].parent, path, code_lines
  
imports: import inspect
  import os
  from jedi.parser_utils import get_cached_code_lines
  from jedi import settings
  from jedi.evaluate import compiled
  from jedi.cache import underscore_memoization
  from jedi.evaluate import imports
  from jedi.evaluate.base_context import Context, ContextSet
  from jedi.evaluate.context import ModuleContext
  from jedi.evaluate.cache import evaluator_function_cache
  from jedi.evaluate.compiled.getattr_static import getattr_static
  from jedi.evaluate.compiled.access import compiled_objects_cache
  from jedi.evaluate.compiled.context import create_cached_compiled_object
label_desc: Use image node_id 3 for calling a global function with example usage: _find_syntax_node_name(evaluator, access_handle) and returns: module_node,  names,  path,  code_lines, None, module_node,  module_node,  path,  code_lines, None, None, None, None