happydoc-checkins Mailing List for HappyDoc (Page 9)
Brought to you by:
doughellmann,
krlosaqp
You can subscribe to this list here.
2002 |
Jan
(3) |
Feb
(40) |
Mar
(1) |
Apr
|
May
(12) |
Jun
(4) |
Jul
|
Aug
(39) |
Sep
|
Oct
(4) |
Nov
(49) |
Dec
(78) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(54) |
Feb
|
Mar
(41) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2006 |
Jan
|
Feb
|
Mar
|
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(13) |
From: Doug H. <dou...@us...> - 2002-11-17 16:20:02
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib In directory usw-pr-cvs1:/tmp/cvs-serv25274/happydoclib Modified Files: scanner.py test_scanner.py Log Message: Add a separate canonical name to the package tree. This can be used to determine the full input name of the tree, where the regular name is used to determine the relative positional name of each node. Index: scanner.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/scanner.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** scanner.py 17 Nov 2002 15:15:17 -0000 1.3 --- scanner.py 17 Nov 2002 16:19:59 -0000 1.4 *************** *** 80,86 **** def __init__(self, parent, name): UserDict.UserDict.__init__(self) self.parent = parent ! self.name = name return --- 80,92 ---- def __init__(self, parent, name): + trace.into('PackageTree', '__init__', + parent=parent, + name=name, + ) UserDict.UserDict.__init__(self) self.parent = parent ! self.name = os.path.basename(name) ! self.canonical_name = name ! trace.outof() return *************** *** 101,105 **** return self.name ! def getPath(self): """Return the path from the root to this node. --- 107,116 ---- return self.name ! def getCanonicalName(self): ! """Returns the canonical, full, name of the this tree node. ! """ ! return self.canonical_name ! ! def getPath(self, useCanonicalName=0): """Return the path from the root to this node. *************** *** 109,116 **** parent = self.getParent() if parent: ! parent_path = parent.getPath() else: parent_path = () ! path = parent_path + (self.getName(),) return path --- 120,132 ---- parent = self.getParent() if parent: ! parent_path = parent.getPath(useCanonicalName=useCanonicalName) else: parent_path = () ! ! if useCanonicalName: ! name = self.getCanonicalName() ! else: ! name = self.getName() ! path = parent_path + (name,) return path *************** *** 189,193 **** tree = parent.addSubNode(package_tree_name) else: ! tree = PackageTree(parent, package_tree_name) # --- 205,209 ---- tree = parent.addSubNode(package_tree_name) else: ! tree = PackageTree(parent, directoryName) # Index: test_scanner.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/test_scanner.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** test_scanner.py 17 Nov 2002 15:02:11 -0000 1.2 --- test_scanner.py 17 Nov 2002 16:19:59 -0000 1.3 *************** *** 165,168 **** --- 165,189 ---- ) return + + def testPackageTreePath(self): + import os + cwd = os.getcwd() + input_dir = os.path.join(cwd, 'TestCases/testScanner') + scanner = Scanner([input_dir]) + + trees = scanner.getPackageTrees() + expected_tree = trees[0] + + module_two = expected_tree['levelOne']['levelTwo']['two.py'] + + module_two_path = module_two.getPath(1) + self.failUnlessEqual(module_two_path, + (input_dir, + 'levelOne', + 'levelTwo', + 'two.py', + ), + ) + return def testPackageTreeIgnore(self): *************** *** 184,187 **** --- 205,220 ---- tree = PackageTree(None, 'tree1') self.failUnlessEqual('tree1', tree.getName(), + 'Names do not match.') + return + + def testPackageTreeNameNotCanonical(self): + tree = PackageTree(None, '/full/path/to/tree1') + self.failUnlessEqual('tree1', tree.getName(), + 'Names do not match.') + return + + def testPackageTreeNameCanonical(self): + tree = PackageTree(None, '/full/path/to/tree1') + self.failUnlessEqual('/full/path/to/tree1', tree.getCanonicalName(), 'Names do not match.') return |
From: Doug H. <dou...@us...> - 2002-11-17 16:17:17
|
Update of /cvsroot/happydoc/HappyDoc3/TestCases/testScanner/levelOne In directory usw-pr-cvs1:/tmp/cvs-serv24251/TestCases/testScanner/levelOne Added Files: README.txt Log Message: Add simple text files to the sample test case. --- NEW FILE: README.txt --- This is the README file for levelOne. |
From: Doug H. <dou...@us...> - 2002-11-17 16:17:17
|
Update of /cvsroot/happydoc/HappyDoc3/TestCases/testScanner/levelOne/levelTwo In directory usw-pr-cvs1:/tmp/cvs-serv24251/TestCases/testScanner/levelOne/levelTwo Added Files: README.stx Log Message: Add simple text files to the sample test case. --- NEW FILE: README.stx --- This is a StructuredText README file. |
From: Doug H. <dou...@us...> - 2002-11-17 15:15:29
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib In directory usw-pr-cvs1:/tmp/cvs-serv6820/happydoclib Modified Files: appclass.py Log Message: Use regular expressions to look for files to ignore. Index: appclass.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/appclass.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** appclass.py 17 Nov 2002 14:59:08 -0000 1.2 --- appclass.py 17 Nov 2002 15:15:26 -0000 1.3 *************** *** 127,131 **** self._ignore_dir_patterns = [] ! self.addIgnoreDirectoryPattern('CVS', 'dist', 'build', 'doc', 'docs') ## self.parser_function = happydoclib.parseinfo.getDocs --- 127,131 ---- self._ignore_dir_patterns = [] ! self.addIgnoreDirectoryPattern('(CVS|dist|build|docs?|.*pyc|.*~)') ## self.parser_function = happydoclib.parseinfo.getDocs |
From: Doug H. <dou...@us...> - 2002-11-17 15:15:20
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib In directory usw-pr-cvs1:/tmp/cvs-serv6772/happydoclib Modified Files: scanner.py Log Message: Use regular expressions to look for files to ignore. Index: scanner.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/scanner.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** scanner.py 17 Nov 2002 15:01:50 -0000 1.2 --- scanner.py 17 Nov 2002 15:15:17 -0000 1.3 *************** *** 60,63 **** --- 60,64 ---- import glob import os + import re import UserDict *************** *** 142,148 **** """ ! def __init__(self, inputDirectories, ignoreNames=[]): ! self._ignore_names = ignoreNames self._package_trees = [] --- 143,150 ---- """ ! def __init__(self, inputDirectories, ignorePatterns=[]): ! self._ignore_patterns = ignorePatterns ! self._ignore_res = [ re.compile(ip) for ip in ignorePatterns ] self._package_trees = [] *************** *** 175,181 **** # Make sure we are not ignoring this name # ! if package_tree_name in self._ignore_names: ! trace.outof() ! return None # --- 177,185 ---- # Make sure we are not ignoring this name # ! #if package_tree_name in self._ignore_names: ! for ignore_re in self._ignore_res: ! if ignore_re.match(package_tree_name): ! trace.outof() ! return None # |
From: Doug H. <dou...@us...> - 2002-11-17 15:06:09
|
Update of /cvsroot/happydoc/HappyDoc3/tools In directory usw-pr-cvs1:/tmp/cvs-serv4318/tools Added Files: run_etags Log Message: Script to run etags. --- NEW FILE: run_etags --- #!/bin/bash # # $Id: run_etags,v 1.1 2002/11/17 15:06:06 doughellmann Exp $ # # Script to run etags against the source tree. # rm -f TAGS echo -n "Running etags..." find . \ \( -type f \( -name '*.py' -o -name '*.[ch]' \) \) \ -print \ \ | etags -l auto \ --regex='/[ \t]*\def[ \t]+\([^ :(\t]+\)/\1/' \ - echo "Done" |
Update of /cvsroot/happydoc/HappyDoc3/happydoclib/parseinfo In directory usw-pr-cvs1:/tmp/cvs-serv4203/happydoclib/parseinfo Added Files: utils.py suite.py parsecomments.py moduleinfo.py imports.py functioninfo.py classinfo.py __init__.py Log Message: Import parseinfo modules from HappyDoc 2.x, with some mods. Move parsecomments.py into this package. --- NEW FILE: utils.py --- #!/usr/bin/env python # # $Id: utils.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $ # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # """Utility functions for parseinfo package. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: utils.py,v $', 'rcs_id' : '$Id: utils.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $', 'creator' : 'Doug Hellmann <do...@he...>', 'project' : 'UNSPECIFIED', 'created' : 'Sun, 11-Nov-2001 10:47:39 EST', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 15:05:43 $', } try: __version__ = __rcs_info__['version'].split(' ')[1] except: __version__ = '0.0' # # Import system modules # import pprint import symbol import token import types # # Import Local modules # # # Module # # This pattern identifies compound statements, allowing them to be readily # differentiated from simple statements. # COMPOUND_STMT_PATTERN = ( symbol.stmt, (symbol.compound_stmt, ['compound']) ) # This pattern matches the name of an item which appears in a # testlist sequence. This can be used for finding the # base classes of a class, or the parameters to a function or # method. # # BASE_CLASS_NAME_PATTERN = ( # symbol.test, # (symbol.and_test, # (symbol.not_test, # (symbol.comparison, # (symbol.expr, # (symbol.xor_expr, # (symbol.and_expr, # (symbol.shift_expr, # (symbol.arith_expr, # (symbol.term, # (symbol.factor, # (symbol.power, # (symbol.atom, # (token.NAME, ['name']) # ))))))))))))) BASE_CLASS_NAME_PATTERN = ( symbol.test, (symbol.and_test, (symbol.not_test, (symbol.comparison, (symbol.expr, (symbol.xor_expr, (symbol.and_expr, (symbol.shift_expr, (symbol.arith_expr, (symbol.term, (symbol.factor, ['power']) )))))))))) # This pattern will match a 'stmt' node which *might* represent a docstring; # docstrings require that the statement which provides the docstring be the # first statement in the class or function, which this pattern does not check. # DOCSTRING_STMT_PATTERN = ( symbol.stmt, (symbol.simple_stmt, (symbol.small_stmt, (symbol.expr_stmt, (symbol.testlist, (symbol.test, (symbol.and_test, (symbol.not_test, (symbol.comparison, (symbol.expr, (symbol.xor_expr, (symbol.and_expr, (symbol.shift_expr, (symbol.arith_expr, (symbol.term, (symbol.factor, (symbol.power, (symbol.atom, (token.STRING, ['docstring']) )))))))))))))))), (token.NEWLINE, '') )) def joinCodeSnippets(first, second, separator): """Join two code snippets into one string. Use some general code content rules to try to make the resulting snippet look nice. """ if second.strip() in ('.',): sep_to_be_used = '' elif second and ( second[0] in ('.', ',', '(',) ): if second[0] == '(' and first and first[-1] == ',': sep_to_be_used = separator else: sep_to_be_used = '' elif (not first) or (first and first[-1] in ('.',)) or (first in ('-',)): sep_to_be_used = '' elif ( (first and ( first[-1] in ('(', '[', '{') )) and (second and ( second[-1] in (')', ']', '}') )) ): sep_to_be_used = '' elif first and ( first[-1] in ('(', '[', '{') ): sep_to_be_used = separator else: sep_to_be_used = separator text = '%s%s%s' % (first, sep_to_be_used, second) return text def parseTreeToString(tree, separator=' '): """Convert a parse tree to a string which would have parsed in that way. Given a parse tree, walk it to determine the original string which would have been parsed to produce that tree. """ #pprint 'STRINGING: ', #pprint.pprint(tree) text = '' if tree and type(tree) in (types.TupleType, types.ListType): if type(tree[0]) in (types.TupleType, types.ListType): tree_parts = tree else: tree_parts = tree[1:] sub_parts = map( lambda x, s=separator: parseTreeToString(x, s), tree_parts) for one_part in sub_parts: text = joinCodeSnippets(text, one_part, separator) else: text = str(tree) return text def findNode(tree, node, response=None): "Return a sequence of subtrees starting with node value of 'node'." if response == None: response = [] if type(tree) not in (types.ListType, types.TupleType): return response if tree[0] == node: response.append(tree) else: for subtree in tree[1:]: findNode(subtree, node, response) return response def drill(tree, depth): "Return the section of the parse 'tree' that is 'depth' nodes deep." for i in range(depth): try: tree = tree[1] except IndexError: return () return tree def match(pattern, data, vars=None, dbg=0): """Match `data' to `pattern', with variable extraction. pattern -- Pattern to match against, possibly containing variables. data -- Data to be checked and against which variables are extracted. vars -- Dictionary of variables which have already been found. If not provided, an empty dictionary is created. The `pattern' value may contain variables of the form ['varname'] which are allowed to match anything. The value that is matched is returned as part of a dictionary which maps 'varname' to the matched value. 'varname' is not required to be a string object, but using strings makes patterns and the code which uses them more readable. This function returns two values: a boolean indicating whether a match was found and a dictionary mapping variable names to their associated values. """ pattern_type = type(pattern) #if dbg: # print 'PATTERN: ', # pprint.pprint(pattern) # print 'DATA:', # pprint.pprint(data) if vars is None: vars = {} if pattern_type is types.ListType: # 'variables' are ['varname'] #if dbg: # print 'storing "%s" for variable "%s"' % (data, pattern[0]) vars[pattern[0]] = data return 1, vars if pattern_type is not types.TupleType: #if dbg: # print 'end recursion' # print 'pattern=', pattern # print 'data', data # # Ignore comments, since the pattern will include an empty # string. # if (pattern_type == types.StringType) and (data and data[0] == '#'): return 1, vars return (pattern == data), vars if len(data) != len(pattern): #if dbg: # print 'shortcut, length does not match' return 0, vars for pattern, data in map(None, pattern, data): #if dbg: # print 'recursing' same, vars = match(pattern, data, vars, dbg=dbg) if not same: break return same, vars def lenientMatch(pattern, data, vars=None, dbg=0): """Match `data' to `pattern', with variable extraction. pattern -- Pattern to match against, possibly containing variables. data -- Data to be checked and against which variables are extracted. vars -- Dictionary of variables which have already been found. If not provided, an empty dictionary is created. The `pattern' value may contain variables of the form ['varname'] which are allowed to match anything. The value that is matched is returned as part of a dictionary which maps 'varname' to the matched value. 'varname' is not required to be a string object, but using strings makes patterns and the code which uses them more readable. This function is based on the match() function, but is more lenient. The pattern does not have to completely describe the tree. Instead, it can be the 'top' portion of the tree. Everything must match down to the leaves of the pattern. At that point, the matching stops. If a match was found at all, the return values indicate a match. This function returns two values: a boolean indicating whether a match was found and a dictionary mapping variable names to their associated values. """ #if dbg: # print 'PATTERN : ', # pprint.pprint(pattern) # print 'DATA :', # #pprint.pprint(data) # print data if vars is None: vars = {} if type(pattern) is types.ListType: # 'variables' are ['varname'] #if dbg: # print 'storing "%s" for variable "%s"' % (data, pattern[0]) vars[pattern[0]] = data return 1, vars if type(pattern) is not types.TupleType: #if dbg: # print 'end recursion' return (pattern == data), vars found_match = 0 if pattern and data: for pattern, data in map(None, pattern, data): #if dbg: # print 'recursing' same, vars = lenientMatch(pattern, data, vars, dbg=dbg) if not same: break else: found_match = same return found_match, vars --- NEW FILE: suite.py --- #!/usr/bin/env python # # $Id: suite.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $ # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # """Base class for information gathering classes. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: suite.py,v $', 'rcs_id' : '$Id: suite.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $', 'creator' : 'Doug Hellmann <do...@he...>', 'project' : 'UNSPECIFIED', 'created' : 'Sun, 11-Nov-2001 10:45:58 EST', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 15:05:43 $', } try: __version__ = __rcs_info__['version'].split(' ')[1] except: __version__ = '0.0' # # Import system modules # import re # # Import Local modules # import happydoclib from happydoclib.parseinfo.utils import * # # Module # class SuiteInfoBase: """Base class for information gathering classes. Default implementation assumes that the user is interested in learning about functions and classes defined within the parse tree used for initialization. This makes implementation of MethodInfo easy. Other derived classes add behavior to find other information. """ #_docstring = '' _docstring_summary = None def __init__(self, name, parent, filename, tree, commentInfo={}, defaultConfigValues={}, ): """Initialize the info extractor. Parameters: name -- name of this object parent -- parent object (e.g. Module for Class) filename -- file which contains the tree tree -- parse tree from which to extract information commentInfo -- comments extracted from source file where this object was found """ self._name = name self._parent = parent self._filename = filename self._class_info = {} self._function_info = {} self._namespaces = ( self._class_info, self._function_info ) self._comment_info = commentInfo self._configuration_values = {} self._configuration_values.update(defaultConfigValues) self._extractConfigurationValues() comment_key = self.getCommentKey() #print 'PARSEINFO: Looking for comments for %s in %s' % (name, comment_key) self._comments = commentInfo.get(comment_key, '') if tree: self._extractInfo(tree) return def getName(self): "Return this info object's name." return self._name def getSymbolInfo(self, name, tryParent=1): """Look up the info record for the name. Looks in the namespaces registered for this DOM node. If no value is found, 'None' is returned. """ for ns in self._namespaces: info = ns.get(name, None) if info: return info if tryParent and self.getParent(): return self.getParent().getSymbolInfo(name, tryParent) return None def __getitem__(self, itemName): info = self.getSymbolInfo(itemName) if not info: raise KeyError('Unrecognized name: "%s"' % itemName, itemName) return info def getFilename(self): return self._filename def getCommentKey(self): if self._parent: return self._parent.getCommentKey() + (self._name,) else: return (self._name,) ## ## Internal Data Extraction ## def getConfigurationValues(self): "Return any HappyDoc configuration values related to this object." values = None if self._parent: try: values = self._parent.getConfigurationValues() except: values = None if values is None: values = self._configuration_values return values def _extractInfo(self, tree): "Pull information out of the parse tree." from happydoclib.parseinfo.classinfo import ClassInfo from happydoclib.parseinfo.functioninfo import FunctionInfo # extract docstring if len(tree) == 2: found, vars = match(DOCSTRING_STMT_PATTERN[1], tree[1]) else: found, vars = match(DOCSTRING_STMT_PATTERN, tree[3]) if found: self._docstring = eval(vars['docstring']) else: self._docstring = '' # discover inner definitions for node in tree[1:]: found, vars = match(COMPOUND_STMT_PATTERN, node) if found: cstmt = vars['compound'] if cstmt[0] == symbol.funcdef: name = cstmt[2][1] self._function_info[name] = FunctionInfo( tree=cstmt, parent=self, commentInfo=self._comment_info, ) #pprint.pprint(cstmt) elif cstmt[0] == symbol.classdef: name = cstmt[2][1] self._class_info[name] = ClassInfo( tree=cstmt, parent=self, commentInfo=self._comment_info, ) return def _extractConfigurationValues(self): "Default implementation does nothing." return _summary_pattern = re.compile(r'^\s*([^\n]+)\n') def _extractSummary(self, text): "Extract a summary text from a larger body." text = text.strip() # # Remove surrounding quotes, if present. # while text and (text[0] in ('"', "'")): text = text[1:] while text and (text[-1] in ('"', "'")): text = text[:-1] # # Pull out the first line, and return it if # we can find it. Otherwise, return the whole # string since that means that the whole thing # is just one line. # matchObj = self._summary_pattern.search(text) if matchObj: return matchObj.group(0).strip() else: return text ## ## DocStrings ## def getDocString(self): "Return any __doc__ string value found for the object." dstring = '%s\n\n%s' % (self._docstring, self._comments) #print 'DOC STRING for %s is ' % self._name, dstring return dstring def getDocStringFormat(self): "Returns the docstring converter format name for the docstring for this object." config_values = self.getConfigurationValues() return config_values['docStringFormat'] def getSummaryAndFormat(self): "Return a summary of the __doc__ string for this object and the docstring converter name for the format of the text." if self._docstring_summary is None: self._docstring_summary = \ self._extractSummary(self.getDocString()) return self._docstring_summary, self.getDocStringFormat() --- NEW FILE: parsecomments.py --- #!/usr/bin/env python # # $Id: parsecomments.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $ # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # """Parse comment information from a module. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: parsecomments.py,v $', 'rcs_id' : '$Id: parsecomments.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $', 'creator' : 'Doug Hellmann <do...@he...>', 'project' : 'UNSPECIFIED', 'created' : 'Sat, 27-Oct-2001 17:49:02 EDT', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 15:05:43 $', } try: __version__ = __rcs_info__['version'].split(' ')[1] except: __version__ = '0.0' # # Import system modules # import re try: from cStringIO import StringIO except: from StringIO import StringIO import unittest # # Import Local modules # # # Module # class ParseStack: "Helper class for 'extractComments' function in this module." def __init__(self): "Create a ParseStack." self.data = [] return def push(self, name, indent): """Push a new 'name' onto the stack. Smartly determine, based on 'indent', whether to 'pop' other 'names' before pushing this one. """ while self.data and (indent <= self.data[-1][1]): self.pop() self.data.append( (name, indent) ) return def pop(self): "Remove the top of the stack and return it." item, indent = self.data[-1] self.data = self.data[:-1] return item def __names(self): "Return a list of the names as they appear on the stack, bottom first." return map(lambda x: x[0], self.data) def __str__(self): "Create a string representation." return string.join(self.__names(), ':') def key(self): "Return a value to be used as a dictionary key." return tuple(self.__names()) def extractComments( text, extractRe=re.compile('^((?P<blankline>\s*$)|(?P<namedobj>(?P<indent>\s*)(?P<nametype>(class|def))\s+(?P<name>[0-9A-Za-z_]+))|(?P<commentline>\s*#+(?P<comment>.*)))').search, ignoreRe=re.compile('\s*[+-=#][ +-=#]*\s*$').match, ): """Given a block of Python source, extract the comments. The comment text is associated with nearby named objects (functions, methods, classes, etc.). This function returns a dictionary of names and the associated comment text. Arguments text -- The Python source to be scanned. """ dbg=None comment_info = {} comment_text = '' parse_stack = ParseStack() current_name = None f = StringIO(text) line = f.readline() while line: #if dbg and (dbg >= 2): print '=>%s' % string.rstrip(line) match_obj = extractRe(line) if match_obj: # # Documentation before named object # match_dict = match_obj.groupdict() comment = match_dict['comment'] name = match_dict['name'] nametype = match_dict['nametype'] blankline = match_dict['blankline'] indent = ((match_dict['indent'] and len(match_dict['indent'])) or 0) if match_dict['commentline'] and not comment: comment = ' ' if comment: # Append new text to running buffer. if ignoreRe and not ignoreRe(comment): #if dbg: print 'PARSEINFO: Adding comment text.' comment_text = '%s%s\n' % (comment_text, comment,) elif name and comment_text: if current_name: # Hit a new name, store the comment_text buffer # for the current_name #if dbg: # print 'PARSEINFO: 1 Storing comment for %s' % parse_stack # print 'PARSEINFO: ', comment_text comment_info[parse_stack.key()] = comment_text # Update the parse stack parse_stack.push(name, indent) #if dbg: # print 'PARSEINFO: switching to %s' % parse_stack comment_text = '' else: # Hit a new name with existing comment_text, # store the comment along with that name. parse_stack.push(name, indent) #if dbg: # print 'PARSEINFO: 2 Storing comment for %s' % parse_stack # print 'PARSEINFO: ', comment_text comment_info[parse_stack.key()] = comment_text comment_text = '' current_name = None elif name: # Recognized new name definition. #if dbg: # print 'PARSEINFO: New name %d:%s:%s' % (indent, # nametype, # name, # ) current_name = name parse_stack.push(name, indent) elif blankline: # Reset when a blank line separates comment from # named stuff. #if dbg: # print 'PARSEINFO: blank line' if comment_text and current_name: if not comment_info.get(parse_stack, None): #if dbg: # print 'PARSEINFO: Storing comment after name %s:%s' \ # % parse_stack comment_info[parse_stack.key()] = comment_text #else: # if dbg: # if comment_text: # print 'PARSEINFO: Discarding comment "%s"' % comment_text current_name = None comment_text = '' elif current_name and comment_text: # Store all comment text for the current_name. #if dbg: # print 'PARSEINFO: 3 Storing comment for %s' % current_name # print 'PARSEINFO: ', comment_text comment_info[parse_stack.key()] = comment_text comment_text = '' current_name = None else: #if dbg: # print 'PARSEINFO: Not matched (%s)' % string.strip(line) current_name = None comment_text = '' line = f.readline() f.close() if current_name and comment_text: # Final storage to make sure we have everything. #if dbg: # print 'PARSEINFO: Final storage of comment for %s' % current_name comment_info[parse_stack.key()] = comment_text #if dbg: # pprint.pprint(comment_info) return comment_info class ParseCommentsTest(unittest.TestCase): def testComments(self): body = open('TestCases/parseinfo/test_ignore_comments.py', 'rt').read() actual = extractComments(body) expected = { ('WithComments',): ' \n This class is documented only with comments.\n \n Any documentation which appears for this class with the\n comment flag set to ignore comments indicates a bug.\n \n', ('WithComments', '__init__'): ' \n WithComments init method.\n \n You should not see this!\n \n', } assert actual == expected, \ 'Did not get expected comment values. Got %s' % str(actual) def testDecoratedComments(self): body = open('TestCases/parseinfo/test_decorated_comments.py', 'rt').read() actual = extractComments(body) expected = { ('Dashes',): ' \n Func with dash lines\n \n', ('Equals',): ' \n Func with equal lines\n \n', ('Hashes',): ' \n \n Func with hash lines\n \n \n', ('StructuredTextTable',): " \n This function has, in the comments about it, a table. That table\n should be rendered via STNG to an HTML table in the test output.\n \n |-------------------------------------------------|\n | Function | Documentation |\n |=================================================|\n | '__str__' | This method converts the |\n | | the object to a string. |\n | | |\n | | - Blah |\n | | |\n | | - Blaf |\n | | |\n | | |--------------------------| |\n | | | Name | Favorite | |\n | | | | Color | |\n | | |==========================| |\n | | | Jim | Red | |\n | | |--------------------------| |\n | | | John | Blue | |\n | | |--------------------------| |\n |-------------------------------------------------|\n \n", ('Mixed',): ' \n Func with mixed dashes and equals\n \n', } assert actual == expected, \ 'Did not get expected comment values. Got %s' % str(actual) --- NEW FILE: moduleinfo.py --- #!/usr/bin/env python # # $Id: moduleinfo.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $ # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # """Information gatherer for source code modules. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: moduleinfo.py,v $', 'rcs_id' : '$Id: moduleinfo.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $', 'creator' : 'Doug Hellmann <do...@he...>', 'project' : 'UNSPECIFIED', 'created' : 'Sun, 11-Nov-2001 10:52:52 EST', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 15:05:43 $', } try: __version__ = __rcs_info__['version'].split(' ')[1] except: __version__ = '0.0' # # Import system modules # import pprint import re import string import sys import traceback import urllib # # Import Local modules # import happydoclib from happydoclib.parseinfo.classinfo import ClassInfo from happydoclib.parseinfo.functioninfo import SuiteFuncInfo, FunctionInfo from happydoclib.parseinfo.suite import SuiteInfoBase from happydoclib.parseinfo.imports import ImportInfo from happydoclib.parseinfo.utils import * # # Module # class ModuleInfo(SuiteInfoBase, SuiteFuncInfo): """Information gatherer for source code modules. Extract information about a source module from its parse tree. """ def __init__(self, parent, tree, name = "<string>", fileName = None, commentInfo = {}, defaultConfigValues={}, ): """Initialize the info extractor. Parameters: tree -- parse tree from which to extract information name -- name of the module fileName -- name of the file containing the module commentInfo -- comments extracted from the file """ happydoclib.TRACE.into('ModuleInfo', '__init__', parent=parent, tree=tree, name=name, fileName=fileName, commentInfo=commentInfo, defaultConfigValues=defaultConfigValues, ) self._filename = fileName SuiteInfoBase.__init__(self, name, parent, fileName, tree, commentInfo=commentInfo, defaultConfigValues=defaultConfigValues) if tree: # # Look for doc string # found, vars = match(DOCSTRING_STMT_PATTERN, tree[1]) if found: self._docstring = vars["docstring"] # # Look for imported modules # self._import_info = self._extractImportedModules(tree) happydoclib.TRACE.outof() return ## ## Internal data extraction ## def _extractConfigurationValues( self, matchConfigValue=re.compile('^#\s*HappyDoc:(.+)$', re.IGNORECASE).match, ): """Look into the module source file and extract HappyDoc configuration values. Variables can be embedded in the first comment block of the module. """ body = open(self._filename, 'rt').read() lines = body.split('\n') config_statement = '' for l in lines: l = l.strip() if not l: break if l[0] != '#': break match = matchConfigValue(l) if match: config_statement = '%s\n%s' % (config_statement, match.group(1)) # # Exec puts in values from the builtin modules to set up the # namespace. That means we don't want to use our # configuration value table for global and local names, so we # create (and use) a dummy table here. We can pre-populate # it with a few modules we think the user should be allowed # to call. # global_namespace = { 'string':string, 'urlquote':urllib.quote, 'urlquote_plus':urllib.quote_plus, 'urlencode':urllib.urlencode, } local_namespace = { } try: exec config_statement in global_namespace, local_namespace except: sys.stderr.write('\n--- Parser Config Value Extraction Error ---\n') traceback.print_exc() sys.stderr.write('--------------------------------------------\n\n') else: self._configuration_values.update(local_namespace) return def _extractImportedModules(self, tree): """Returns modules imported by code in tree. Scan the parse tree for import statements and return the names of all modules imported. """ dbg=0 IMPORT_STMT_WITH_LIST_PATTERN =( symbol.stmt, (symbol.simple_stmt, (symbol.small_stmt, ['import_stmt'] ), (token.NEWLINE, '') ) ) imported_modules = ImportInfo() for subtree in tree[1:]: #if dbg: print '\nNEW IMPORT SUBTREE' found, vars = match(IMPORT_STMT_WITH_LIST_PATTERN, subtree, dbg=dbg) #if dbg: # print 'found:', found # if found: # print 'vars: ', # pprint.pprint(vars) if found: # vars['import_stmt'] should be an import statement # in one of several different forms import_stmt = vars['import_stmt'] if import_stmt[0] == symbol.import_stmt: first = import_stmt[1] if (first[0] == token.NAME) and (first[1] == 'import'): for import_module in import_stmt[2:]: try: if import_module[0] == symbol.dotted_as_name: #if dbg: print 'Collapsing dotted_as_name' import_module = import_module[1] except AttributeError: # # Must be using python < 2.0 # pass if import_module[0] == symbol.dotted_name: # Get the tuples with the name module_name_parts = import_module[1:] # Get the strings in the 2nd part of each tuple module_name_parts = map(lambda x: x[1], module_name_parts) # Combine the strings into the name module_name = ''.join(module_name_parts) #if dbg: print 'ADDING module_name=%s' % module_name imported_modules.addImport(module_name) elif (first[0] == token.NAME) and (first[1] == 'from'): #if dbg: print 'FROM ', import_stmt x=import_stmt[2] try: if x[0] == symbol.dotted_name: x = x[1:] except AttributeError: # # Must be using python < 2.0 # pass #if dbg: print 'from x import y' module_name = parseTreeToString(x) try: symbol_list = imported_modules.importedSymbols(module_name) except ValueError: symbol_list = [] names = import_stmt[4:] #if dbg: print 'NAMES: ', names for n in names: if n[0] == token.NAME: #symbol_list.append(n[1]) imported_modules.addImport(module_name, n[1]) elif n[0] == token.STAR: #symbol_list.append('*') imported_modules.addImport(module_name, '*') elif n[0] == getattr(symbol, 'import_as_name', 9999): # python 2.x "from X import Y as Z" feature import_name = parseTreeToString(n[1]) imported_modules.addImport(module_name, import_name) #if dbg: # for part in import_stmt[1:]: # pprint.pprint(part) #if dbg: print 'ITERATION IMPORTS: ', imported_modules #if dbg: print 'FINAL IMPORTS: ', imported_modules, '\n' return imported_modules ## ## ## def getClassNames(self): "Return the names of classes defined within the module." return self._class_info.keys() def getClassInfo(self, name): "Return a ClassInfo object for the class by name." return self._class_info[name] def getCommentKey(self): return () def getImportData(self): "Returns a list of which symbols are imported." return self._import_info.items() # def getReference(self, formatter, sourceNode): # "Return a reference to this module from sourceNode." # ref = formatter.getReference(self, sourceNode.name) # return ref def getReferenceTargetName(self): "Return the name to use as a target for a reference such as a hyperlink." #print 'PARSINFO: ModuleInfo::getReferenceTargetName(%s)' % self.getName() target_name = self.getName() if target_name == '__init__': #print 'PARSINFO: \tasking for parent' parent = self.getParent() if parent: #print 'PARSINFO: \tusing parent' target_name = parent.getReferenceTargetName() else: #print 'PARSINFO: \tusing name' target_name = self.getName() #print 'PARSINFO: \ttarget:%s' % target_name return target_name --- NEW FILE: imports.py --- #!/usr/bin/env python # # $Id: imports.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $ # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # """Collects info about imports for a module. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: imports.py,v $', 'rcs_id' : '$Id: imports.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $', 'creator' : 'Doug Hellmann <do...@he...>', 'project' : 'UNSPECIFIED', 'created' : 'Sun, 11-Nov-2001 10:51:52 EST', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 15:05:43 $', } try: __version__ = __rcs_info__['version'].split(' ')[1] except: __version__ = '0.0' # # Import system modules # # # Import Local modules # # # Module # class ImportInfo: """Collects info about imports for a module. """ def __init__(self): self._straight_imports = [] self._named_imports = {} return def addImport(self, moduleName, symbolName=None, asName=None): """Add information about an import statement to the saved info. Parameters moduleName -- The name of the module involved in the import. For example, in 'from X import Y', X is the moduleName and in 'import A.B', A.B is the moduleName. symbolName -- The name of the symbol being imported. For example, in 'from X import Y', Y is the symbolName. asName -- The name within the module by which symbolName can be referenced. Usually, this is the same as symbolName, but by using the 'import X as Y' syntax, the name can be changed. """ dbg=0 if symbolName: #if dbg: print '\nIMPORT SYMBOL %s from MODULE %s' % (symbolName, moduleName) name_list = self._named_imports.get(moduleName, []) if symbolName not in name_list: #if dbg: print '\t*** added' name_list.append(symbolName) self._named_imports[moduleName] = name_list else: #if dbg: print '\nIMPORT MODULE: %s' % moduleName if moduleName not in self._straight_imports: #if dbg: print '\t*** added' self._straight_imports.append(moduleName) #if dbg: # print 'STRAIGHT: ', # pprint.pprint(self._straight_imports) # print 'NAMED: ', # pprint.pprint(self._named_imports) # print 'CURRENT IMPORTS: ', self.items() return def importedSymbols(self, moduleName): if self._named_imports.has_key(moduleName): return self._named_imports[moduleName] else: raise ValueError('No symbols imported for module', moduleName) return def __str__(self): return '(%s)' % string.join( map(str, self.items()), '\n' ) def items(self): """Returns a sequence of tuples containing module names and the symbols imported from them. """ all_names = self._straight_imports[:] for name in self._named_imports.keys(): if name not in all_names: all_names.append(name) all_names.sort() all_items = [] for name in all_names: if name in self._straight_imports: all_items.append( (name, None) ) if self._named_imports.has_key(name): all_items.append( (name, self._named_imports[name]) ) return all_items --- NEW FILE: functioninfo.py --- #!/usr/bin/env python # # $Id: functioninfo.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $ # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # """Gather information about a function or method definition. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: functioninfo.py,v $', 'rcs_id' : '$Id: functioninfo.py,v 1.1 2002/11/17 15:05:43 doughellmann Exp $', 'creator' : 'Doug Hellmann <do...@he...>', 'project' : 'UNSPECIFIED', 'created' : 'Sun, 11-Nov-2001 10:54:53 EST', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 15:05:43 $', } try: __version__ = __rcs_info__['version'].split(' ')[1] except: __version__ = '0.0' # # Import system modules # import symbol import token # # Import Local modules # import happydoclib from happydoclib.parseinfo.suite import SuiteInfoBase from happydoclib.parseinfo.utils import * # # Module # class SuiteFuncInfo: # Mixin class providing access to function names and info. def getFunctionNames(self): return self._function_info.keys() def getFunctionInfo(self, name): return self._function_info[name] class FunctionInfo(SuiteInfoBase, SuiteFuncInfo): "Gather information about a function or method definition." def __init__(self, parent=None, tree = None, commentInfo={}): """Initialize the info extractor. Parameters: parent -- parent object for this object (e.g. Module or Function) tree -- parse tree from which to extract information commentInfo -- comments extracted from the source file holding this module """ happydoclib.TRACE.into('FunctionInfo', '__init__', parent=parent, tree=tree, commentInfo=commentInfo, ) SuiteInfoBase.__init__(self, tree[2][1], parent, parent.getFilename(), (tree and tree[-1] or None), commentInfo=commentInfo) parameter_data = self._extractFunctionParameters(tree) self._constructParameterInfo(parameter_data) self._exception_info = self._extractThrownExceptions(tree) #if self._exception_info: # print 'EXCEPTIONS: ', # pprint.pprint(self._exception_info) happydoclib.TRACE.outof() return def getReference(self, formatter, sourceNode): "Return a reference to this function from sourceNode." ref = formatter.getNamedReference( self, self.getName(), sourceNode.name ) return ref def getFullyQualifiedName(self): "Return a complete, unique, name representing this object." return self.getParent().getFullyQualifiedName() ## ## EXCEPTIONS ## EXCEPTION_BY_NAME_PATTERN = ( (symbol.factor, ['exception']) ) EXCEPTION_STRING_PATTERN = ( (symbol.factor, (symbol.power, (symbol.atom, (token.STRING, ['exception']) ))) ) def getExceptionNames(self): "Return a list of the names of any exceptions raised by the function." return self._exception_info.keys() def getExceptionInfo(self, exceptionName): """Returns a type value for an exception. The return value will be one of (token.NAME, token.STRING) indicating whether the exception was thrown as a string or a named object. """ return self._exception_info[exceptionName] def _extractThrownExceptions(self, tree): "Return a dictionary of exception->exception_type values." #dbg = 0 thrown_exceptions = {} if not tree: return thrown_exceptions if type(tree) in (types.ListType, types.TupleType): raise_tree_list = findNode(tree, symbol.raise_stmt) for tree in raise_tree_list: try: subtree = drill(tree[2], 10) except IndexError: subtree = tree #if dbg: print 'subtree: ', parseTreeToString(subtree) #if dbg: print 'found raise: ', parseTreeToString(tree) #if dbg: print 'parsing...' # # Initialize # exception_name = None exception_type = None if not exception_name: found, vars = lenientMatch( self.EXCEPTION_STRING_PATTERN, tree, #dbg=1 ) if found and vars.has_key('exception'): #if dbg: print 'FOUND STRING EXCEPTION: ', vars exception_name = vars['exception'] exception_type = token.STRING #if dbg: print 'GOT EXCEPTION: ', exception_name if not exception_name: found, vars = lenientMatch( self.EXCEPTION_BY_NAME_PATTERN, tree, #dbg=1 ) if found and vars.has_key('exception'): #if dbg: print 'FOUND NAMED EXCEPTION: ', vars # Threw a named thing, record the name. exception_name = parseTreeToString(vars['exception']) exception_type = token.NAME #if dbg: print 'GOT EXCEPTION: ', exception_name if not exception_name: #if dbg: print 'NO NAME,', if len(tree) >= 3: slice=tree[2:] if slice: #if dbg: print 'using slice of 2:1=', slice exception_name = parseTreeToString(slice) else: #if dbg: print 'using whole tree=', tree execption_name = parseTreeToString(tree) if exception_name: #if dbg: print 'STORING REFERENCE' thrown_exceptions[exception_name] = exception_type #if dbg and thrown_exceptions: print 'EXCEPTIONS: ', thrown_exceptions.keys() return thrown_exceptions ## ## PARAMETERS ## # This pattern matches the name of an item which appears in a # testlist sequence. This can be used for finding the # base classes of a class, or the parameters to a function or # method. # PARAMETER_DEFAULT_PATTERN = ( symbol.test, (symbol.and_test, (symbol.not_test, (symbol.comparison, (symbol.expr, (symbol.xor_expr, (symbol.and_expr, (symbol.shift_expr, (symbol.arith_expr, ['term'], ['trailer'], ['trailer_bits']) )))))))) oldPARAMETER_DEFAULT_PATTERN = ( symbol.test, (symbol.and_test, (symbol.not_test, (symbol.comparison, (symbol.expr, (symbol.xor_expr, (symbol.and_expr, (symbol.shift_expr, (symbol.arith_expr, (symbol.term, (symbol.factor, (symbol.power, ['atom']) ))))))))))) PARAMETER_DEFAULT_WITH_TRAILER_PATTERN = ( symbol.test, (symbol.and_test, (symbol.not_test, (symbol.comparison, (symbol.expr, (symbol.xor_expr, (symbol.and_expr, (symbol.shift_expr, (symbol.arith_expr, (symbol.term, (symbol.factor, (symbol.power, ['atom'], ['trailer'], ['trailer_bits']) )))))))))) ) PARAMETER_ARITH_DEFAULT_WITH_TRAILER_PATTERN = ( symbol.test, (symbol.and_test, (symbol.not_test, (symbol.comparison, (symbol.expr, (symbol.xor_expr, (symbol.and_expr, (symbol.shift_expr, (symbol.arith_expr, #(symbol.term, # (symbol.factor, # (symbol.power, ['atom'], ['trailer'], ['trailer_bits']) # )) ['expression'], ['trailer'], ['trailer_bits'] )))))))) ) def _constructParameterInfo(self, parameterData): """Construct storable parameter data from a parameter list. Given the sequence of tuples extracted as a parameter list, store the names (in order) in self._parameter_names and the information about the parameter in self._parameter_info where the keys are the parameter name and the info is a tuple containing: (default_specified, default_value, default_value_type) Where: default_specified -- boolean indicating whether a default value was specified default_value -- the default value given, if any default_value_type -- the type of the default value (token.STRING, token.NAME, None). A type of None means unknown. """ parameter_info = {} parameter_names = [] for (param, default_specified, default_value, default_value_type) in parameterData: parameter_names.append(param) parameter_info[param] = ( default_specified, default_value, default_value_type, ) self._parameter_names = tuple(parameter_names) self._parameter_info = parameter_info return def getParameterNames(self): """Returns a list of the names of all parameters to the function, in order.""" return self._parameter_names def getParameterInfo(self, paramName): """Returns the info record for a parameter. The returned tuple consists of: (default_specified, default_value, default_value_type) Where: default_specified -- boolean indicating whether a default value was specified default_value -- the default value given, if any default_value_type -- the type of the default value (token.STRING, token.NAME, None). A type of None means unknown. """ return self._parameter_info[paramName] def _extractFunctionParameters(self, tree): "Extract information about a function's parameters." dbg=0 #if dbg: print #if dbg: print self._name function_parameters = [] parameters = tree[3] #if dbg: pprint.pprint(parameters) if parameters[1][0] != token.LPAR: raise 'Unrecognized parse result %s in %s' % (parameters[1], parameters) if parameters[2][0] == token.RPAR: # No parameters: def func() return function_parameters if parameters[2][0] != symbol.varargslist: raise 'Unrecognized parse result %s in %s' % (parameters[2], parameters) # # Move down the parse tree and process the argument list # parameters = parameters[2] #if dbg: pprint.pprint(parameters) found_varargs = 0 # are we looking at a variable argument parameter? found_kwargs = 0 # are we looking at keyword argument parameter? name = None # what is the name of the parameter? found_default_value = None # did we see a default value for the param? default_value = None # what is the default value? default_value_type = None # what is the type of the default value? for parameter in parameters[1:]: # Shortcut cases if parameter[0] == token.COMMA: continue if parameter[0] == token.STAR: # Start variable argument definition found_varargs = 1 if parameter[0] == token.DOUBLESTAR: # Start keyword argument definition found_kwargs = 1 if (parameter[0] in (token.NAME, symbol.fpdef)) and name: # We've already found a name, # handle adding the previous # def to a list. function_parameters.append( (name, ... [truncated message content] |
From: Doug H. <dou...@us...> - 2002-11-17 15:04:21
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib/docstring In directory usw-pr-cvs1:/tmp/cvs-serv3832/happydoclib/docstring Modified Files: docstring_ClassicStructuredText.py Log Message: Fix up test case directory name. Index: docstring_ClassicStructuredText.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/docstring/docstring_ClassicStructuredText.py,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** docstring_ClassicStructuredText.py 17 Nov 2002 00:26:19 -0000 1.1.1.1 --- docstring_ClassicStructuredText.py 17 Nov 2002 15:04:17 -0000 1.2 *************** *** 355,359 **** def testClassicStructuredTextConversion(self): ! filename = 'TestCases/test_classic_structuredtext.py' import happydoclib.parseinfo parsed_module = happydoclib.parseinfo.getDocs(None, filename) --- 355,359 ---- def testClassicStructuredTextConversion(self): ! filename = 'TestCases/docstring/test_classic_structuredtext.py' import happydoclib.parseinfo parsed_module = happydoclib.parseinfo.getDocs(None, filename) |
From: Doug H. <dou...@us...> - 2002-11-17 15:02:14
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib In directory usw-pr-cvs1:/tmp/cvs-serv3210/happydoclib Modified Files: test_scanner.py Log Message: Rename TestCase directory to TestCases. Index: test_scanner.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/test_scanner.py,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** test_scanner.py 17 Nov 2002 00:26:19 -0000 1.1.1.1 --- test_scanner.py 17 Nov 2002 15:02:11 -0000 1.2 *************** *** 81,85 **** def testScannerNoSuchDir(self): try: ! scanner = Scanner(['TestCase/testScannerNotThere']) except ValueError: pass --- 81,85 ---- def testScannerNoSuchDir(self): try: ! scanner = Scanner(['TestCases/testScannerNotThere']) except ValueError: pass *************** *** 89,93 **** def testScannerOnTestCase(self): ! scanner = Scanner(['TestCase/testScanner']) trees = scanner.getPackageTrees() --- 89,93 ---- def testScannerOnTestCase(self): ! scanner = Scanner(['TestCases/testScanner']) trees = scanner.getPackageTrees() *************** *** 149,153 **** def testPackageTreePath(self): ! scanner = Scanner(['TestCase/testScanner']) trees = scanner.getPackageTrees() --- 149,153 ---- def testPackageTreePath(self): ! scanner = Scanner(['TestCases/testScanner']) trees = scanner.getPackageTrees() *************** *** 167,171 **** def testPackageTreeIgnore(self): ! scanner = Scanner(['TestCase/testScanner'], ['ignoreme.py']) trees = scanner.getPackageTrees() --- 167,171 ---- def testPackageTreeIgnore(self): ! scanner = Scanner(['TestCases/testScanner'], ['ignoreme.py']) trees = scanner.getPackageTrees() |
From: Doug H. <dou...@us...> - 2002-11-17 15:01:53
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib In directory usw-pr-cvs1:/tmp/cvs-serv3045/happydoclib Modified Files: scanner.py Log Message: Fix up tests to work with Proctor instead of using StreamFlushTest. Index: scanner.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/scanner.py,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** scanner.py 17 Nov 2002 00:26:19 -0000 1.1.1.1 --- scanner.py 17 Nov 2002 15:01:50 -0000 1.2 *************** *** 65,69 **** # Import Local modules # ! from trace import trace # --- 65,69 ---- # Import Local modules # ! from happydoclib.trace import trace # |
From: Doug H. <dou...@us...> - 2002-11-17 15:01:39
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib In directory usw-pr-cvs1:/tmp/cvs-serv2962/happydoclib Modified Files: happydocstring.py Log Message: Fix up tests to work with Proctor instead of using StreamFlushTest. Index: happydocstring.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/happydocstring.py,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** happydocstring.py 17 Nov 2002 00:26:19 -0000 1.1.1.1 --- happydocstring.py 17 Nov 2002 15:01:36 -0000 1.2 *************** *** 184,189 **** class DocStringConverterTest(unittest.TestCase): ! def __init__(self, methodName, outputDir=''): ! import happydoclib.docstring self._hddocstring = happydoclib.docstring --- 184,188 ---- class DocStringConverterTest(unittest.TestCase): ! def setUp(self): import happydoclib.docstring self._hddocstring = happydoclib.docstring *************** *** 216,224 **** if debug: print '\n[[%s]]' % converted_text ! if converted_text != expectedText: ! print '[INPUT[%s]INPUT]' % inputText ! print '[EXPECTED[%s]EXPECTED]' % expectedText ! print '[CONVERTED[%s]CONVERTED]' % converted_text ! self._compareText(expectedText, converted_text) return --- 215,226 ---- if debug: print '\n[[%s]]' % converted_text ! try: ! self._compareText(expectedText, converted_text) ! except AssertionError, msg: ! import sys ! sys.stderr.write('[INPUT[%s]INPUT]\n' % inputText) ! sys.stderr.write('[EXPECTED[%s]EXPECTED]\n' % expectedText) ! sys.stderr.write('[CONVERTED[%s]CONVERTED]\n' % converted_text) ! raise return |
From: Doug H. <dou...@us...> - 2002-11-17 14:59:12
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib In directory usw-pr-cvs1:/tmp/cvs-serv2208/happydoclib Modified Files: appclass.py Log Message: Reworking to use the new scanner module. Index: appclass.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/appclass.py,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** appclass.py 17 Nov 2002 00:26:19 -0000 1.1.1.1 --- appclass.py 17 Nov 2002 14:59:08 -0000 1.2 *************** *** 60,64 **** import string import re - import parser import traceback --- 60,63 ---- *************** *** 141,161 **** return - def ignoreDirectoryTest(self, dirName): - """Determines whether 'dirName' matches pattern to be ignored. - - Arguments - - 'dirName' -- Full path of the directory to be tested. - - Returns true value if 'dirName' should be ignored, false value - otherwise. - - """ - dir_base = happydoclib.path.basename(dirName) - if dir_base in self._ignore_dir_patterns: - return 1 - else: - return 0 - def set_format(self, format): "Set the formatter to be used." --- 140,143 ---- *************** *** 327,330 **** --- 309,324 ---- ## + def scanForInput(self, inputModules): + scanner = Scanner(inputModules, self._ignore_dir_patterns) + return scanner + + def parseInputs(self, scanner): + package_trees = scanner.getPackageTrees() + + for package_tree in package_trees: + pass + + return + def main(self, *args): *************** *** 349,361 **** # Create the scanner, and get the package trees. # ! scanner = Scanner(input_modules, self._ignore_dir_patterns) package_trees = scanner.getPackageTrees() - for package_tree in package_trees: - package_tree.walk(self.showPackageTree) return ! def showPackageTree(self, packageTreeNode): path = packageTreeNode.getPath() indent = ' ' * len(path) --- 343,359 ---- # Create the scanner, and get the package trees. # ! scanner = self.scanForInput(input_modules) ! self.showPackageTree(scanner) ! ! return + def showPackageTree(self, scanner): package_trees = scanner.getPackageTrees() + for package_tree in package_trees: + package_tree.walk(self.showPackageTreeCB) return ! def showPackageTreeCB(self, packageTreeNode): path = packageTreeNode.getPath() indent = ' ' * len(path) |
From: Doug H. <dou...@us...> - 2002-11-17 14:58:40
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib In directory usw-pr-cvs1:/tmp/cvs-serv1995/happydoclib Modified Files: __init__.py Log Message: Set locale. Bring in parseinfo package. Index: __init__.py =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/__init__.py,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** __init__.py 17 Nov 2002 00:26:14 -0000 1.1.1.1 --- __init__.py 17 Nov 2002 14:58:37 -0000 1.2 *************** *** 57,60 **** --- 57,62 ---- # Import system modules # + import locale + locale.setlocale(locale.LC_ALL, '') *************** *** 67,71 **** #import happydoclib.path import happydoclib.optiontools ! #import happydoclib.parseinfo import happydoclib.pluginloader #import happydoclib.prettyast --- 69,73 ---- #import happydoclib.path import happydoclib.optiontools ! import happydoclib.parseinfo import happydoclib.pluginloader #import happydoclib.prettyast |
From: Doug H. <dou...@us...> - 2002-11-17 14:58:17
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib/docstring In directory usw-pr-cvs1:/tmp/cvs-serv1835/happydoclib/docstring Added Files: .proctor Log Message: Proctor test configuration file. --- NEW FILE: .proctor --- # # Local variables: # mode: python # end: # # $Id: .proctor,v 1.1 2002/11/17 14:58:13 doughellmann Exp $ # """Proctor instruction file. """ ignore = [ 'StructuredText', ] |
From: Doug H. <dou...@us...> - 2002-11-17 14:57:24
|
Update of /cvsroot/happydoc/HappyDoc3/happydoclib/parseinfo In directory usw-pr-cvs1:/tmp/cvs-serv1559/happydoclib/parseinfo Log Message: Directory /cvsroot/happydoc/HappyDoc3/happydoclib/parseinfo added to the repository |
From: Doug H. <dou...@us...> - 2002-11-17 14:51:47
|
Update of /cvsroot/happydoc/HappyDoc3/TestCases/parseinfo In directory usw-pr-cvs1:/tmp/cvs-serv32400/TestCases/parseinfo Added Files: __init__.py emptytest.py test_bug434946.py test_decorated_comments.py test_function_params.py test_ignore_comments.py test_import_statements.py test_nested_structures.py test_variable_extraction.py test_variable_extraction_with_exception.py Log Message: Add test files. --- NEW FILE: __init__.py --- --- NEW FILE: emptytest.py --- #!/usr/bin/env python # # Time-stamp: <00/07/04 13:26:04 dhellmann> # # COPYRIGHT: # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # """Empty test file. No classes or functions defined. """ __rcs_info__ = { # # Creation Information # 'module_name':'$RCSfile: emptytest.py,v $', 'creator':'Doug Hellmann <do...@he...>', 'project':'HappyDoc', 'created':'Sun, 21-May-2000 15:44:37 EDT', # # Current Information # 'author':'$Author: doughellmann $', 'version':'$Revision: 1.1 $', 'date':'$Date: 2002/11/17 14:51:44 $', 'locker':'$Locker: $', } # # Import system modules # # # Import Local modules # # # Module # --- NEW FILE: test_bug434946.py --- #!/usr/bin/python # """Carriage-returns in input text. This file includes carriage returns with each newline for each line. $Id: test_bug434946.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $ """ import string import CommandLineApp import os, types import one.two from sys import path from token import * from a.b import c, d from CommandLineApp import TestApp class DefaultClassInst: "Class used for default parameter with a class instance." pass class DefaultClassInstWithParams: "Class used for default parameter with a class instance taking parameters." def __init__(self, *args): "Initialize DefaultClassInstWithParams instance." pass class DottedBaseClass(A.B): "Class to test subclassing from a base class with dots in the name." pass class MultipleBaseClasses(DefaultClassInst, DefaultClassInstWithParams, CommandLineApp.CommandLineApp): "Class testing multiple inheritence." pass # Here is a module level variable definition. foo=1 def example_function_with_args(arg1, arg2, arg3withDefault='hi there', arg3aWithDefault="'hi again'", arg3bWithDefault='"hi there again"', arg4DefaultInt=101, arg5DefaultTuple=(1,2), arg6DefaultList=[3,4], arg7DefaultNone=None, arg8DefaultName=foo, arg9DefaultInstance=DefaultClassInst(), arg10DefaultInstanceWithParams= \ DefaultClassInstWithParams(1, 2, ('tuple', 'param'), ['list', 'param'] ), stringArgWithHTML='<h1>Hi, Dick & Jane!</h1>', ): "This is an example function for testing purposes." if one: raise IOError('RAISE_class') else: raise 'RAISE_blah2' for i in range(1, 10): raise 'RAISE_loop' raise 'RAISE_main_level' return None def example_function_without_args(): "This example function has no arguments." pass def example_function_with_varargs(*args): "This example function takes a variable number of arguments." pass def example_function_with_kwargs(**kw): """ This example function takes variable keyword arguments. """ pass class BaseClass1: "First base class." # # classMember definition example # classMember=1 # # Documentation for method_of_bc1 # def method_of_bc1(self): pass def method2_of_bc1(self): # # Documentation for method2_of_bc1 after name # pass class SubClass1(BaseClass1): "First subclass of BaseClass1." pass class BaseClass2: "Second base class." pass class SubClass2(BaseClass1, BaseClass2): "Second subclass of BaseClass1 and BaseClass2." def anotherMethod(self): "A method not defined in the base classes." pass # # Class documentation for SubClass3. # # This class documentation section includes a lot of text, # in several paragraphs. # # See, here is another paragraph. # # We even have an example: # # a -> b -> c -> a # # And a bulleted list: # # * line one # # * line two # # * line three # class SubClass3(SubClass2, MultipleBaseClasses): pass # # Random comment inserted in text # class SubClass4(SubClass1, SubClass3): # # Class documentation for SubClass4 after the name # pass # # External docs for five are skipped because # of the blank line following the comment block # class five: # # internal docs for five # pass class OverRecursion: pass class OverRecursion(OverRecursion): pass --- NEW FILE: test_decorated_comments.py --- """Test behavior with decorated comments. $Id: test_decorated_comments.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $ Comments (not docstrings) with decorative lines consisting of only the characters [-=# ] will be ignored. """ ################################################################################# # # Func with hash lines # ################################################################################# def Hashes(): pass #-------------------------------------------------------------------------------- # # Func with dash lines # #-------------------------------------------------------------------------------- def Dashes(): pass #================================================================================ # # Func with equal lines # #================================================================================ def Equals(): pass #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # Func with mixed dashes and equals # #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= def Mixed(): pass # # This function has, in the comments about it, a table. That table # should be rendered via STNG to an HTML table in the test output. # # |-------------------------------------------------| # | Function | Documentation | # |=================================================| # | '__str__' | This method converts the | # | | the object to a string. | # | | | # | | - Blah | # | | | # | | - Blaf | # | | | # | | |--------------------------| | # | | | Name | Favorite | | # | | | | Color | | # | | |==========================| | # | | | Jim | Red | | # | | |--------------------------| | # | | | John | Blue | | # | | |--------------------------| | # |-------------------------------------------------| # def StructuredTextTable(): pass --- NEW FILE: test_function_params.py --- """Test case for function argument handling with lots of different types of arguments.""" def example_function_with_args(arg1, arg2, arg3withDefault='hi there', arg3aWithDefault="'hi again'", arg3bWithDefault='"hi there again"', arg4DefaultInt=101, arg5DefaultTuple=(1,2), arg6DefaultList=[3,4], arg7DefaultNone=None, arg8DefaultName=foo, arg9DefaultInstance=DefaultClassInst(), arg10DefaultInstanceWithParams= \ DefaultClassInstWithParams(1, 2, ('tuple', 'param'), ['list', 'param'] ), negativeIntArg=-1, floatArg=1.2, negativeFloatArg=-3.4, mathArg=1 + 2, stringArgWithHTML='<h1>Hi, Dick & Jane!</h1>', ): "This is an example function for testing purposes." if one: raise IOError('RAISE_class') else: raise 'RAISE_blah2' for i in range(1, 10): raise 'RAISE_loop' raise 'RAISE_main_level' return None --- NEW FILE: test_ignore_comments.py --- """This module is used to test the ignore comments flag. If the test is successful, the 'WithComments' class will not have any documentation at all in the generated output. """ class WithComments: # # This class is documented only with comments. # # Any documentation which appears for this class with the # comment flag set to ignore comments indicates a bug. # def __init__(self): # # WithComments init method. # # You should not see this! # pass class WithoutComments: """This class is documented with __doc__ strings. The documentation for this class should always appear. """ def __init__(self): """WithoutComments __init__ method. You should see this. """ pass --- NEW FILE: test_import_statements.py --- """Simple test file for HappyDoc. This module contains a variety of import statements for unit testing. """ import CommandLineApp from CommandLineApp import TestApp, SubClassTestApp import Module1 from Module2 import Symbol1 import Package1.SubModule1 from Package2.SubModule2 import Symbol2 from Package3.SubModule3 import Symbol3 as Symbol3x from a.b import c, d import one.two import os, types import string from string import strip as StringStrip from sys import path from token import * from prettyast import astListFixNames # # Bug 478659 - Import statements with trailing comments seem to be ignored. # # this module will be listed import webbrowser import cgi # this module will not be listed --- NEW FILE: test_nested_structures.py --- #!/usr/bin/env python # # $Id: test_nested_structures.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $ # # Time-stamp: <01/03/08 02:13:53 dhellmann> # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # """Test various nested structures. o Jerome Alet <al...@un...> reported that nested classes do not appear in the output. o Jerome Alet <al...@un...> reported that nested functions do not appear in the output. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: test_nested_structures.py,v $', 'rcs_id' : '$Id: test_nested_structures.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $', 'creator' : 'Doug Hellmann <Dou...@bi...>', 'project' : 'HappyDoc', 'created' : 'Thu, 08-Mar-2001 02:08:06 EST', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 14:51:44 $', } # # Import system modules # # # Import Local modules # # # Module # class OuterClass: """This class is on the outside. This class contains one nested class. """ class InnerClass: """This class is inside of OuterClass. This class is nested one level deep. """ class InnerClass2: """This class is inside of InnerClass. This class is nested two levels deep. """ def OuterFunction(): "This function is at the outer level." def InnerFunction(): "This function is inside of OuterFunction." def InnerFunction2(): "This function is inside of InnerFunction." --- NEW FILE: test_variable_extraction.py --- #!/usr/bin/env python # # HappyDoc:# These variables should be discovered. # HappyDoc:TestInt=1 # HappyDoc:TestString="String" # HappyDoc:TestStringModule=string.strip(' this has spaces in front and back ') # HappyDoc:url=urlencode({'a':'A', 'b':'B'}) # # $Id: test_variable_extraction.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $ # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # HappyDoc:# These variables should **NOT** be discovered. # HappyDoc:NotFound=1 """There are HappyDoc variables embedded in the comments of this module. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: test_variable_extraction.py,v $', 'rcs_id' : '$Id: test_variable_extraction.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $', 'creator' : 'Doug Hellmann <Dou...@bi...>', 'project' : 'UNSPECIFIED', 'created' : 'Thu, 04-Oct-2001 10:59:20 EDT', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 14:51:44 $', } try: __version__ = __rcs_info__['version'].split(' ')[1] except: __version__ = '0.0' # # Import system modules # # # Import Local modules # # # Module # --- NEW FILE: test_variable_extraction_with_exception.py --- #!/usr/bin/env python # # HappyDoc:# These variables should be discovered. # HappyDoc:TestInt=1 # HappyDoc:TestString="String" # HappyDoc:TestStringModule=string.strip(' this has spaces in front and back ') # HappyDoc:url=urlencode({'a':'A', 'b':'B'}) # HappyDoc:# This should cause processing to abort. # HappyDOc:raise RuntimeError('Raising test exception in embedded directives.') # # $Id: test_variable_extraction_with_exception.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $ # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # HappyDoc:# These variables should **NOT** be discovered. # HappyDoc:NotFound=1 """There are HappyDoc variables embedded in the comments of this module. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: test_variable_extraction_with_exception.py,v $', 'rcs_id' : '$Id: test_variable_extraction_with_exception.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $', 'creator' : 'Doug Hellmann <Dou...@bi...>', 'project' : 'UNSPECIFIED', 'created' : 'Thu, 04-Oct-2001 10:59:20 EDT', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 14:51:44 $', } try: __version__ = __rcs_info__['version'].split(' ')[1] except: __version__ = '0.0' # # Import system modules # # # Import Local modules # # # Module # |
From: Doug H. <dou...@us...> - 2002-11-17 14:51:47
|
Update of /cvsroot/happydoc/HappyDoc3/TestCases/testScanner/levelOne/levelTwo In directory usw-pr-cvs1:/tmp/cvs-serv32400/TestCases/testScanner/levelOne/levelTwo Added Files: __init__.py two.py Log Message: Add test files. --- NEW FILE: __init__.py --- --- NEW FILE: two.py --- |
From: Doug H. <dou...@us...> - 2002-11-17 14:51:47
|
Update of /cvsroot/happydoc/HappyDoc3/TestCases/testScanner/levelOne In directory usw-pr-cvs1:/tmp/cvs-serv32400/TestCases/testScanner/levelOne Added Files: __init__.py ignoreme.py one.py Log Message: Add test files. --- NEW FILE: __init__.py --- --- NEW FILE: ignoreme.py --- --- NEW FILE: one.py --- |
From: Doug H. <dou...@us...> - 2002-11-17 14:51:47
|
Update of /cvsroot/happydoc/HappyDoc3/TestCases In directory usw-pr-cvs1:/tmp/cvs-serv32400/TestCases Added Files: __init__.py test.py Log Message: Add test files. --- NEW FILE: __init__.py --- #!/usr/bin/env python # # $Id: __init__.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $ # # Copyright 2001 Doug Hellmann. # # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of Doug # Hellmann not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # """Various input files for unit and regression tests. """ __rcs_info__ = { # # Creation Information # 'module_name' : '$RCSfile: __init__.py,v $', 'rcs_id' : '$Id: __init__.py,v 1.1 2002/11/17 14:51:44 doughellmann Exp $', 'creator' : 'Doug Hellmann <Dou...@bi...>', 'project' : 'UNSPECIFIED', 'created' : 'Sat, 06-Oct-2001 12:23:43 EDT', # # Current Information # 'author' : '$Author: doughellmann $', 'version' : '$Revision: 1.1 $', 'date' : '$Date: 2002/11/17 14:51:44 $', } try: __version__ = __rcs_info__['version'].split(' ')[1] except: __version__ = '0.0' # # Import system modules # # # Import Local modules # # # Module # --- NEW FILE: test.py --- #!/usr/bin/python # # Here is the module documentation # """Simple test file for HappyDoc. This module contains various test cases for testing the HappyDoc documentation generator. """ import string import CommandLineApp import os, types import TestCases.test from sys import path from token import * from TestCases.parseinfo.test_nested_structures import OuterClass, OuterFunction from CommandLineApp import TestApp class DefaultClassInst: "Class used for default parameter with a class instance." pass class DefaultClassInstWithParams: "Class used for default parameter with a class instance taking parameters." def __init__(self, *args): "Initialize DefaultClassInstWithParams instance." pass class DottedBaseClass(CommandLineApp.TestApp): "Class to test subclassing from a base class with dots in the name." pass class MultipleBaseClasses(DefaultClassInst, DefaultClassInstWithParams, CommandLineApp.CommandLineApp): "Class testing multiple inheritence." def __init__(self): "Initializer" pass # Here is a module level variable definition. foo=1 def example_function_with_args(arg1, arg2, arg3withDefault='hi there', arg3aWithDefault="'hi again'", arg3bWithDefault='"hi there again"', arg4DefaultInt=101, arg5DefaultTuple=(1,2), arg6DefaultList=[3,4], arg7DefaultNone=None, arg8DefaultName=foo, arg9DefaultInstance=DefaultClassInst(), arg10DefaultInstanceWithParams= \ DefaultClassInstWithParams(1, 2, ('tuple', 'param'), ['list', 'param'] ), stringArgWithHTML='<h1>Hi, Dick & Jane!</h1>', ): "This is an example function for testing purposes." if one: raise IOError('RAISE_class') else: raise 'RAISE_blah2' for i in range(1, 10): raise 'RAISE_loop' raise 'RAISE_main_level' return None def example_function_without_args(): "This example function has no arguments." pass def example_function_with_varargs(*args): "This example function takes a variable number of arguments." pass def example_function_with_kwargs(**kw): """ This example function takes variable keyword arguments. """ pass class BaseClass1: "First base class." # # classMember definition example # classMember=1 # # Documentation for method_of_bc1 # def method_of_bc1(self): pass def method2_of_bc1(self): # # Documentation for method2_of_bc1 after name # pass class SubClass1(BaseClass1): "First subclass of BaseClass1." pass class BaseClass2: "Second base class." pass class SubClass2(BaseClass1, BaseClass2): "Second subclass of BaseClass1 and BaseClass2." def anotherMethod(self): "A method not defined in the base classes." pass # # Class documentation for SubClass3. # # This class documentation section includes a lot of text, # in several paragraphs. # # See, here is another paragraph. # # We even have an example: # # a -> b -> c -> a # # And a bulleted list: # # * line one # # * line two # # * line three # class SubClass3(SubClass2, MultipleBaseClasses): pass # # Random comment inserted in text # class SubClass4(SubClass1, SubClass3): # # Class documentation for SubClass4 after the name # pass # # External docs for five are skipped because # of the blank line following the comment block # class five: # # internal docs for five # pass class OverRecursion: pass class OverRecursion(OverRecursion): pass |
From: Doug H. <dou...@us...> - 2002-11-17 14:51:47
|
Update of /cvsroot/happydoc/HappyDoc3/TestCases/docstring In directory usw-pr-cvs1:/tmp/cvs-serv32400/TestCases/docstring Added Files: test_classic_structuredtext.py Log Message: Add test files. --- NEW FILE: test_classic_structuredtext.py --- #!/usr/bin/env python # # HappyDoc:docStringFormat="ClassicStructuredText" # """Classic Structured Text Manipulation Parse a structured text string into a form that can be used with structured formats, like html. Structured text is text that uses indentation and simple symbology to indicate the structure of a document. A structured string consists of a sequence of paragraphs separated by one or more blank lines. Each paragraph has a level which is defined as the minimum indentation of the paragraph. A paragraph is a sub-paragraph of another paragraph if the other paragraph is the last preceding paragraph that has a lower level. Special symbology is used to indicate special constructs: - A single-line paragraph whose immediately succeeding paragraphs are lower level is treated as a header. - A paragraph that begins with a '-', '*', or 'o' is treated as an unordered list (bullet) element. - A paragraph that begins with a sequence of digits followed by a white-space character is treated as an ordered list element. - A paragraph that begins with a sequence of sequences, where each sequence is a sequence of digits or a sequence of letters followed by a period, is treated as an ordered list element. - A paragraph with a first line that contains some text, followed by some white-space and '--' is treated as a descriptive list element. The leading text is treated as the element title. - Sub-paragraphs of a paragraph that ends in the word 'example' or the word 'examples', or '::' is treated as example code and is output as is. - Text enclosed single quotes (with white-space to the left of the first quote and whitespace or punctuation to the right of the second quote) is treated as example code. - Text surrounded by '*' characters (with white-space to the left of the first '*' and whitespace or punctuation to the right of the second '*') is emphasized. - Text surrounded by '**' characters (with white-space to the left of the first '**' and whitespace or punctuation to the right of the second '**') is made strong. - Text surrounded by '_' underscore characters (with whitespace to the left and whitespace or punctuation to the right) is made underlined. - Text encloded by double quotes followed by a colon, a URL, and concluded by punctuation plus white space, *or* just white space, is treated as a hyper link. For example: "Zope":http://www.zope.org/ is ... Is interpreted as '<a href="http://www.zope.org/">Zope</a> is ....' Note: This works for relative as well as absolute URLs. - Text enclosed by double quotes followed by a comma, one or more spaces, an absolute URL and concluded by punctuation plus white space, or just white space, is treated as a hyper link. For example: "mail me", mailto:am...@di.... Is interpreted as '<a href="mailto:am...@di...">mail me</a>.' - Text enclosed in brackets which consists only of letters, digits, underscores and dashes is treated as hyper links within the document. For example: As demonstrated by Smith [12] this technique is quite effective. Is interpreted as '... by Smith <a href="#12">[12]</a> this ...'. Together with the next rule this allows easy coding of references or end notes. - Text enclosed in brackets which is preceded by the start of a line, two periods and a space is treated as a named link. For example: .. [12] "Effective Techniques" Smith, Joe ... Is interpreted as '<a name="12">[12]</a> "Effective Techniques" ...'. Together with the previous rule this allows easy coding of references or end notes. - A paragraph that has blocks of text enclosed in '||' is treated as a table. The text blocks correspond to table cells and table rows are denoted by newlines. By default the cells are center aligned. A cell can span more than one column by preceding a block of text with an equivalent number of cell separators '||'. Newlines and '|' cannot be a part of the cell text. For example:: |||| **Ingredient** || || *Name* || *Amount* || ||Spam||10|| ||Eggs||3|| is interpreted as:: <TABLE BORDER=1 CELLPADDING=2> <TR> <TD ALIGN=CENTER COLSPAN=2> <strong>Ingredients</strong> </TD> </TR> <TR> <TD ALIGN=CENTER COLSPAN=1> <em>Name</em> </TD> <TD ALIGN=CENTER COLSPAN=1> <em>Amount</em> </TD> </TR> <TR> <TD ALIGN=CENTER COLSPAN=1>Spam</TD> <TD ALIGN=CENTER COLSPAN=1>10</TD> </TR> <TR> <TD ALIGN=CENTER COLSPAN=1>Eggs</TD> <TD ALIGN=CENTER COLSPAN=1>3</TD> </TR> </TABLE> and appear as: |||| **Ingredient** || || *Name* || *Amount* || ||Spam||10|| ||Eggs||3|| """ |
From: Doug H. <dou...@us...> - 2002-11-17 14:51:17
|
Update of /cvsroot/happydoc/HappyDoc3/TestCases/docstring In directory usw-pr-cvs1:/tmp/cvs-serv32267/TestCases/docstring Log Message: Directory /cvsroot/happydoc/HappyDoc3/TestCases/docstring added to the repository |
From: Doug H. <dou...@us...> - 2002-11-17 14:51:06
|
Update of /cvsroot/happydoc/HappyDoc3 In directory usw-pr-cvs1:/tmp/cvs-serv32198 Added Files: .cvsignore Log Message: Ignore some files. --- NEW FILE: .cvsignore --- .coverage trace.txt |
From: Doug H. <dou...@us...> - 2002-11-17 14:50:09
|
Update of /cvsroot/happydoc/HappyDoc3/tools In directory usw-pr-cvs1:/tmp/cvs-serv32009/tools Log Message: Directory /cvsroot/happydoc/HappyDoc3/tools added to the repository |
From: Doug H. <dou...@us...> - 2002-11-17 14:46:23
|
Update of /cvsroot/happydoc/HappyDoc3 In directory usw-pr-cvs1:/tmp/cvs-serv28409 Modified Files: happydoc Log Message: Handle the locale stuff in the happydoclib library, so it works for the tests, too. Index: happydoc =================================================================== RCS file: /cvsroot/happydoc/HappyDoc3/happydoc,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** happydoc 17 Nov 2002 00:26:14 -0000 1.1.1.1 --- happydoc 17 Nov 2002 14:46:19 -0000 1.2 *************** *** 55,61 **** __version__ = '0.0' - import locale - locale.setlocale(locale.LC_ALL, '') - from happydoclib import HappyDoc --- 55,58 ---- |
From: Doug H. <dou...@us...> - 2002-11-17 14:45:28
|
Update of /cvsroot/happydoc/HappyDoc3 In directory usw-pr-cvs1:/tmp/cvs-serv28155 Removed Files: .coverage Log Message: Do not want to track the test coverage data. --- .coverage DELETED --- |