# Path: sphinx_gallery/backreferences.py
# def identify_names(script_blocks, global_variables=None, node=''):
#     """Build a codeobj summary by identifying and resolving used names."""
#     if node == '':  # mostly convenience for testing functions
#         c = '\n'.join(txt for kind, txt, _ in script_blocks if kind == 'code')
#         node = ast.parse(c)
#     # Get matches from the code (AST, implicit matches)
#     finder = NameFinder(global_variables)
#     if node is not None:
#         finder.visit(node)
#     names = list(finder.get_mapping())
#     # Get matches from docstring inspection (explicit matches)
#     text = '\n'.join(txt for kind, txt, _ in script_blocks if kind == 'text')
#     names.extend((x, x, False, False, True) for x in re.findall(_regex, text))
#     example_code_obj = collections.OrderedDict()  # order is important
#     # Make a list of all guesses, in `_embed_code_links` we will break
#     # when we find a match
#     for name, full_name, class_like, is_class, is_explicit in names:
#         if name not in example_code_obj:
#             example_code_obj[name] = list()
#         # name is as written in file (e.g. np.asarray)
#         # full_name includes resolved import path (e.g. numpy.asarray)
#         splitted = full_name.rsplit('.', 1 + class_like)
#         if len(splitted) == 1:
#             splitted = ('builtins', splitted[0])
#         elif len(splitted) == 3:  # class-like
#             assert class_like
#             splitted = (splitted[0], '.'.join(splitted[1:]))
#         else:
#             assert not class_like
# 
#         module, attribute = splitted
# 
#         # get shortened module name
#         module_short = _get_short_module_name(module, attribute)
#         cobj = {'name': attribute, 'module': module,
#                 'module_short': module_short or module, 'is_class': is_class,
#                 'is_explicit': is_explicit}
#         example_code_obj[name].append(cobj)
#     return example_code_obj
# 
# Path: sphinx_gallery/py_source_parser.py
# def split_code_and_text_blocks(source_file, return_node=False):
#     """Return list with source file separated into code and text blocks.
# 
#     Parameters
#     ----------
#     source_file : str
#         Path to the source file.
#     return_node : bool
#         If True, return the ast node.
# 
#     Returns
#     -------
#     file_conf : dict
#         File-specific settings given in source file comments as:
#         ``# sphinx_gallery_<name> = <value>``
#     blocks : list
#         (label, content, line_number)
#         List where each element is a tuple with the label ('text' or 'code'),
#         the corresponding content string of block and the leading line number
#     node : ast Node
#         The parsed node.
#     """
#     docstring, rest_of_content, lineno, node = _get_docstring_and_rest(
#         source_file)
#     blocks = [('text', docstring, 1)]
# 
#     file_conf = extract_file_config(rest_of_content)
# 
#     pattern = re.compile(
#         r'(?P<header_line>^#{20,}.*|^# ?%%.*)\s(?P<text_content>(?:^#.*\s?)*)',
#         flags=re.M)
#     sub_pat = re.compile('^#', flags=re.M)
# 
#     pos_so_far = 0
#     for match in re.finditer(pattern, rest_of_content):
#         code_block_content = rest_of_content[pos_so_far:match.start()]
#         if code_block_content.strip():
#             blocks.append(('code', code_block_content, lineno))
#         lineno += code_block_content.count('\n')
# 
#         lineno += 1  # Ignored header line of hashes.
#         text_content = match.group('text_content')
#         text_block_content = dedent(re.sub(sub_pat, '', text_content)).lstrip()
#         if text_block_content.strip():
#             blocks.append(('text', text_block_content, lineno))
#         lineno += text_content.count('\n')
# 
#         pos_so_far = match.end()
# 
#     remaining_content = rest_of_content[pos_so_far:]
#     if remaining_content.strip():
#         blocks.append(('code', remaining_content, lineno))
# 
#     out = (file_conf, blocks)
#     if return_node:
#         out += (node,)
#     return out


import os.path as op  # noqa, analysis:ignore
import matplotlib.pyplot as plt
import sphinx_gallery
from sphinx_gallery.backreferences import identify_names
from sphinx_gallery.py_source_parser import split_code_and_text_blocks
This demonstrates how Sphinx-Gallery identifies when

1. a function/method/attribute/object is used or class instantiated in a
   code block
2. a function/method/attribute/object/class is referred to using sphinx markup
   in a text block.

Sphinx-Gallery examines both the executed code itself, as well as the
text blocks (such as this one, or the one below) for these references and
identifies the module they belong to. This means that by writing
:obj:`numpy.sin` and :obj:`numpy.exp` here, they will be identified even though
they are not used in the code. This is useful in particular when functions
return classes (meaning it is not explicitly instantiated) -- if you add them
to the documented blocks of examples that use them, they will be added to
backreferences.

This functionality is used to add documentation hyperlinks to your code
(:ref:`link_to_documentation`) and for mini-gallery creation
(:ref:`references_to_examples`).
"""

# Code source: Óscar Nájera
# License: BSD 3 clause


filename = 'plot_6_function_identifier.py'
if not op.exists(filename):
    filename = __file__ if '__file__' in locals() else op.join(op.dirname(
                   sphinx_gallery.__path__[0]), 'examples', filename)


# Path: sphinx_gallery/backreferences.py
# def identify_names(script_blocks, global_variables=None, node=''):
#     """Build a codeobj summary by identifying and resolving used names."""
#     if node == '':  # mostly convenience for testing functions
#         c = '\n'.join(txt for kind, txt, _ in script_blocks if kind == 'code')
#         node = ast.parse(c)
#     # Get matches from the code (AST, implicit matches)
#     finder = NameFinder(global_variables)
#     if node is not None:
#         finder.visit(node)
#     names = list(finder.get_mapping())
#     # Get matches from docstring inspection (explicit matches)
#     text = '\n'.join(txt for kind, txt, _ in script_blocks if kind == 'text')
#     names.extend((x, x, False, False, True) for x in re.findall(_regex, text))
#     example_code_obj = collections.OrderedDict()  # order is important
#     # Make a list of all guesses, in `_embed_code_links` we will break
#     # when we find a match
#     for name, full_name, class_like, is_class, is_explicit in names:
#         if name not in example_code_obj:
#             example_code_obj[name] = list()
#         # name is as written in file (e.g. np.asarray)
#         # full_name includes resolved import path (e.g. numpy.asarray)
#         splitted = full_name.rsplit('.', 1 + class_like)
#         if len(splitted) == 1:
#             splitted = ('builtins', splitted[0])
#         elif len(splitted) == 3:  # class-like
#             assert class_like
#             splitted = (splitted[0], '.'.join(splitted[1:]))
#         else:
#             assert not class_like
# 
#         module, attribute = splitted
# 
#         # get shortened module name
#         module_short = _get_short_module_name(module, attribute)
#         cobj = {'name': attribute, 'module': module,
#                 'module_short': module_short or module, 'is_class': is_class,
#                 'is_explicit': is_explicit}
#         example_code_obj[name].append(cobj)
#     return example_code_obj
# 
# Path: sphinx_gallery/py_source_parser.py
# def split_code_and_text_blocks(source_file, return_node=False):
#     """Return list with source file separated into code and text blocks.
# 
#     Parameters
#     ----------
#     source_file : str
#         Path to the source file.
#     return_node : bool
#         If True, return the ast node.
# 
#     Returns
#     -------
#     file_conf : dict
#         File-specific settings given in source file comments as:
#         ``# sphinx_gallery_<name> = <value>``
#     blocks : list
#         (label, content, line_number)
#         List where each element is a tuple with the label ('text' or 'code'),
#         the corresponding content string of block and the leading line number
#     node : ast Node
#         The parsed node.
#     """
#     docstring, rest_of_content, lineno, node = _get_docstring_and_rest(
#         source_file)
#     blocks = [('text', docstring, 1)]
# 
#     file_conf = extract_file_config(rest_of_content)
# 
#     pattern = re.compile(
#         r'(?P<header_line>^#{20,}.*|^# ?%%.*)\s(?P<text_content>(?:^#.*\s?)*)',
#         flags=re.M)
#     sub_pat = re.compile('^#', flags=re.M)
# 
#     pos_so_far = 0
#     for match in re.finditer(pattern, rest_of_content):
#         code_block_content = rest_of_content[pos_so_far:match.start()]
#         if code_block_content.strip():
#             blocks.append(('code', code_block_content, lineno))
#         lineno += code_block_content.count('\n')
# 
#         lineno += 1  # Ignored header line of hashes.
#         text_content = match.group('text_content')
#         text_block_content = dedent(re.sub(sub_pat, '', text_content)).lstrip()
#         if text_block_content.strip():
#             blocks.append(('text', text_block_content, lineno))
#         lineno += text_content.count('\n')
# 
#         pos_so_far = match.end()
# 
#     remaining_content = rest_of_content[pos_so_far:]
#     if remaining_content.strip():
#         blocks.append(('code', remaining_content, lineno))
# 
#     out = (file_conf, blocks)
#     if return_node:
#         out += (node,)
#     return out


# Path: examples/plot_6_function_identifier.py
import os.path as op  # noqa, analysis:ignore
import matplotlib.pyplot as plt
import sphinx_gallery
from sphinx_gallery.backreferences import identify_names
from sphinx_gallery.py_source_parser import split_code_and_text_blocks

This demonstrates how Sphinx-Gallery identifies when

1. a function/method/attribute/object is used or class instantiated in a
   code block
2. a function/method/attribute/object/class is referred to using sphinx markup
   in a text block.

Sphinx-Gallery examines both the executed code itself, as well as the
text blocks (such as this one, or the one below) for these references and
identifies the module they belong to. This means that by writing
:obj:`numpy.sin` and :obj:`numpy.exp` here, they will be identified even though
they are not used in the code. This is useful in particular when functions
return classes (meaning it is not explicitly instantiated) -- if you add them
to the documented blocks of examples that use them, they will be added to
backreferences.

This functionality is used to add documentation hyperlinks to your code
(:ref:`link_to_documentation`) and for mini-gallery creation
(:ref:`references_to_examples`).
"""

# Code source: Óscar Nájera
# License: BSD 3 clause


filename = 'plot_6_function_identifier.py'
if not op.exists(filename):
    filename = __file__ if '__file__' in locals() else op.join(op.dirname(
                   sphinx_gallery.__path__[0]), 'examples', filename)


_, script_blocks = split_code_and_text_blocks(filename)