Update of /cvsroot/happydoc/HappyDoc3/happydoclib
In directory sc8-pr-cvs1:/tmp/cvs-serv28702/happydoclib
Modified Files:
scanner.py test_scanner.py
Added Files:
packagetree.py test_packagetree.py
Log Message:
Move PackageTree to its own file.
--- NEW FILE: packagetree.py ---
#!/usr/bin/env python
#
# $Id: packagetree.py,v 1.1 2002/12/29 18:35:14 doughellmann Exp $
#
# Copyright 2002 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.
#
"""Tree representing the input data.
"""
__rcs_info__ = {
#
# Creation Information
#
'module_name' : '$RCSfile: packagetree.py,v $',
'rcs_id' : '$Id: packagetree.py,v 1.1 2002/12/29 18:35:14 doughellmann Exp $',
'creator' : 'Doug Hellmann <do...@he...>',
'project' : 'HappyDoc',
'created' : 'Sun, 29-Dec-2002 12:37:53 EST',
#
# Current Information
#
'author' : '$Author: doughellmann $',
'version' : '$Revision: 1.1 $',
'date' : '$Date: 2002/12/29 18:35:14 $',
}
try:
__version__ = __rcs_info__['version'].split(' ')[1]
except:
__version__ = '0.0'
#
# Import system modules
#
import mimetypes
import os
import re
import UserDict
#
# Import Local modules
#
import happydoclib
from happydoclib.status import statusMessage
from happydoclib.trace import trace
from happydoclib.utils import *
#
# Module
#
TRACE_LEVEL=2
#
# Initialize extensions for mimetypes that we know about but which are
# not standard.
#
mimetypes.types_map['.stx'] = 'text/x-structured'
class PackageTree(UserDict.UserDict):
"""Tree of package information.
Access each child node using the standard mapping de-reference
syntax ([], .get(), etc.).
"""
parser_mapping = {
'text/x-python' : 'parsePythonInput',
'text/plain' : 'parsePlainTextInput',
'text/x-structured' : 'parseStructuredTextInput',
}
def __init__(self, parent, name):
trace.into('PackageTree', '__init__',
parent=parent,
name=name,
outputLevel=TRACE_LEVEL,
)
UserDict.UserDict.__init__(self)
self.parent = parent
self.name = os.path.basename(name)
trace.write('self.name=%s' % self.name, outputLevel=TRACE_LEVEL)
self.canonical_name = name
trace.outof(outputLevel=TRACE_LEVEL)
return
def __repr__(self):
base_str = UserDict.UserDict.__repr__(self)
return '<%s %s: %s>' % (self.__class__.__name__, self.getName(), base_str)
#
# Parsing methods
#
def parsePythonInput(self):
trace.into('PackageTree', 'parsePythonInput',
outputLevel=TRACE_LEVEL)
#
# Derive the filename for this module.
#
filename = self.getInputFilename()
statusMessage('Parsing: %s' % filename)
#
# Figure out if there is a parent node for the
# documentation suite.
#
package_parent = self.getParent()
if package_parent and hasattr(package_parent, 'module_info'):
docs_parent = package_parent.module_info
else:
docs_parent = None
trace.writeVar(docs_parent=docs_parent,
outputLevel=TRACE_LEVEL)
docs = happydoclib.parseinfo.getDocs(
parent=docs_parent,
fileName=filename,
)
self.module_info = docs
trace.outof(outputLevel=TRACE_LEVEL)
return
def parsePlainTextInput(self):
trace.into('PackageTree', 'parsePlainTextInput',
outputLevel=TRACE_LEVEL,
)
#
# Derive the filename for this module.
#
filename = self.getInputFilename()
trace.writeVar(filename=filename, outputLevel=TRACE_LEVEL)
statusMessage('Importing preformatted file: %s' % filename)
#f = open(filename, 'rt')
#body = f.read()
#f.close()
#packageTreeNode.preformatted_text = body
trace.outof(outputLevel=TRACE_LEVEL)
return
def parseStructuredTextInput(self):
trace.into('PackageTree', 'parseStructuredTextInput',
outputLevel=TRACE_LEVEL)
self.parsePlainTextInput()
trace.outof(outputLevel=TRACE_LEVEL)
return
def parseInput(self):
"""Get whatever information is appropriate from the input file.
"""
trace.into('PackageTree', 'parseInput',
outputLevel=TRACE_LEVEL)
if os.path.isdir(self.getInputFilename()):
trace.write('directory', outputLevel=TRACE_LEVEL)
trace.outof(outputLevel=TRACE_LEVEL)
return
mimetype, encoding = self.getMimeType()
try:
parse_method_name = self.parser_mapping[mimetype]
except KeyError:
#
# Don't know what to do with this file.
#
statusMessage('Not parsing input %s with mimetype %s' % (
self.getInputFilename(),
mimetype,
), 2)
else:
#
# Call the parse method
#
parse_method = getattr(self, parse_method_name)
parse_method()
trace.outof(outputLevel=TRACE_LEVEL)
return
#
# Data retrieval methods
#
def getMimeType(self):
"""Returns the (mimetype, encoding) setting for this node.
"""
trace.into('PackageTreeNode', 'getMimeType',
name=self.name,
outputLevel=TRACE_LEVEL,
)
input_filename = self.getInputFilename()
mimetype = mimetypes.guess_type(input_filename)
if mimetype == (None, None):
if isSomethingThatLooksLikeDirectory(input_filename):
mimetype = ('application/x-directory', None)
trace.outof(mimetype, outputLevel=TRACE_LEVEL)
return mimetype
def getName(self):
"""Returns the name of this tree node.
"""
return self.name
def getCanonicalName(self):
"""Returns the canonical, full, name of the this tree node.
"""
return self.canonical_name
def getInputFilename(self):
"""Returns the original input filename that created the node.
"""
trace.into('PackageTree', 'getInputFilename',
outputLevel=TRACE_LEVEL)
node_path = self.getPath(1)
trace.writeVar(node_path=node_path, outputLevel=TRACE_LEVEL)
filename = apply(os.path.join, node_path)
trace.writeVar(filename=filename, outputLevel=TRACE_LEVEL)
trace.outof(filename, outputLevel=TRACE_LEVEL)
return filename
def getRelativeFilename(self):
"""Returns the filename relative to the root of the input area.
"""
trace.into('PackageTree', 'getRelativeFilename',
outputLevel=TRACE_LEVEL)
node_path = self.getPath()
trace.writeVar(node_path=node_path,
outputLevel=TRACE_LEVEL)
filename = apply(os.path.join, node_path)
trace.writeVar(filename=filename,
outputLevel=TRACE_LEVEL)
trace.outof(filename, outputLevel=TRACE_LEVEL)
return filename
def _unquoteString(self, str):
"Remove surrounding quotes from a string."
str = str.strip()
while ( str
and
(str[0] == str[-1])
and
str[0] in ('"', "'")
):
str = str[1:-1]
return str
def getDocStringAndFormat(self):
#
# Are we a python module?
#
if hasattr(self, 'module_info'):
docstring = self.module_info.getDocString()
docstring = self._unquoteString(docstring)
format = self.module_info.getDocStringFormat()
return (docstring, format)
#
# Are we a text file?
#
mimetype, encoding = self.getMimeType()
if mimetype in ('text/plain', 'text/x-structured'):
input_filename = self.getInputFilename()
readme_text = open(input_filename, 'rt').read()
format = 'StructuredText'
return (readme_text, format)
#
# Look inside sub-nodes
#
for name in ('__init__.py', 'README.txt', 'README.stx'):
trace.write('looking for %s' % name, outputLevel=TRACE_LEVEL)
node = self.get(name)
if node is not None:
return node.getDocStringAndFormat()
return ('', 'StructuredText')
_summary_pattern = re.compile(r'^\s*([^\n]+)\n')
def getSummaryAndFormat(self):
if hasattr(self, 'module_info'):
return self.module_info.getSummaryAndFormat()
else:
text, format = self.getDocStringAndFormat()
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(), format)
else:
return (text, format)
#
# Tree methods
#
def getParent(self):
"""Returns the parent node for this tree.
If there is no parent (root of the tree), returns None.
"""
return self.parent
def getPath(self, useCanonicalName=0):
"""Return the path from the root to this node.
Returns a tuple of node names, beginning with the root node
and ending with this node.
"""
trace.into('PackageTree', 'getPath',
useCanonicalName=useCanonicalName,
outputLevel=TRACE_LEVEL+1,
)
parent = self.getParent()
trace.writeVar(parent=parent,
outputLevel=TRACE_LEVEL+1,
)
if parent:
parent_path = parent.getPath(useCanonicalName=useCanonicalName)
else:
parent_path = ()
trace.writeVar(parent_path=parent_path,
outputLevel=TRACE_LEVEL+1,
)
if useCanonicalName:
name = self.getCanonicalName()
else:
name = self.getName()
path = parent_path + (name,)
trace.outof(path,
outputLevel=TRACE_LEVEL+1,
)
return path
def getPathToNode(self, otherNode):
"""Returns a sequence of nodes to be traversed to reach the otherNode.
The sequence assumes that traversal begins at the current node.
A '..' indicates moving up to the parent one level.
"""
my_path = self.getPath()
other_path = otherNode.getPath()
if my_path == other_path:
return ()
#
# Strip the top parts of the paths which match.
#
while my_path and other_path and my_path[0] == other_path[0]:
my_path = my_path[1:]
other_path = other_path[1:]
if self.items():
is_file = 0
else:
is_file = 1
going_up = ('..',) * (len(my_path) - is_file)
relative_path = going_up + other_path
return relative_path
def findNodeFromDottedName(self, dottedNodeName, tryParent=1):
"""Find the node referenced by the dotted name given.
The dottedNodeName 'happydoclib.scanner' retuns the node for
this module. If the named node cannot be found, the return
value is None.
"""
trace_level=TRACE_LEVEL
trace.into('PackageTree', 'findNodeFromDottedName',
dottedNodeName=dottedNodeName,
outputLevel=trace_level,
)
name_parts = dottedNodeName.split('.')
name = name_parts[0]
trace.write('name=%s' % name,
outputLevel=trace_level,
)
trace.writeVar(name=name,
outputLevel=trace_level,
)
named_node = None
#
# Is someone looking for us?
#
if (named_node is None):
if (name == self.getName()):
trace.write('Matched ourself',
outputLevel=trace_level,
)
named_node = self
if (named_node is None):
trace.write('Checking %s as child' % name,
outputLevel=trace_level,
)
named_node = self.get(name)
if (named_node is None):
trace.write('Checking %s.py as child' % name,
outputLevel=trace_level,
)
named_node = self.get('%s.py' % name)
if (named_node is None) and tryParent:
#
# Try the parent with the whole name
#
parent = self.getParent()
if parent:
trace.write('Checking for %s in parent' % name,
outputLevel=trace_level,
)
named_node = parent.findNodeFromDottedName(dottedNodeName)
#
# Do we need to process the remainder of the original name?
#
if named_node and (len(name_parts) > 1):
remainder = '.'.join(name_parts[1:])
trace.write('Handling remainder (%s)' % remainder,
outputLevel=trace_level,
)
named_node = named_node.findNodeFromDottedName(remainder,
tryParent=0)
if named_node is not None:
trace.outof(named_node.getName(),
outputLevel=trace_level,
)
else:
trace.outof(outputLevel=trace_level)
return named_node
def addSubNode(self, name):
"""Insert a child node under this node.
Create a new PackageTree node, set its parent to be ourself,
and save it as one of our children.
"""
trace.into('PackageTree', 'addSubNode', name=name,
outputLevel=TRACE_LEVEL)
new_node = PackageTree(self, name)
self[name] = new_node
trace.outof(outputLevel=TRACE_LEVEL)
return new_node
def getSubNodes(self, mimetype=None):
"""Returns the children of this node.
If mimetype is not none, returns only the children with that
mimetype.
"""
if mimetype is None:
return self.values()
else:
if not hasattr(self, 'grouped_children'):
self.grouped_children = {}
for node in self.values():
mimetype, encoding = node.getMimeType()
group = self.grouped_children.setdefault(mimetype, [])
group.append(node)
return self.grouped_children.get(mimetype, [])
def walk(self, callback):
"""Walk the PackageTree, calling the callback at each node.
"""
callback(self)
for child in self.values():
child.walk(callback)
return
--- NEW FILE: test_packagetree.py ---
#!/usr/bin/env python
#
# $Id: test_packagetree.py,v 1.1 2002/12/29 18:35:14 doughellmann Exp $
#
# Copyright 2002 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.
#
"""Tests for packagetree module.
"""
__rcs_info__ = {
#
# Creation Information
#
'module_name' : '$RCSfile: test_packagetree.py,v $',
'rcs_id' : '$Id: test_packagetree.py,v 1.1 2002/12/29 18:35:14 doughellmann Exp $',
'creator' : 'Doug Hellmann <do...@he...>',
'project' : 'HappyDoc',
'created' : 'Sun, 29-Dec-2002 12:41:21 EST',
#
# Current Information
#
'author' : '$Author: doughellmann $',
'version' : '$Revision: 1.1 $',
'date' : '$Date: 2002/12/29 18:35:14 $',
}
try:
__version__ = __rcs_info__['version'].split(' ')[1]
except:
__version__ = '0.0'
#
# Import system modules
#
import os
import unittest
#
# Import Local modules
#
from happydoclib.scanner import Scanner
from happydoclib.packagetree import PackageTree
#
# Module
#
class PackageTreeTestCase(unittest.TestCase):
def testGetInputFilename(self):
scanner = Scanner(['TestCases/testScanner'])
trees = scanner.getPackageTrees()
expected_tree = trees[0]
self.failUnlessEqual(
expected_tree.getName(),
'testScanner',
'First level tree got %s instead of testScanner' % expected_tree.getName(),
)
level_one = expected_tree['levelOne']
self.failUnlessEqual(
level_one.getName(),
'levelOne',
'First sub-level tree got %s instead of levelOne' % level_one.getName(),
)
self.failUnlessEqual(level_one.getInputFilename(),
'TestCases/testScanner/levelOne',
)
level_two = level_one['levelTwo']
self.failUnlessEqual(
level_two.getName(),
'levelTwo',
'First sub-level tree got %s instead of levelTwo' % level_two.getName(),
)
self.failUnlessEqual(level_two.getInputFilename(),
'TestCases/testScanner/levelOne/levelTwo',
)
return
def testPackageTreePath(self):
scanner = Scanner(['TestCases/testScanner'])
trees = scanner.getPackageTrees()
expected_tree = trees[0]
dir_one = expected_tree['levelOne']
dir_one_path = dir_one.getPath()
self.failUnlessEqual(dir_one_path,
('testScanner',
'levelOne',
))
dir_two = expected_tree['levelOne']['levelTwo']
dir_two_path = dir_two.getPath()
self.failUnlessEqual(dir_two_path,
('testScanner',
'levelOne',
'levelTwo',
))
module_two = expected_tree['levelOne']['levelTwo']['two.py']
module_two_path = module_two.getPath()
self.failUnlessEqual(module_two_path,
('testScanner',
'levelOne',
'levelTwo',
'two.py',
),
)
return
def testPackageTreePath(self):
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):
scanner = Scanner(['TestCases/testScanner'], ['ignoreme.py'])
trees = scanner.getPackageTrees()
level_one = trees[0]['levelOne']
try:
ignoring = level_one['ignoreme.py']
except KeyError:
pass
else:
self.fail('Still have ignoreme.py')
return
def testPackageTreeIgnoreTestFiles(self):
scanner = Scanner(['happydoclib'], ['^tests.py$',
'^test_.*py$',
])
trees = scanner.getPackageTrees()
level_one = trees[0]
for name in ('tests.py',
'test_scanner.py',
):
try:
ignoring = level_one[name]
except KeyError:
pass
else:
self.fail('Still have %s' % name)
return
def testPackageTreeName(self):
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
def testPackageTreeParent(self):
tree = PackageTree(None, 'tree1')
self.failUnlessEqual(None, tree.getParent(),
'Parents do not match.')
return
class PackageTreeRelativePathTestCase(unittest.TestCase):
def setUp(self):
cwd = os.getcwd()
input_dir = os.path.join(cwd, 'TestCases/testScanner')
scanner = Scanner([input_dir])
trees = scanner.getPackageTrees()
expected_tree = trees[0]
self.expected_tree = expected_tree
return
def testSelf(self):
target = self.expected_tree['levelOne']['levelTwo']['two.py']
start = self.expected_tree['levelOne']['levelTwo']['two.py']
relative_path = start.getPathToNode(target)
self.failUnlessEqual(relative_path,
(),
)
return
def testParentDirOfModuleDir(self):
target = self.expected_tree['levelOne']
start = self.expected_tree['levelOne']['levelTwo']['two.py']
relative_path = start.getPathToNode(target)
self.failUnlessEqual(relative_path,
('..',
),
)
return
def testModuleSameDir(self):
target = self.expected_tree['levelOne']['one.py']
start = self.expected_tree['levelOne']['ignoreme.py']
relative_path = start.getPathToNode(target)
self.failUnlessEqual(relative_path,
('one.py',
),
)
return
def testModuleParentDir(self):
target = self.expected_tree['levelOne']['one.py']
start = self.expected_tree['levelOne']['levelTwo']['two.py']
relative_path = start.getPathToNode(target)
self.failUnlessEqual(relative_path,
('..',
'one.py',
),
)
return
def testParentDirOfDir(self):
target = self.expected_tree['levelOne']
start = self.expected_tree['levelOne']['levelTwo']
relative_path = start.getPathToNode(target)
self.failUnlessEqual(relative_path,
('..',
),
)
return
class PackageTreeSummaryAndDocStringTests(unittest.TestCase):
def setUp(self):
input_dir = os.path.join('TestCases', 'testScanner')
output_dir = '/tmp/foo'
scanner = Scanner([input_dir])
self.scanner = scanner
return
def tearDown(self):
del self.scanner
return
def testGetReadmeTextForDirectoryInit(self):
trees = self.scanner.getPackageTrees()
expected_tree = trees[0]['readme_from_init']
actual, format = expected_tree.getDocStringAndFormat()
expected_format = 'StructuredText'
expected = 'This is the __init__.py file for readme_from_init.'
self.failUnlessEqual(actual, expected)
return
def testGetReadmeTextForDirectoryDotTxt(self):
trees = self.scanner.getPackageTrees()
expected_tree = trees[0]['readme_from_readme']
actual, format = expected_tree.getDocStringAndFormat()
expected_format = 'StructuredText'
expected = 'This is the README.txt file for readme_from_readme.\n'
self.failUnlessEqual(actual, expected)
return
def testGetReadmeTextForDirectoryDotStx(self):
trees = self.scanner.getPackageTrees()
expected_tree = trees[0]['readme_from_stx']
actual, format = expected_tree.getDocStringAndFormat()
expected_format = 'StructuredText'
expected = 'This is the README.stx file for readme_from_stx.\n'
self.failUnlessEqual(actual, expected)
return
class PackageTreeFindNodeTestCase(unittest.TestCase):
def setUp(self):
cwd = os.getcwd()
input_dir = os.path.join(cwd, 'TestCases/testScanner')
scanner = Scanner([input_dir])
trees = scanner.getPackageTrees()
expected_tree = trees[0]
self.expected_tree = expected_tree
return
def _testFind(self, name, start, target):
found = start.findNodeFromDottedName(name)
if not found:
self.fail('Did not find anything')
self.failUnlessEqual(found, target)
return
def testFindSelf(self):
self._testFind('levelOne',
self.expected_tree['levelOne'],
self.expected_tree['levelOne'],
)
return
def testFindChild(self):
self._testFind('levelTwo',
self.expected_tree['levelOne'],
self.expected_tree['levelOne']['levelTwo'],
)
return
def testFindSelfDotChild(self):
self._testFind('levelOne.levelTwo',
self.expected_tree['levelOne'],
self.expected_tree['levelOne']['levelTwo'],
)
return
def testFindParent(self):
self._testFind('levelOne',
self.expected_tree['levelOne']['levelTwo'],
self.expected_tree['levelOne'],
)
return
def testFindSibling(self):
self._testFind('readme_from_readme',
self.expected_tree['levelOne'],
self.expected_tree['readme_from_readme'],
)
return
def testFindAunt(self):
self._testFind('readme_from_readme',
self.expected_tree['levelOne']['levelTwo'],
self.expected_tree['readme_from_readme'],
)
return
def testFindNeice(self):
self._testFind('levelOne.levelTwo',
self.expected_tree['readme_from_readme'],
self.expected_tree['levelOne']['levelTwo'],
)
return
def testFindNotThere(self):
name = 'levelOne.levelTwo.notThereAtAll'
start = self.expected_tree['readme_from_readme']
found = start.findNodeFromDottedName(name)
if found:
self.fail('Found something unexpected')
return
if __name__ == '__main__':
unittest.main()
Index: scanner.py
===================================================================
RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/scanner.py,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -d -r1.13 -r1.14
*** scanner.py 29 Dec 2002 17:30:58 -0000 1.13
--- scanner.py 29 Dec 2002 18:35:14 -0000 1.14
***************
*** 59,66 ****
#
import glob
- import mimetypes
import os
import re
- import UserDict
#
--- 59,64 ----
***************
*** 68,71 ****
--- 66,70 ----
#
import happydoclib
+ from happydoclib.packagetree import PackageTree
from happydoclib.status import statusMessage
from happydoclib.trace import trace
***************
*** 76,527 ****
#
! #
! # Initialize extensions for mimetypes that we know about but which are
! # not standard.
! #
! mimetypes.types_map['.stx'] = 'text/x-structured'
!
! class PackageTree(UserDict.UserDict):
! """Tree of package information.
!
! Access each child node using the standard mapping de-reference
! syntax ([], .get(), etc.).
! """
!
! parser_mapping = {
! 'text/x-python' : 'parsePythonInput',
! 'text/plain' : 'parsePlainTextInput',
! 'text/x-structured' : 'parseStructuredTextInput',
! }
!
! 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)
! trace.write('self.name=%s' % self.name)
! self.canonical_name = name
!
! trace.outof()
! return
!
! def __repr__(self):
! base_str = UserDict.UserDict.__repr__(self)
! return '<%s %s: %s>' % (self.__class__.__name__, self.getName(), base_str)
!
! #
! # Parsing methods
! #
!
! def parsePythonInput(self):
! trace.into('PackageTree', 'parsePythonInput')
! #
! # Derive the filename for this module.
! #
! filename = self.getInputFilename()
! statusMessage('Parsing: %s' % filename)
!
! #
! # Figure out if there is a parent node for the
! # documentation suite.
! #
! package_parent = self.getParent()
! if package_parent and hasattr(package_parent, 'module_info'):
! docs_parent = package_parent.module_info
! else:
! docs_parent = None
!
! trace.writeVar(docs_parent=docs_parent)
!
! docs = happydoclib.parseinfo.getDocs(
! parent=docs_parent,
! fileName=filename,
! )
!
! self.module_info = docs
!
! trace.outof()
! return
!
! def parsePlainTextInput(self):
! trace.into('PackageTree', 'parsePlainTextInput',
! )
! #
! # Derive the filename for this module.
! #
! filename = self.getInputFilename()
! trace.writeVar(filename=filename)
!
! statusMessage('Importing preformatted file: %s' % filename)
!
! #f = open(filename, 'rt')
! #body = f.read()
! #f.close()
!
! #packageTreeNode.preformatted_text = body
!
! trace.outof()
! return
!
! def parseStructuredTextInput(self):
! trace.into('PackageTree', 'parseStructuredTextInput')
! self.parsePlainTextInput()
! trace.outof()
! return
!
! def parseInput(self):
! """Get whatever information is appropriate from the input file.
! """
! trace.into('PackageTree', 'parseInput')
!
! if os.path.isdir(self.getInputFilename()):
! trace.write('directory')
! trace.outof()
! return
!
! mimetype, encoding = self.getMimeType()
! try:
! parse_method_name = self.parser_mapping[mimetype]
! except KeyError:
! #
! # Don't know what to do with this file.
! #
! statusMessage('Not parsing input %s with mimetype %s' % (
! self.getInputFilename(),
! mimetype,
! ), 2)
! else:
! #
! # Call the parse method
! #
! parse_method = getattr(self, parse_method_name)
! parse_method()
!
! trace.outof()
! return
!
! #
! # Data retrieval methods
! #
!
! def getMimeType(self):
! """Returns the (mimetype, encoding) setting for this node.
! """
! trace.into('PackageTreeNode', 'getMimeType',
! name=self.name,
! )
!
! input_filename = self.getInputFilename()
! mimetype = mimetypes.guess_type(input_filename)
!
! if mimetype == (None, None):
! if isSomethingThatLooksLikeDirectory(input_filename):
! mimetype = ('application/x-directory', None)
!
! trace.outof(mimetype)
! return mimetype
!
! def getName(self):
! """Returns the name of this tree node.
! """
! return self.name
!
! def getCanonicalName(self):
! """Returns the canonical, full, name of the this tree node.
! """
! return self.canonical_name
!
! def getInputFilename(self):
! """Returns the original input filename that created the node.
! """
! trace.into('PackageTree', 'getInputFilename')
!
! node_path = self.getPath(1)
! trace.writeVar(node_path=node_path)
! filename = apply(os.path.join, node_path)
! trace.writeVar(filename=filename)
!
! trace.outof(filename)
! return filename
!
! def getRelativeFilename(self):
! """Returns the filename relative to the root of the input area.
! """
! trace.into('PackageTree', 'getRelativeFilename')
!
! node_path = self.getPath()
! trace.writeVar(node_path=node_path)
! filename = apply(os.path.join, node_path)
! trace.writeVar(filename=filename)
!
! trace.outof(filename)
! return filename
!
! def _unquoteString(self, str):
! "Remove surrounding quotes from a string."
! str = str.strip()
! while ( str
! and
! (str[0] == str[-1])
! and
! str[0] in ('"', "'")
! ):
! str = str[1:-1]
! return str
!
! def getDocStringAndFormat(self):
! #
! # Are we a python module?
! #
! if hasattr(self, 'module_info'):
! docstring = self.module_info.getDocString()
! docstring = self._unquoteString(docstring)
! format = self.module_info.getDocStringFormat()
! return (docstring, format)
!
! #
! # Are we a text file?
! #
! mimetype, encoding = self.getMimeType()
! if mimetype in ('text/plain', 'text/x-structured'):
! input_filename = self.getInputFilename()
! readme_text = open(input_filename, 'rt').read()
! format = 'StructuredText'
! return (readme_text, format)
!
! #
! # Look inside sub-nodes
! #
! for name in ('__init__.py', 'README.txt', 'README.stx'):
! trace.write('looking for %s' % name)
! node = self.get(name)
! if node is not None:
! return node.getDocStringAndFormat()
!
! return ('', 'StructuredText')
!
! _summary_pattern = re.compile(r'^\s*([^\n]+)\n')
! def getSummaryAndFormat(self):
! if hasattr(self, 'module_info'):
! return self.module_info.getSummaryAndFormat()
! else:
! text, format = self.getDocStringAndFormat()
! 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(), format)
! else:
! return (text, format)
!
!
! #
! # Tree methods
! #
!
! def getParent(self):
! """Returns the parent node for this tree.
!
! If there is no parent (root of the tree), returns None.
! """
! return self.parent
!
! def getPath(self, useCanonicalName=0):
! """Return the path from the root to this node.
!
! Returns a tuple of node names, beginning with the root node
! and ending with this node.
! """
! trace.into('PackageTree', 'getPath',
! useCanonicalName=useCanonicalName,
! outputLevel=2,
! )
!
! parent = self.getParent()
! trace.writeVar(parent=parent,
! outputLevel=2,
! )
! if parent:
! parent_path = parent.getPath(useCanonicalName=useCanonicalName)
! else:
! parent_path = ()
!
! trace.writeVar(parent_path=parent_path,
! outputLevel=2,
! )
!
! if useCanonicalName:
! name = self.getCanonicalName()
! else:
! name = self.getName()
!
! path = parent_path + (name,)
!
! trace.outof(path,
! outputLevel=2,
! )
! return path
!
! def getPathToNode(self, otherNode):
! """Returns a sequence of nodes to be traversed to reach the otherNode.
!
! The sequence assumes that traversal begins at the current node.
! A '..' indicates moving up to the parent one level.
! """
! my_path = self.getPath()
! other_path = otherNode.getPath()
! if my_path == other_path:
! return ()
!
! #
! # Strip the top parts of the paths which match.
! #
! while my_path and other_path and my_path[0] == other_path[0]:
! my_path = my_path[1:]
! other_path = other_path[1:]
!
! if self.items():
! is_file = 0
! else:
! is_file = 1
!
! going_up = ('..',) * (len(my_path) - is_file)
!
! relative_path = going_up + other_path
!
! return relative_path
!
! def findNodeFromDottedName(self, dottedNodeName, tryParent=1):
! """Find the node referenced by the dotted name given.
!
! The dottedNodeName 'happydoclib.scanner' retuns the node for
! this module. If the named node cannot be found, the return
! value is None.
! """
! trace_level=1
! trace.into('PackageTree', 'findNodeFromDottedName',
! dottedNodeName=dottedNodeName,
! outputLevel=trace_level,
! )
!
! name_parts = dottedNodeName.split('.')
! name = name_parts[0]
!
! trace.write('name=%s' % name,
! outputLevel=trace_level,
! )
! trace.writeVar(name=name,
! outputLevel=trace_level,
! )
!
! named_node = None
!
! #
! # Is someone looking for us?
! #
! if (named_node is None):
! if (name == self.getName()):
! trace.write('Matched ourself',
! outputLevel=trace_level,
! )
! named_node = self
!
! if (named_node is None):
! trace.write('Checking %s as child' % name,
! outputLevel=trace_level,
! )
! named_node = self.get(name)
!
! if (named_node is None):
! trace.write('Checking %s.py as child' % name,
! outputLevel=trace_level,
! )
! named_node = self.get('%s.py' % name)
!
! if (named_node is None) and tryParent:
! #
! # Try the parent with the whole name
! #
! parent = self.getParent()
! if parent:
! trace.write('Checking for %s in parent' % name,
! outputLevel=trace_level,
! )
! named_node = parent.findNodeFromDottedName(dottedNodeName)
!
! #
! # Do we need to process the remainder of the original name?
! #
! if named_node and (len(name_parts) > 1):
! remainder = '.'.join(name_parts[1:])
! trace.write('Handling remainder (%s)' % remainder,
! outputLevel=trace_level,
! )
! named_node = named_node.findNodeFromDottedName(remainder,
! tryParent=0)
!
! if named_node is not None:
! trace.outof(named_node.getName(),
! outputLevel=trace_level,
! )
! else:
! trace.outof(outputLevel=trace_level)
! return named_node
!
! def addSubNode(self, name):
! """Insert a child node under this node.
!
! Create a new PackageTree node, set its parent to be ourself,
! and save it as one of our children.
! """
! trace.into('PackageTree', 'addSubNode', name=name)
! new_node = PackageTree(self, name)
! self[name] = new_node
! trace.outof()
! return new_node
!
! def getSubNodes(self, mimetype=None):
! """Returns the children of this node.
!
! If mimetype is not none, returns only the children with that
! mimetype.
! """
! if mimetype is None:
! return self.values()
! else:
! if not hasattr(self, 'grouped_children'):
! self.grouped_children = {}
! for node in self.values():
! mimetype, encoding = node.getMimeType()
! group = self.grouped_children.setdefault(mimetype, [])
! group.append(node)
! return self.grouped_children.get(mimetype, [])
!
! def walk(self, callback):
! """Walk the PackageTree, calling the callback at each node.
! """
! callback(self)
! for child in self.values():
! child.walk(callback)
! return
!
!
class Scanner:
--- 75,79 ----
#
! TRACE_LEVEL=2
class Scanner:
***************
*** 541,544 ****
--- 93,97 ----
ignorePatterns=ignorePatterns,
includeComments=includeComments,
+ outputLevel=TRACE_LEVEL,
)
***************
*** 564,568 ****
self._parsePackageTree()
! trace.outof()
return
--- 117,121 ----
self._parsePackageTree()
! trace.outof(outputLevel=TRACE_LEVEL)
return
***************
*** 586,591 ****
trace.into('Scanner', 'buildPackageTree',
directoryName=directoryName,
! parent=parent,
)
package_tree_name = os.path.basename(directoryName)
--- 139,152 ----
trace.into('Scanner', 'buildPackageTree',
directoryName=directoryName,
! #parent=parent,
! outputLevel=TRACE_LEVEL,
)
+
+ if parent is not None:
+ trace.writeVar(parent=parent.getName(),
+ outputLevel=TRACE_LEVEL)
+ else:
+ trace.writeVar(parent=parent,
+ outputLevel=TRACE_LEVEL)
package_tree_name = os.path.basename(directoryName)
***************
*** 598,604 ****
if ignore_re.search(package_tree_name):
trace.write('Ignoring because "%s" matched %s' % (package_tree_name,
! ignore_re.pattern)
)
! trace.outof()
return None
--- 159,166 ----
if ignore_re.search(package_tree_name):
trace.write('Ignoring because "%s" matched %s' % (package_tree_name,
! ignore_re.pattern),
! outputLevel=TRACE_LEVEL,
)
! trace.outof(outputLevel=TRACE_LEVEL)
return None
***************
*** 618,622 ****
# Get directory contents
#
! trace.write('Scanning %s' % directoryName)
pattern = os.path.join(directoryName, '*')
contents = glob.glob(pattern)
--- 180,185 ----
# Get directory contents
#
! trace.write('Scanning %s' % directoryName,
! outputLevel=TRACE_LEVEL)
pattern = os.path.join(directoryName, '*')
contents = glob.glob(pattern)
***************
*** 628,632 ****
self.buildPackageTree(subnode_name, tree)
! trace.outof()
return tree
--- 191,195 ----
self.buildPackageTree(subnode_name, tree)
! trace.outof(outputLevel=TRACE_LEVEL)
return tree
Index: test_scanner.py
===================================================================
RCS file: /cvsroot/happydoc/HappyDoc3/happydoclib/test_scanner.py,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** test_scanner.py 28 Dec 2002 16:41:31 -0000 1.9
--- test_scanner.py 29 Dec 2002 18:35:14 -0000 1.10
***************
*** 61,65 ****
# Import Local modules
#
! from happydoclib.scanner import Scanner, PackageTree
--- 61,65 ----
# Import Local modules
#
! from happydoclib.scanner import Scanner
***************
*** 195,540 ****
self.failUnlessEqual(mimetype, ('text/x-structured', None))
- return
-
- def testGetInputFilename(self):
- scanner = Scanner(['TestCases/testScanner'])
-
- trees = scanner.getPackageTrees()
-
- expected_tree = trees[0]
- self.failUnlessEqual(
- expected_tree.getName(),
- 'testScanner',
- 'First level tree got %s instead of testScanner' % expected_tree.getName(),
- )
-
- level_one = expected_tree['levelOne']
- self.failUnlessEqual(
- level_one.getName(),
- 'levelOne',
- 'First sub-level tree got %s instead of levelOne' % level_one.getName(),
- )
- self.failUnlessEqual(level_one.getInputFilename(),
- 'TestCases/testScanner/levelOne',
- )
-
- level_two = level_one['levelTwo']
- self.failUnlessEqual(
- level_two.getName(),
- 'levelTwo',
- 'First sub-level tree got %s instead of levelTwo' % level_two.getName(),
- )
- self.failUnlessEqual(level_two.getInputFilename(),
- 'TestCases/testScanner/levelOne/levelTwo',
- )
-
- return
-
- def testPackageTreePath(self):
- scanner = Scanner(['TestCases/testScanner'])
-
- trees = scanner.getPackageTrees()
- expected_tree = trees[0]
-
- dir_one = expected_tree['levelOne']
- dir_one_path = dir_one.getPath()
- self.failUnlessEqual(dir_one_path,
- ('testScanner',
- 'levelOne',
- ))
-
- dir_two = expected_tree['levelOne']['levelTwo']
- dir_two_path = dir_two.getPath()
- self.failUnlessEqual(dir_two_path,
- ('testScanner',
- 'levelOne',
- 'levelTwo',
- ))
-
- module_two = expected_tree['levelOne']['levelTwo']['two.py']
-
- module_two_path = module_two.getPath()
- self.failUnlessEqual(module_two_path,
- ('testScanner',
- 'levelOne',
- 'levelTwo',
- 'two.py',
- ),
- )
- return
-
- def testPackageTreePath(self):
- 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):
- scanner = Scanner(['TestCases/testScanner'], ['ignoreme.py'])
-
- trees = scanner.getPackageTrees()
- level_one = trees[0]['levelOne']
-
- try:
- ignoring = level_one['ignoreme.py']
- except KeyError:
- pass
- else:
- self.fail('Still have ignoreme.py')
-
- return
-
- def testPackageTreeIgnoreTestFiles(self):
- scanner = Scanner(['happydoclib'], ['^tests.py$',
- '^test_.*py$',
- ])
-
- trees = scanner.getPackageTrees()
- level_one = trees[0]
-
- for name in ('tests.py',
- 'test_scanner.py',
- ):
- try:
- ignoring = level_one[name]
- except KeyError:
- pass
- else:
- self.fail('Still have %s' % name)
-
- return
-
- def testPackageTreeName(self):
- 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
-
- def testPackageTreeParent(self):
- tree = PackageTree(None, 'tree1')
- self.failUnlessEqual(None, tree.getParent(),
- 'Parents do not match.')
- return
-
- class ScannerRelativePathTestCase(unittest.TestCase):
-
- def setUp(self):
- cwd = os.getcwd()
- input_dir = os.path.join(cwd, 'TestCases/testScanner')
- scanner = Scanner([input_dir])
-
- trees = scanner.getPackageTrees()
- expected_tree = trees[0]
- self.expected_tree = expected_tree
- return
-
- def testSelf(self):
- target = self.expected_tree['levelOne']['levelTwo']['two.py']
- start = self.expected_tree['levelOne']['levelTwo']['two.py']
-
- relative_path = start.getPathToNode(target)
- self.failUnlessEqual(relative_path,
- (),
- )
- return
-
- def testParentDirOfModuleDir(self):
- target = self.expected_tree['levelOne']
- start = self.expected_tree['levelOne']['levelTwo']['two.py']
-
- relative_path = start.getPathToNode(target)
- self.failUnlessEqual(relative_path,
- ('..',
- ),
- )
- return
-
- def testModuleSameDir(self):
- target = self.expected_tree['levelOne']['one.py']
- start = self.expected_tree['levelOne']['ignoreme.py']
-
- relative_path = start.getPathToNode(target)
- self.failUnlessEqual(relative_path,
- ('one.py',
- ),
- )
- return
-
- def testModuleParentDir(self):
- target = self.expected_tree['levelOne']['one.py']
- start = self.expected_tree['levelOne']['levelTwo']['two.py']
-
- relative_path = start.getPathToNode(target)
- self.failUnlessEqual(relative_path,
- ('..',
- 'one.py',
- ),
- )
- return
-
- def testParentDirOfDir(self):
- target = self.expected_tree['levelOne']
- start = self.expected_tree['levelOne']['levelTwo']
-
- relative_path = start.getPathToNode(target)
- self.failUnlessEqual(relative_path,
- ('..',
- ),
- )
- return
-
-
- class ScannerSummaryAndDocStringTests(unittest.TestCase):
-
- def setUp(self):
- input_dir = os.path.join('TestCases', 'testScanner')
- output_dir = '/tmp/foo'
-
- scanner = Scanner([input_dir])
-
- self.scanner = scanner
- return
-
- def tearDown(self):
- del self.scanner
- return
-
- def testGetReadmeTextForDirectoryInit(self):
- trees = self.scanner.getPackageTrees()
- expected_tree = trees[0]['readme_from_init']
-
- actual, format = expected_tree.getDocStringAndFormat()
-
- expected_format = 'StructuredText'
- expected = 'This is the __init__.py file for readme_from_init.'
-
- self.failUnlessEqual(actual, expected)
- return
-
- def testGetReadmeTextForDirectoryDotTxt(self):
- trees = self.scanner.getPackageTrees()
- expected_tree = trees[0]['readme_from_readme']
-
- actual, format = expected_tree.getDocStringAndFormat()
-
- expected_format = 'StructuredText'
- expected = 'This is the README.txt file for readme_from_readme.\n'
-
- self.failUnlessEqual(actual, expected)
- return
-
- def testGetReadmeTextForDirectoryDotStx(self):
- trees = self.scanner.getPackageTrees()
- expected_tree = trees[0]['readme_from_stx']
-
- actual, format = expected_tree.getDocStringAndFormat()
-
- expected_format = 'StructuredText'
- expected = 'This is the README.stx file for readme_from_stx.\n'
-
- self.failUnlessEqual(actual, expected)
- return
-
- class ScannerFindNodeTestCase(unittest.TestCase):
-
- def setUp(self):
- cwd = os.getcwd()
- input_dir = os.path.join(cwd, 'TestCases/testScanner')
- scanner = Scanner([input_dir])
-
- trees = scanner.getPackageTrees()
- expected_tree = trees[0]
- self.expected_tree = expected_tree
- return
-
- def _testFind(self, name, start, target):
- found = start.findNodeFromDottedName(name)
- if not found:
- self.fail('Did not find anything')
- self.failUnlessEqual(found, target)
- return
-
- def testFindSelf(self):
- self._testFind('levelOne',
- self.expected_tree['levelOne'],
- self.expected_tree['levelOne'],
- )
- return
-
- def testFindChild(self):
- self._testFind('levelTwo',
- self.expected_tree['levelOne'],
- self.expected_tree['levelOne']['levelTwo'],
- )
- return
-
- def testFindSelfDotChild(self):
- self._testFind('levelOne.levelTwo',
- self.expected_tree['levelOne'],
- self.expected_tree['levelOne']['levelTwo'],
- )
- return
-
- def testFindParent(self):
- self._testFind('levelOne',
- self.expected_tree['levelOne']['levelTwo'],
- self.expected_tree['levelOne'],
- )
- return
-
- def testFindSibling(self):
- self._testFind('readme_from_readme',
- self.expected_tree['levelOne'],
- self.expected_tree['readme_from_readme'],
- )
- return
-
- def testFindAunt(self):
- self._testFind('readme_from_readme',
- self.expected_tree['levelOne']['levelTwo'],
- self.expected_tree['readme_from_readme'],
- )
- return
-
- def testFindNeice(self):
- self._testFind('levelOne.levelTwo',
- self.expected_tree['readme_from_readme'],
- self.expected_tree['levelOne']['levelTwo'],
- )
- return
-
- def testFindNotThere(self):
- name = 'levelOne.levelTwo.notThereAtAll'
- start = self.expected_tree['readme_from_readme']
- found = start.findNodeFromDottedName(name)
-
- if found:
- self.fail('Found somethi...
[truncated message content] |