checker.py :  » Development » Epydoc » epydoc-3.0.1 » epydoc » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Epydoc 
Epydoc » epydoc 3.0.1 » epydoc » checker.py
#
# objdoc: epydoc documentation completeness checker
# Edward Loper
#
# Created [01/30/01 05:18 PM]
# $Id: checker.py 1366 2006-09-07 15:54:59Z edloper $
#

"""
Documentation completeness checker.  This module defines a single
class, C{DocChecker}, which can be used to check the that specified
classes of objects are documented.
"""
__docformat__ = 'epytext en'

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

import re, sys, os.path, string
from xml.dom.minidom import Text
from epydoc.apidoc import *

# The following methods may be undocumented:
_NO_DOCS = ['__hash__', '__repr__', '__str__', '__cmp__']

# The following methods never need descriptions, authors, or
# versions:
_NO_BASIC = ['__hash__', '__repr__', '__str__', '__cmp__']

# The following methods never need return value descriptions.
_NO_RETURN = ['__init__', '__hash__', '__repr__', '__str__', '__cmp__']

# The following methods don't need parameters documented:
_NO_PARAM = ['__cmp__']

class DocChecker:
    """
    Documentation completeness checker.  C{DocChecker} can be used to
    check that specified classes of objects are documented.  To check
    the documentation for a group of objects, you should create a
    C{DocChecker} from a L{DocIndex<apidoc.DocIndex>} that documents
    those objects; and then use the L{check} method to run specified
    checks on the objects' documentation.

    What checks are run, and what objects they are run on, are
    specified by the constants defined by C{DocChecker}.  These
    constants are divided into three groups.  

      - Type specifiers indicate what type of objects should be
        checked: L{MODULE}; L{CLASS}; L{FUNC}; L{VAR}; L{IVAR};
        L{CVAR}; L{PARAM}; and L{RETURN}.
      - Public/private specifiers indicate whether public or private
        objects should be checked: L{PRIVATE}.
      - Check specifiers indicate what checks should be run on the
        objects: L{TYPE}; L{DESCR}; L{AUTHOR};
        and L{VERSION}.

    The L{check} method is used to perform a check on the
    documentation.  Its parameter is formed by or-ing together at
    least one value from each specifier group:

        >>> checker.check(DocChecker.MODULE | DocChecker.DESCR)
        
    To specify multiple values from a single group, simply or their
    values together:
    
        >>> checker.check(DocChecker.MODULE | DocChecker.CLASS |
        ...               DocChecker.FUNC )

    @group Types: MODULE, CLASS, FUNC, VAR, IVAR, CVAR, PARAM,
        RETURN, ALL_T
    @type MODULE: C{int}
    @cvar MODULE: Type specifier that indicates that the documentation
        of modules should be checked.
    @type CLASS: C{int}
    @cvar CLASS: Type specifier that indicates that the documentation
        of classes should be checked.
    @type FUNC: C{int}
    @cvar FUNC: Type specifier that indicates that the documentation
        of functions should be checked.
    @type VAR: C{int}
    @cvar VAR: Type specifier that indicates that the documentation
        of module variables should be checked.
    @type IVAR: C{int}
    @cvar IVAR: Type specifier that indicates that the documentation
        of instance variables should be checked.
    @type CVAR: C{int}
    @cvar CVAR: Type specifier that indicates that the documentation
        of class variables should be checked.
    @type PARAM: C{int}
    @cvar PARAM: Type specifier that indicates that the documentation
        of function and method parameters should be checked.
    @type RETURN: C{int}
    @cvar RETURN: Type specifier that indicates that the documentation
        of return values should be checked.
    @type ALL_T: C{int}
    @cvar ALL_T: Type specifier that indicates that the documentation
        of all objects should be checked.

    @group Checks: TYPE, AUTHOR, VERSION, DESCR, ALL_C
    @type TYPE: C{int}
    @cvar TYPE: Check specifier that indicates that every variable and
        parameter should have a C{@type} field.
    @type AUTHOR: C{int}
    @cvar AUTHOR: Check specifier that indicates that every object
        should have an C{author} field.
    @type VERSION: C{int}
    @cvar VERSION: Check specifier that indicates that every object
        should have a C{version} field.
    @type DESCR: C{int}
    @cvar DESCR: Check specifier that indicates that every object
        should have a description.  
    @type ALL_C: C{int}
    @cvar ALL_C: Check specifier that indicates that  all checks
        should be run.

    @group Publicity: PRIVATE
    @type PRIVATE: C{int}
    @cvar PRIVATE: Specifier that indicates that private objects should
        be checked.
    """
    # Types
    MODULE = 1
    CLASS  = 2
    FUNC   = 4
    VAR    = 8
    #IVAR   = 16
    #CVAR   = 32
    PARAM  = 64
    RETURN = 128
    PROPERTY = 256
    ALL_T  = 1+2+4+8+16+32+64+128+256

    # Checks
    TYPE = 256
    AUTHOR = 1024
    VERSION = 2048
    DESCR = 4096
    ALL_C = 256+512+1024+2048+4096

    # Private/public
    PRIVATE = 16384

    ALL = ALL_T + ALL_C + PRIVATE

    def __init__(self, docindex):
        """
        Create a new C{DocChecker} that can be used to run checks on
        the documentation of the objects documented by C{docindex}

        @param docindex: A documentation map containing the
            documentation for the objects to be checked.
        @type docindex: L{Docindex<apidoc.DocIndex>}
        """
        self._docindex = docindex

        # Initialize instance variables
        self._checks = 0
        self._last_warn = None
        self._out = sys.stdout
        self._num_warnings = 0

    def check(self, *check_sets):
        """
        Run the specified checks on the documentation of the objects
        contained by this C{DocChecker}'s C{DocIndex}.  Any errors found
        are printed to standard out.

        @param check_sets: The checks that should be run on the
            documentation.  This value is constructed by or-ing
            together the specifiers that indicate which objects should
            be checked, and which checks should be run.  See the
            L{module description<checker>} for more information.
            If no checks are specified, then a default set of checks
            will be run.
        @type check_sets: C{int}
        @return: True if no problems were found.
        @rtype: C{boolean}
        """
        if not check_sets:
            check_sets = (DocChecker.MODULE | DocChecker.CLASS |
                          DocChecker.FUNC | DocChecker.VAR | 
                          DocChecker.DESCR,)
            
        self._warnings = {}
        log.start_progress('Checking docs')
        for j, checks in enumerate(check_sets):
            self._check(checks)
        log.end_progress()

        for (warning, docs) in self._warnings.items():
            docs = sorted(docs)
            docnames = '\n'.join(['  - %s' % self._name(d) for d in docs])
            log.warning('%s:\n%s' % (warning, docnames))

    def _check(self, checks):
        self._checks = checks
        
        # Get the list of objects to check.
        valdocs = sorted(self._docindex.reachable_valdocs(
            imports=False, packages=False, bases=False, submodules=False, 
            subclasses=False, private = (checks & DocChecker.PRIVATE)))
        docs = set()
        for d in valdocs:
            if not isinstance(d, GenericValueDoc): docs.add(d)
        for doc in valdocs:
            if isinstance(doc, NamespaceDoc):
                for d in doc.variables.values():
                    if isinstance(d.value, GenericValueDoc): docs.add(d)

        for i, doc in enumerate(sorted(docs)):
            if isinstance(doc, ModuleDoc):
                self._check_module(doc)
            elif isinstance(doc, ClassDoc):
                self._check_class(doc)
            elif isinstance(doc, RoutineDoc):
                self._check_func(doc)
            elif isinstance(doc, PropertyDoc):
                self._check_property(doc)
            elif isinstance(doc, VariableDoc):
                self._check_var(doc)
            else:
                log.error("Don't know how to check %r" % doc)

    def _name(self, doc):
        name = str(doc.canonical_name)
        if isinstance(doc, RoutineDoc): name += '()'
        return name

    def _check_basic(self, doc):
        """
        Check the description, author, version, and see-also fields of
        C{doc}.  This is used as a helper function by L{_check_module},
        L{_check_class}, and L{_check_func}.

        @param doc: The documentation that should be checked.
        @type doc: L{APIDoc}
        @rtype: C{None}
        """
        if ((self._checks & DocChecker.DESCR) and
            (doc.descr in (None, UNKNOWN))):
            if doc.docstring in (None, UNKNOWN):
                self.warning('Undocumented', doc)
            else:
                self.warning('No description', doc)
        if self._checks & DocChecker.AUTHOR:
            for tag, arg, descr in doc.metadata:
                if 'author' == tag: break
            else:
                self.warning('No authors', doc)
        if self._checks & DocChecker.VERSION:
            for tag, arg, descr in doc.metadata:
                if 'version' == tag: break
            else:
                self.warning('No version', doc)
            
    def _check_module(self, doc):
        """
        Run checks on the module whose APIDoc is C{doc}.
        
        @param doc: The APIDoc of the module to check.
        @type doc: L{APIDoc}
        @rtype: C{None}
        """
        if self._checks & DocChecker.MODULE:
            self._check_basic(doc)
        
    def _check_class(self, doc):
        """
        Run checks on the class whose APIDoc is C{doc}.
        
        @param doc: The APIDoc of the class to check.
        @type doc: L{APIDoc}
        @rtype: C{None}
        """
        if self._checks & DocChecker.CLASS:
            self._check_basic(doc)

    def _check_property(self, doc):
        if self._checks & DocChecker.PROPERTY:
            self._check_basic(doc)

    def _check_var(self, doc):
        """
        Run checks on the variable whose documentation is C{var} and
        whose name is C{name}.
        
        @param doc: The documentation for the variable to check.
        @type doc: L{APIDoc}
        @rtype: C{None}
        """
        if self._checks & DocChecker.VAR:
            if (self._checks & (DocChecker.DESCR|DocChecker.TYPE) and
                doc.descr in (None, UNKNOWN) and
                doc.type_descr in (None, UNKNOWN) and
                doc.docstring in (None, UNKNOWN)):
                self.warning('Undocumented', doc)
            else:
                if (self._checks & DocChecker.DESCR and
                    doc.descr in (None, UNKNOWN)):
                    self.warning('No description', doc)
                if (self._checks & DocChecker.TYPE and
                    doc.type_descr in (None, UNKNOWN)):
                    self.warning('No type information', doc)
            
    def _check_func(self, doc):
        """
        Run checks on the function whose APIDoc is C{doc}.
        
        @param doc: The APIDoc of the function to check.
        @type doc: L{APIDoc}
        @rtype: C{None}
        """
        name = doc.canonical_name
        if (self._checks & DocChecker.FUNC and
            doc.docstring in (None, UNKNOWN) and
            doc.canonical_name[-1] not in _NO_DOCS):
            self.warning('Undocumented', doc)
            return
        if (self._checks & DocChecker.FUNC and
            doc.canonical_name[-1] not in _NO_BASIC):
                self._check_basic(doc)
        if (self._checks & DocChecker.RETURN and
            doc.canonical_name[-1] not in _NO_RETURN):
            if (doc.return_type in (None, UNKNOWN) and
                doc.return_descr in (None, UNKNOWN)):
                self.warning('No return descr', doc)
        if (self._checks & DocChecker.PARAM and
            doc.canonical_name[-1] not in _NO_PARAM):
            if doc.arg_descrs in (None, UNKNOWN):
                self.warning('No argument info', doc)
            else:
                args_with_descr = []
                for arg, descr in doc.arg_descrs:
                    if isinstance(arg, basestring):
                        args_with_descr.append(arg)
                    else:
                        args_with_descr += arg
                for posarg in doc.posargs:
                    if (self._checks & DocChecker.DESCR and
                        posarg not in args_with_descr):
                        self.warning('Argument(s) not described', doc)
                    if (self._checks & DocChecker.TYPE and
                        posarg not in doc.arg_types):
                        self.warning('Argument type(s) not described', doc)

    def warning(self, msg, doc):
        self._warnings.setdefault(msg,set()).add(doc)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.