<commit_before># epydoc -- Introspection
#
# Copyright (C) 2005 <NAME>
# Author: <NAME> <<EMAIL>>
# URL: <http://epydoc.sf.net>
#
# $Id: docintrospecter.py 1678 2008-01-29 17:21:29Z edloper $

"""
Extract API documentation about python objects by directly introspecting
their values.

The function L{introspect_docs()}, which provides the main interface
of this module, examines a Python objects via introspection, and uses
the information it finds to create an L{APIDoc} objects containing the
API documentation for that objects.

The L{register_introspecter()} method can be used to extend the
functionality of C{docintrospector}, by providing methods that handle
special value types.
"""
__docformat__ = 'epytext en'

######################################################################
## Imports
######################################################################

import inspect, re, sys, os.path, imp
# API documentation encoding:
from epydoc.apidoc import *
# Type comparisons:
from types import *
# Error reporting:
from epydoc import log
# Helper functions:
from epydoc.util import *
# For extracting encoding for docstrings:
import epydoc.docparser
# Builtin values
import __builtin__
# Backwards compatibility
from epydoc.compat import * 

######################################################################
## Caches
######################################################################

_valuedoc_cache = {}
"""A cache containing the API documentation for values that we've
already seen.  This cache is implemented as a dictionary that maps a
value's pyid to its L{ValueDoc}.

Note that if we encounter a value but decide not to introspect it
(because it's imported from another module), then C{_valuedoc_cache}
will contain an entry for the value, but the value will not be listed
in L{_introspected_values}."""

_introspected_values = {}
"""A record which values we've introspected, encoded as a dictionary from
pyid to C{bool}."""

def clear_cache():
    """
    Discard any cached C{APIDoc} values that have been computed for
    introspected values.
    """
    _valuedoc_cache.clear()
    _introspected_values.clear()

######################################################################
## Introspection
######################################################################

def introspect_docs(value=None, name=None, filename=None, context=None,
                    is_script=False, module_name=None):
    """
    Generate the API documentation for a specified object by
    introspecting Python values, and return it as a L{ValueDoc}.  The
    object to generate documentation for may be specified using
    the C{value} parameter, the C{filename} parameter, I{or} the
    C{name} parameter.  (It is an error to specify more than one
    of these three parameters, or to not specify any of them.)

    @param value: The python object that should be documented.
    @param filename: The name of the file that contains the python
        source code for a package, module, or script.  If
        C{filename} is specified, then C{introspect} will return a
        C{ModuleDoc} describing its contents.
    @param name: The fully-qualified python dotted name of any
        value (including packages, modules, classes, and
        functions).  C{DocParser} will automatically figure out
        which module(s) it needs to import in order to find the
        documentation for the specified object.
    @param context: The API documentation for the class of module
        that contains C{value} (if available).
    @param module_name: The name of the module where the value is defined.
        Useful to retrieve the docstring encoding if there is no way to
        detect the module by introspection (such as in properties)
    """
    if value is None and name is not None and filename is None:
        value = get_value_from_name(DottedName(name))
    elif value is None and name is None and filename is not None:
        if is_script:
            value = get_value_from_scriptname(filename)
        else:
            value = get_value_from_filename(filename, context)
    elif name is None and filename is None:
        # it's ok if value is None -- that's a value, after all.
        pass 
    else:
        raise ValueError("Expected exactly one of the following "
                         "arguments: value, name, filename")
    
    pyid = id(value)

    # If we've already introspected this value, then simply return
    # its ValueDoc from our cache.
    if pyid in _introspected_values:
        # If the file is a script, then adjust its name.
        if is_script and filename is not None:
            _valuedoc_cache[pyid].canonical_name = DottedName(
                munge_script_name(str(filename)))
        return _valuedoc_cache[pyid]

    # Create an initial value doc for this value & add it to the cache.
    val_doc = _get_valuedoc(value)

    # Introspect the value.
    _introspected_values[pyid] = True
    introspect_func = _get_introspecter(value)
    introspect_func(value, val_doc, module_name=module_name)

    # Set canonical name, if it was given
    if val_doc.canonical_name is UNKNOWN and name is not None:
        val_doc.canonical_name = DottedName(name)

    # If the file is a script, then adjust its name.
    if is_script and filename is not None:
        val_doc.canonical_name = DottedName(munge_script_name(str(filename)))
        
    if val_doc.canonical_name is UNKNOWN and filename is not None:
        shadowed_name = DottedName(value.__name__)
        log.warning("Module %s is shadowed by a variable with "
                    "the same name." % shadowed_name)
        val_doc.canonical_name = DottedName(str(shadowed_name)+"'")

    return val_doc

def _get_valuedoc(value):
    """
    If a C{ValueDoc} for the given value exists in the valuedoc
    cache, then return it; otherwise, create a new C{ValueDoc},
    add it to the cache, and return it.  When possible, the new
    C{ValueDoc}'s C{pyval}, C{repr}, and C{canonical_name}
    attributes will be set appropriately.
    """
    pyid = id(value)
    val_doc = _valuedoc_cache.get(pyid)
    if val_doc is None:
        try: canonical_name = get_canonical_name(value, strict=True)
        except DottedName.InvalidDottedName: canonical_name = UNKNOWN
        val_doc = ValueDoc(pyval=value, canonical_name = canonical_name,
                           docs_extracted_by='introspecter')
        _valuedoc_cache[pyid] = val_doc
        
        # If it's a module, then do some preliminary introspection.
        # Otherwise, check what the containing module is (used e.g.
        # to decide what markup language should be used for docstrings)
        if inspect.ismodule(value):
            introspect_module(value, val_doc, preliminary=True)
            val_doc.defining_module = val_doc
        else:
            module_name = str(get_containing_module(value))
            module = sys.modules.get(module_name)
            if module is not None and inspect.ismodule(module):
                val_doc.defining_module = _get_valuedoc(module)
            
    return val_doc

#////////////////////////////////////////////////////////////
# Module Introspection
#////////////////////////////////////////////////////////////

#: A list of module variables that should not be included in a
#: module's API documentation.
UNDOCUMENTED_MODULE_VARS = (
    '__builtins__', '__doc__', '__all__', '__file__', '__path__',
    '__name__', '__extra_epydoc_fields__', '__docformat__')

def introspect_module(module, module_doc, module_name=None, preliminary=False):
    """
    Add API documentation information about the module C{module}
    to C{module_doc}.
    """
    module_doc.specialize_to(ModuleDoc)

    # Record the module's docformat
    if hasattr(module, '__docformat__'):
        module_doc.docformat = unicode(module.__docformat__)
                                  
    # Record the module's filename
    if hasattr(module, '__file__'):
        try: module_doc.filename = unicode(module.__file__)
        except KeyboardInterrupt: raise
        except: pass
        if module_doc.filename is not UNKNOWN:
            try: module_doc.filename = py_src_filename(module_doc.filename)
            except ValueError: pass

    # If this is just a preliminary introspection, then don't do
    # anything else.  (Typically this is true if this module was
    # imported, but is not included in the set of modules we're
    # documenting.)
    module_doc.variables = {}
    if preliminary: return
<commit_msg>add patch from pld-linux<commit_after># epydoc -- Introspection
#
# Copyright (C) 2005 <NAME>
# Author: <NAME> <<EMAIL>>
# URL: <http://epydoc.sf.net>
#
# $Id: docintrospecter.py 1678 2008-01-29 17:21:29Z edloper $

"""
Extract API documentation about python objects by directly introspecting
their values.

The function L{introspect_docs()}, which provides the main interface
of this module, examines a Python objects via introspection, and uses
the information it finds to create an L{APIDoc} objects containing the
API documentation for that objects.

The L{register_introspecter()} method can be used to extend the
functionality of C{docintrospector}, by providing methods that handle
special value types.
"""
__docformat__ = 'epytext en'

######################################################################
## Imports
######################################################################

import inspect, re, sys, os.path, imp
# API documentation encoding:
from epydoc.apidoc import *
# Type comparisons:
from types import *
# Error reporting:
from epydoc import log
# Helper functions:
from epydoc.util import *
# For extracting encoding for docstrings:
import epydoc.docparser
# Builtin values
import __builtin__
# Backwards compatibility
from epydoc.compat import * 

######################################################################
## Caches
######################################################################

_valuedoc_cache = {}
"""A cache containing the API documentation for values that we've
already seen.  This cache is implemented as a dictionary that maps a
value's pyid to its L{ValueDoc}.

Note that if we encounter a value but decide not to introspect it
(because it's imported from another module), then C{_valuedoc_cache}
will contain an entry for the value, but the value will not be listed
in L{_introspected_values}."""

_introspected_values = {}
"""A record which values we've introspected, encoded as a dictionary from
pyid to C{bool}."""

def clear_cache():
    """
    Discard any cached C{APIDoc} values that have been computed for
    introspected values.
    """
    _valuedoc_cache.clear()
    _introspected_values.clear()

######################################################################
## Introspection
######################################################################

def introspect_docs(value=None, name=None, filename=None, context=None,
                    is_script=False, module_name=None):
    """
    Generate the API documentation for a specified object by
    introspecting Python values, and return it as a L{ValueDoc}.  The
    object to generate documentation for may be specified using
    the C{value} parameter, the C{filename} parameter, I{or} the
    C{name} parameter.  (It is an error to specify more than one
    of these three parameters, or to not specify any of them.)

    @param value: The python object that should be documented.
    @param filename: The name of the file that contains the python
        source code for a package, module, or script.  If
        C{filename} is specified, then C{introspect} will return a
        C{ModuleDoc} describing its contents.
    @param name: The fully-qualified python dotted name of any
        value (including packages, modules, classes, and
        functions).  C{DocParser} will automatically figure out
        which module(s) it needs to import in order to find the
        documentation for the specified object.
    @param context: The API documentation for the class of module
        that contains C{value} (if available).
    @param module_name: The name of the module where the value is defined.
        Useful to retrieve the docstring encoding if there is no way to
        detect the module by introspection (such as in properties)
    """
    if value is None and name is not None and filename is None:
        value = get_value_from_name(DottedName(name))
    elif value is None and name is None and filename is not None:
        if is_script:
            value = get_value_from_scriptname(filename)
        else:
            value = get_value_from_filename(filename, context)
    elif name is None and filename is None:
        # it's ok if value is None -- that's a value, after all.
        pass 
    else:
        raise ValueError("Expected exactly one of the following "
                         "arguments: value, name, filename")
    
    pyid = id(value)

    # If we've already introspected this value, then simply return
    # its ValueDoc from our cache.
    if pyid in _introspected_values:
        # If the file is a script, then adjust its name.
        if is_script and filename is not None:
            _valuedoc_cache[pyid].canonical_name = DottedName(
                munge_script_name(str(filename)))
        return _valuedoc_cache[pyid]

    # Create an initial value doc for this value & add it to the cache.
    val_doc = _get_valuedoc(value)

    # Introspect the value.
    _introspected_values[pyid] = True
    introspect_func = _get_introspecter(value)
    introspect_func(value, val_doc, module_name=module_name)

    # Set canonical name, if it was given
    if val_doc.canonical_name is UNKNOWN and name is not None:
        val_doc.canonical_name = DottedName(name)

    # If the file is a script, then adjust its name.
    if is_script and filename is not None:
        val_doc.canonical_name = DottedName(munge_script_name(str(filename)))
        
    if val_doc.canonical_name is UNKNOWN and filename is not None:
        shadowed_name = DottedName(value.__name__)
        log.warning("Module %s is shadowed by a variable with "
                    "the same name." % shadowed_name)
        val_doc.canonical_name = DottedName(str(shadowed_name)+"'")

    return val_doc

def _get_valuedoc(value):
    """
    If a C{ValueDoc} for the given value exists in the valuedoc
    cache, then return it; otherwise, create a new C{ValueDoc},
    add it to the cache, and return it.  When possible, the new
    C{ValueDoc}'s C{pyval}, C{repr}, and C{canonical_name}
    attributes will be set appropriately.
    """
    pyid = id(value)
    val_doc = _valuedoc_cache.get(pyid)
    if val_doc is None:
        try: canonical_name = get_canonical_name(value, strict=True)
        except DottedName.InvalidDottedName: canonical_name = UNKNOWN
        val_doc = ValueDoc(pyval=value, canonical_name = canonical_name,
                           docs_extracted_by='introspecter')
        _valuedoc_cache[pyid] = val_doc
        
        # If it's a module, then do some preliminary introspection.
        # Otherwise, check what the containing module is (used e.g.
        # to decide what markup language should be used for docstrings)
        if inspect.ismodule(value):
            introspect_module(value, val_doc, preliminary=True)
            val_doc.defining_module = val_doc
        else:
            module_name = str(get_containing_module(value))
            module = sys.modules.get(module_name)
            if module is not None and inspect.ismodule(module):
                val_doc.defining_module = _get_valuedoc(module)
            
    return val_doc

#////////////////////////////////////////////////////////////
# Module Introspection
#////////////////////////////////////////////////////////////

#: A list of module variables that should not be included in a
#: module's API documentation.
UNDOCUMENTED_MODULE_VARS = (
    '__builtins__', '__doc__', '__all__', '__file__', '__path__',
    '__name__', '__extra_epydoc_fields__', '__docformat__', '__package__')

def introspect_module(module, module_doc, module_name=None, preliminary=False):
    """
    Add API documentation information about the module C{module}
    to C{module_doc}.
    """
    module_doc.specialize_to(ModuleDoc)

    # Record the module's docformat
    if hasattr(module, '__docformat__'):
        module_doc.docformat = unicode(module.__docformat__)
                                  
    # Record the module's filename
    if hasattr(module, '__file__'):
        try: module_doc.filename = unicode(module.__file__)
        except KeyboardInterrupt: raise
        except: pass
        if module_doc.filename is not UNKNOWN:
            try: module_doc.filename = py_src_filename(module_doc.filename)
            except ValueError: pass

    # If this is just a preliminary introspection, then don't do
    # anything else.  (Typically this is true if this module was
    # imported, but is not included in the set of modules we're
    # documenting.)
    module_doc.variables = {}
    if preliminary: return

{'fraction_non_alphanumeric': 0.13055165965404394, 'fraction_numerical': 0.002571294997662459, 'mean_word_length': 3.127592860588519, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3275675', 'n_tokens_mistral': 4758, 'n_tokens_neox': 4547, 'n_words': 1706}