r532 - in zope-docfindertab/branches/upstream/current: . dtml help tests

Fabio Tranchitella kobold at alioth.debian.org
Tue Nov 28 12:32:36 CET 2006


Author: kobold
Date: 2006-11-28 12:32:36 +0100 (Tue, 28 Nov 2006)
New Revision: 532

Added:
   zope-docfindertab/branches/upstream/current/config.py
   zope-docfindertab/branches/upstream/current/patch_inspect.py
   zope-docfindertab/branches/upstream/current/patch_zope.py
   zope-docfindertab/branches/upstream/current/permissions.py
   zope-docfindertab/branches/upstream/current/tests/runalltests.py
   zope-docfindertab/branches/upstream/current/tests/testAnalyse.py
Removed:
   zope-docfindertab/branches/upstream/current/DocFinder/
   zope-docfindertab/branches/upstream/current/Patch.py
   zope-docfindertab/branches/upstream/current/Permissions.py
   zope-docfindertab/branches/upstream/current/funcs.py
   zope-docfindertab/branches/upstream/current/tests/README.txt
Modified:
   zope-docfindertab/branches/upstream/current/CHANGES.txt
   zope-docfindertab/branches/upstream/current/README.txt
   zope-docfindertab/branches/upstream/current/__init__.py
   zope-docfindertab/branches/upstream/current/analyse.py
   zope-docfindertab/branches/upstream/current/dtml/showDocumentation.dtml
   zope-docfindertab/branches/upstream/current/help/README.stx
   zope-docfindertab/branches/upstream/current/tests/framework.py
   zope-docfindertab/branches/upstream/current/tests/testDocFinderTab.py
   zope-docfindertab/branches/upstream/current/version.txt
Log:
Load /tmp/tmp.lqSUR13430/zope-docfindertab-1.0.2 into
zope-docfindertab/branches/upstream/current.


Modified: zope-docfindertab/branches/upstream/current/CHANGES.txt
===================================================================
--- zope-docfindertab/branches/upstream/current/CHANGES.txt	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/CHANGES.txt	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,5 +1,28 @@
+1.0.2
+Print a pretty None.
+
+1.0.1
+Don't show docstring of DateTime attributes.
+
+1.0
+Update to DocFinder 1.0.3.
+Require at least Python 2.3.
+Use logging instead of zLOG.
+Handle Acquisition.Acquired.
+Handle property, staticmethod, and classmethod.
+
+0.5.3
+Minor tweaks to the monkey patch and showDocumentation.dtml.
+Added 'bool' and 'complex' to simple types mapping.
+Don't display zope.interface internal attributes.
+
+0.5.2
+Format roles more nicely, remove duplicates and faux roles, sort.
+You can get the raw representation back by setting FORMAT_ROLES=0
+in config.py.
+
 0.5.0
-Renamed product to DocFinderTab. 
+Renamed product to DocFinderTab.
 Do not display docstrings but names of simple types in Python 2.3
 
 0.4.1

Deleted: zope-docfindertab/branches/upstream/current/Patch.py
===================================================================
--- zope-docfindertab/branches/upstream/current/Patch.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/Patch.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,62 +0,0 @@
-# DocFinderTab 0.5.0
-# (c) 2001-2004, Stefan H. Holek, stefan at epy.co.at
-# http://zope.org/Members/shh/DocFinderTab
-# License: ZPL
-# Zope: 2.3-2.7
-
-# Monkey patch wrapper around Dieter Maurer's DocFinder product
-# http://www.dieter.handshake.de/pyprojects/zope/DocFinder.html
-# Adds a Doc tab to all Zope objects
-
-# Thanks to Dieter for his input on how to make this work with 
-# PythonScripts and ExternalMethods, and for writing DocFinder 
-# in the first place.
-
-__doc__ = 'Add a Doc tab to all Zope objects'
-__version__ = '0.5.0'
-
-__refresh_module__ = 0
-
-try:
-
-    from Globals import HTMLFile
-    from App.Management import Tabs
-    from OFS.SimpleItem import Item
-    from analyse import DocFinder
-    from AccessControl import getSecurityManager
-    from AccessControl.PermissionRole import PermissionRole
-    from Permissions import ViewDocPermission, ViewDocDefaultRoles
-
-    def filtered_manage_options(self, REQUEST=None):
-        # Append a Doc tab to an object's management tabs
-        tabs = self._old_filtered_manage_options(REQUEST)
-        secman = getSecurityManager()
-        if len(tabs) and secman.checkPermission(ViewDocPermission, self.this()):
-            tabs.append( {'label': 'Doc', 
-                          'action': 'showDocumentation', 
-                          'help': ('DocFinderTab', 'README.stx')} )
-        return tabs
-
-    Tabs._old_filtered_manage_options = Tabs.filtered_manage_options
-    Tabs.filtered_manage_options = filtered_manage_options
-
-    showDocumentation = HTMLFile('dtml/showDocumentation', globals())
-
-    def analyseDocumentation(self, object, type='scripter', filter=''):
-        return DocFinder(object, type, filter)
-        
-    ViewDocRoles = PermissionRole(ViewDocPermission, ViewDocDefaultRoles)
-
-    Item.showDocumentation = showDocumentation
-    Item.showDocumentation__roles__ = ViewDocRoles
-    Item.analyseDocumentation = analyseDocumentation
-    Item.analyseDocumentation__roles__ = ViewDocRoles
-
-    from zLOG import LOG, INFO
-    LOG('DocFinderTab', INFO, 'Applied patch version %s.' % __version__)
-
-except:
-
-    import traceback
-    traceback.print_exc()
-

Deleted: zope-docfindertab/branches/upstream/current/Permissions.py
===================================================================
--- zope-docfindertab/branches/upstream/current/Permissions.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/Permissions.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,12 +0,0 @@
-# DocFinderTab 0.5.0
-# (c) 2001-2004, Stefan H. Holek, stefan at epy.co.at
-# http://zope.org/Members/shh/DocFinderTab
-# License: ZPL
-# Zope: 2.3-2.7
-
-__doc__ = 'Add a Doc tab to all Zope objects'
-__version__ = '0.5.0'
-
-ViewDocPermission = 'View documentation'
-ViewDocDefaultRoles = ('Manager',)
- 

Modified: zope-docfindertab/branches/upstream/current/README.txt
===================================================================
--- zope-docfindertab/branches/upstream/current/README.txt	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/README.txt	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,18 +1,18 @@
 
-DocFinderTab 0.5.0
+DocFinderTab 1.0.2
 
 This product ows nearly everything to Dieter Maurer's DocFinder
-product (version 0.4).
+product (version 1.0.3).
 
 http://www.dieter.handshake.de/pyprojects/zope/DocFinder.html
-   
+
 I just put some sugar on it ;-)
 
 To install extract the tarball into your Products directory and
 restart Zope. This will add a "Doc" tab to every object's managment
-screens. Now go to an object's management screen, click the "Doc" 
+screens. Now go to an object's management screen, click the "Doc"
 tab and start exploring.
 
 See the online help for a detailed explanation of what you can
-do with DocFinderTab.
+do with DocFinderTab (or read help/README.txt).
 

Modified: zope-docfindertab/branches/upstream/current/__init__.py
===================================================================
--- zope-docfindertab/branches/upstream/current/__init__.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/__init__.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,8 +1,8 @@
-# DocFinderTab 0.5.0
-# (c) 2001-2004, Stefan H. Holek, stefan at epy.co.at
+# DocFinderTab 1.0.2
+# (c) 2001-2006, Stefan H. Holek, stefan at epy.co.at
 # http://zope.org/Members/shh/DocFinderTab
 # License: ZPL
-# Zope: 2.3-2.7
+# Zope: 2.6-2.10
 
 # Monkey patch wrapper around Dieter Maurer's DocFinder product
 # http://www.dieter.handshake.de/pyprojects/zope/DocFinder.html
@@ -13,12 +13,12 @@
 # in the first place.
 
 __doc__ = 'Add a Doc tab to all Zope objects'
-__version__ = '0.5.0'
+__version__ = '1.0.2'
 
 __refresh_module__ = 0
 
 from AccessControl.Permission import registerPermissions
-from Permissions import ViewDocPermission, ViewDocDefaultRoles
+from permissions import ViewDocPermission, ViewDocDefaultRoles
 
 def initialize(context):
     # Register the helpfile
@@ -29,6 +29,9 @@
     # Register our permission
     registerPermissions(((ViewDocPermission, (), ViewDocDefaultRoles),))
 
+# Apply the inspect module patch
+import patch_inspect
+
 # Apply the DocFinderTab patch
-import Patch
+import patch_zope
 

Modified: zope-docfindertab/branches/upstream/current/analyse.py
===================================================================
--- zope-docfindertab/branches/upstream/current/analyse.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/analyse.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,4 +1,4 @@
-# Copyright (C) 2001 by Dr. Dieter Maurer <dieter at handshake.de>
+# Copyright (C) 2001-2003 by Dr. Dieter Maurer <dieter at handshake.de>
 # D-66386 St. Ingbert, Eichendorffstr. 23, Germany
 #
 #			All Rights Reserved
@@ -8,7 +8,7 @@
 # provided that the above copyright notice and this permission
 # notice appear in all copies, modified copies and in
 # supporting documentation.
-# 
+#
 # Dieter Maurer DISCLAIMS ALL WARRANTIES WITH
 # REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL Dieter Maurer
@@ -25,38 +25,67 @@
 DETAIL_SCRIPTER= 'scripter'
 DETAIL_WEB= 'web'
 
-import sys
+from Products.DocFinderTab.config import FILTER_ROLES   # DFT
+from Products.DocFinderTab.config import FILTER_METHODS # DFT
 
+from inspect import isclass, ismethod, \
+     isfunction, ismethoddescriptor, \
+     getmro, \
+     getargspec, formatargspec, \
+     getcomments
+import re, types
 
-from funcs import func_prop_tuple
-from string import join, replace
-import re
-from types import IntType, DictType
 from AccessControl.SecurityInfo import ClassSecurityInfo, \
      ACCESS_PUBLIC, ACCESS_PRIVATE, ACCESS_NONE
-from ExtensionClass import Base
+from Acquisition import aq_base, Implicit
+from Acquisition import Acquired                # DFT
+from ComputedAttribute import ComputedAttribute # DFT
+from DateTime import DateTime                   # DFT
 
 # DFT
-try:
-    simple_types = {str: 1, unicode: 1, int: 1, float: 1, long: 1,
-                    tuple: 1, list: 1, dict: 1}
-except:
-    simple_types = None
+simple_types = {types.StringType: 1, types.IntType: 1,
+                types.LongType: 1, types.FloatType: 1,
+                types.TupleType: 1, types.ListType: 1,
+                types.DictType: 1, types.NoneType: 1}
 
+try: simple_types[types.UnicodeType] = 1
+except: pass
+try: simple_types[types.BooleanType] = 1
+except: pass
+try: simple_types[types.ComplexType] = 1
+except: pass
+try: simple_types[set] = 1
+except: pass
+try: simple_types[frozenset] = 1
+except: pass
+try: simple_types[ComputedAttribute] = 1
+except: pass
 
-class DocFinder(Base):
+_marker = {}
+
+
+class Doc(Implicit):
   '''determine the documentation of an object.
 
-  Doc is maintained in a two level structure:
+  The documentation is described by a 'Doc' instance.
+  It maintains.
 
-   1 classes, the object is build from, in inheritance order
+   path -- the physical path of the documented object or 'None'
 
-     each class is described by a 'ClassDoc' instance
+   title -- the title of the documented object or ''
 
-   2 for each class, the attributes defined by the class
-     
-     each attribute is described by a 'AttributeDoc' instance.
+   obj -- the documented object
 
+   classes -- a two level sequence structure:
+
+     1. classes, the object is build from, in message resolution order (mro).
+
+        each class is described by a 'ClassDoc' instance
+
+     2. for each class, the attributes defined by the class
+
+        each attribute is described by a 'AttributeDoc' instance.
+
   The documentation does not include instance level attributes
   (they are too many). However, it does provide
   summary information about access to unprotected attributes
@@ -69,18 +98,35 @@
   _classDict= None
 
   _secInfo= ClassSecurityInfo()
-  _secInfo.declarePublic('__getitem__','__len__','tpValues', 'tpId')
+  _secInfo.declarePublic(
+    'ObjToDoc__', 'DocType__', 'DocMethodRe__', 'Path', 'Title',
+    '__getitem__','__len__','tpValues', 'tpId',
+    )
 
   def __init__(self, obj, detail_type=DETAIL_SCRIPTER, method_filter= None):
+    # note info for presentation
+    self._ObjToDoc__= obj
+    self._DocType__= detail_type
+    self._DocMethodRe__= method_filter
+    # path -- either the path to 'obj' or its 'repr'
+    try: path= '/'.join(obj.getPhysicalPath())
+    except AttributeError: path= repr(obj)
+    # work around for a bug in 'string.translate' (does not like empty string)
+    if not path: path='/'
+    self._Path= path
+    # title -- either 'obj.title' or 'obj.Title' or ''
+    try: title= aq_base(obj).title
+    except AttributeError:
+      try: title= aq_base(obj).Title # for CMF
+      except AttributeError: title= ''
+    self._Title= title
     # encode type
     t= detail_type
-    if type(t) == type(''):
+    if isinstance(t, basestring):
       if t == DETAIL_PROGRAMMER: t= 10
       elif t == DETAIL_WEB: t= -10
       else: t= 0
 
-    # print 'DocFinder: ', detail_type, t; sys.stdout.flush()
-
     # try to get a name
     name= None
     i= getattr(obj,'getId',None) or getattr(obj,'id',None) or getattr(obj,'__name__',None)
@@ -97,7 +143,6 @@
 
     # temporary members
     self._obj= obj
-    self._seenclasses= {}
     self._attributes= {}
     self._check= self._makeUnprotectedChecker()
 
@@ -107,24 +152,30 @@
     ic._append(AttributeDoc('-- unprotected attributes --',self._attrRoles(),obj= obj))
     self._classes.append(ic)
 
-    self._analyseClassStructure(c)
+    for cl in _getMro(c): self._analyseClass(cl)
 
     # delete temporaries
     del self._obj
-    del self._seenclasses
     del self._attributes
     del self._check
 
 
+  def ObjToDoc__(self): return self._ObjToDoc__
+  def DocType__(self): return self._DocType__
+  def DocMethodRe__(self): return self._DocMethodRe__
+  def Path(self): return self._Path
+  def Title(self): return self._Title
+
+
   def __getitem__(self,k):
     '''allow access by both integer as well as class names.'''
-    if type(k) is IntType: return self._classes[k]
+    if isinstance(k, int): return self._classes[k]
     if self._classDict is None:
       cd= self._classDict= {}
       for c in self._classes: cd[c._name]= c
-    return self._classDict[k]
+    return self._classDict[k].__of__(self)
 
-  
+
   def __len__(self):
     '''the length of the classes.'''
     return len(self._classes)
@@ -132,38 +183,36 @@
 
   def tpValues(self):
     '''tuple of classes for tree display.'''
-    return tuple(self._classes)
+    return [c.__of__(self) for c in self._classes]
 
   def tpId(self):
     return self._name
 
 
-  def _analyseClassStructure(self, c):
-    '''analyse class *c* including base classes.'''
-
-    if self._seenclasses.has_key(c): return
-    self._seenclasses[c]= None
-
-    self._analyseClass(c)
-
-    for b in c.__bases__:
-      self._analyseClassStructure(b)
-
-
   def _analyseClass(self, c,
                     _omit= {'__doc__': None, '__module__': None,
                             '__allow_access_to_unprotected_subobjects__': None,
-                            'showDocumentation': None,      # DFT
-                            'analyseDocumentation': None,   # DFT
+                            '__dict__': None,                   # DFT
+                            '__weakref__': None,                # DFT
+                            '__slots__': None,                  # DFT
+                            '__slotnames__': None,              # DFT
+                            '__implements__': None,             # DFT
+                            '__implements_advice_data__': None, # DFT
+                            '__implemented__': None,            # DFT
+                            '__provides__': None,               # DFT
+                            '__providedBy__': None,             # DFT
+                            'showDocumentation': None,          # DFT
+                            'analyseDocumentation': None,       # DFT
                             }.has_key,
                     _allow= {'__len__': None,
+                            '__nonzero__': None,    # DFT
                             '__str__': None,
                             '__getitem__': None,
                             '__call__': None,
                             }.has_key,
                     ):
     '''analyse *c*.'''
-    cd= ClassDoc(c.__name__, getattr(c,'__doc__',None),_getLoc(c))
+    cd= ClassDoc(c.__name__, getattr(c,'__doc__',None),_getLoc(c),_getComment(c))
     attributes= self._attributes; seen= attributes.has_key
     check= self._check; o= self._obj; filter= self._method_filter
 
@@ -174,14 +223,14 @@
       if self._type <= 5:
         if k[0] == '_' and not _allow(k): continue
       if filter and not filter(k): continue
-      r= getattr(o,k+'__roles__', check(k))
+      r= getattr(o,k+'__roles__', check(k,v))
       if self._type <= 0 and _isPrivat(r): continue
       # something interesting
       a= AttributeDoc(k,r,v,o)
       if self._type <= -5 and not a.Doc(): continue
       cd._append(a)
 
-    if filter and not cd: return  # DFT
+    if filter and not cd: return    # DFT
     cd._finish()
     self._classes.append(cd)
 
@@ -189,17 +238,16 @@
   def _makeUnprotectedChecker(self):
     roles= getattr(self._obj,'__roles__', ACCESS_PUBLIC)
     allow= getattr(self._obj,'__allow_access_to_unprotected_subobjects__', 0)
-    if type(allow) is IntType:
+    if isinstance(allow, (int, bool)):
       if not allow: roles= ACCESS_PRIVATE
-      def check(name,roles=roles): return roles
-    elif type(allow) is DictType:
-      def check(name, check=allow.get, roles=roles, priv= ACCESS_PRIVATE):
-        if check(name): return roles
+      def check(name, value, roles=roles): return roles
+    elif isinstance(allow, dict):
+      def check(name, value, allow=allow.get, roles=roles, priv= ACCESS_PRIVATE):
+        if allow(name): return roles
         return priv
     else:
-      def check(name, obj= self._obj, allow= allow, roles=roles, priv= ACCESS_PRIVATE):
-        v= getattr(obj,name)
-        if allow(name,v): return roles
+      def check(name, value, allow=allow, roles=roles, priv= ACCESS_PRIVATE):
+        if allow(name, value): return roles
         return priv
     return check
 
@@ -207,17 +255,22 @@
   def _attrRoles(self):
     roles= getattr(self._obj,'__roles__', ACCESS_PUBLIC)
     allow= getattr(self._obj,'__allow_access_to_unprotected_subobjects__', 0)
-    if type(allow) is IntType:
+    if isinstance(allow, (int, bool)):
       if not allow: roles= ACCESS_PRIVATE
-    elif type(allow) is DictType: roles= 'Restricted (Dict)'
+    elif isinstance(allow, dict): roles= 'Restricted (Dict)'
     else: roles= 'Restricted (Func)'
     return roles
 
+  # may be necessary for 'ZTUtils.Tree.TreeMaker'
+  def tpId(self):
+    return self._Path
 
-DocFinder._secInfo.apply(DocFinder)
 
 
-class ClassDoc(Base):
+Doc._secInfo.apply(Doc)
+
+
+class ClassDoc(Implicit):
   """the documentation of a class.
 
   It consists of a 'Name', 'Doc', 'Module' and a list of attributes,
@@ -225,25 +278,28 @@
   """
 
   _secInfo= ClassSecurityInfo()
-  _secInfo.declarePublic('__getitem__','__len__','tpValues', 'tpId', 'Name', 'Doc', 'Module')
+  _secInfo.declarePublic('__getitem__','__len__','tpValues', 'tpId',
+                         'Name', 'Doc', 'Module','Comment', 'FullName',
+                         )
 
   _AttrDict= None
 
-  def __init__(self,name,doc=None,mod=None):
+  def __init__(self,name,doc=None,mod=None,comment=None):
     self._name= name
     self._doc= doc
     self._mod= mod
     self._attrs= []
+    self._comment= comment
 
   def __getitem__(self,k):
     '''allow access by both integer as well as attr names.'''
-    if type(k) is IntType: return self._attrs[k]
+    if isinstance(k, int): return self._attrs[k]
     if self._AttrDict is None:
       cd= self._AttrDict= {}
       for c in self._attrs: cd[c._name]= c
-    return self._AttrDict[k]
+    return self._AttrDict[k].__of__(self)
 
-  
+
   def __len__(self):
     '''the length of the classes.'''
     return len(self._attrs)
@@ -251,7 +307,7 @@
 
   def tpValues(self):
     '''tuple of attributes for tree display.'''
-    return tuple(self._attrs)
+    return [a.__of__(self) for a in self._attrs]
 
   def tpId(self):
     '''use name as id.'''
@@ -270,7 +326,15 @@
     '''the module the class is defined in.'''
     return self._mod
 
+  def Comment(self):
+    '''the comment preceeding the class.'''
+    return self._comment
 
+  def FullName(self):
+    '''the full class name (to be used with 'showCodeFor').'''
+    return '%s.%s' % (self.Module(),self.Name())
+
+
   def _append(self,attr):
     '''append *attr*.'''
     self._attrs.append(attr)
@@ -285,7 +349,7 @@
 
 
 
-class AttributeDoc(Base):
+class AttributeDoc(Implicit):
   """the documentation of an attribute.
 
   It consists of a 'Name', 'Roles', 'Args', 'Doc' and 'Type'.
@@ -294,33 +358,32 @@
   _secInfo= ClassSecurityInfo()
   _secInfo.declarePublic('tpValues', 'tpId',
                          'Name', 'Roles', 'Args', 'Doc', 'Type', 'DocOrType',
-                         'Permission',
+                         'Comment', 'Permission', 'FullName',
                          )
 
   _knownPermission= 0
 
-  def __init__(self,name,roles,value= None, obj= None):
-    if value is not None:
+  def __init__(self,name,roles,value= _marker, obj= None):
+    arguments= doc= comment= type= ''
+    if value is not _marker:
       # determine arguments and documentation, if possible
-      arguments= doc= ''
-      try:
-        (n,a,doc)= func_prop_tuple(value)
-        arguments= join(a,', ')
+      try: arguments= _findArgSpec(value)
       except: pass
-      try: doc= _getDoc(value)  # DFT
+      try: doc= _getDoc(value)        # DFT
       except: pass
+      # determine comment if possible
+      comment= _getComment(value)
       type= _getType(value)
-    else: doc= arguments= type= ''
 
+    try: roles= _getRoles(roles)    # DFT
+    except: pass
     self._name= name
-    if roles is ACCESS_PUBLIC: roles= 'public'
-    elif roles == ACCESS_PRIVATE: roles= 'private'
-    elif roles is ACCESS_NONE: roles= 'none'
     self._roles= roles
     self._arguments= arguments
     self._doc= doc
     self._type= type
     self._obj= obj
+    self._comment= comment
 
   def Name(self):
     '''the attribute name'''
@@ -353,23 +416,31 @@
     '''either the Doc (prefered) or the Type.'''
     return self.Doc() or self.Type()
 
+  def FullName(self):
+    '''the full class name (to be used with 'showCodeFor').'''
+    return '%s.%s' % (self.aq_inner.aq_parent.FullName(),self.Name())
+
   def Permission(self):
     '''return the permission protecting the attribute, 'None' if not directly protected.'''
     if self._knownPermission: return self._permission
     p= None
-    if self._obj:
+    if self._obj is not None:
       name= self._name
       if name[:3] == '-- ': name= ''
       p= _lookup(self._obj, name+'__roles__')
       if p is not None:
         try:
-          p= replace(p[1]._p[1:-11],'_',' ')
+          p= p[1]._p[1:-11].replace('_',' ')
         except: p= '-- explicit --'
     self._permission= p; self._knownPermission= 1
     return p
 
+  def Comment(self):
+    '''the comment preceeding the attribute.'''
+    return self._comment
 
 
+
 AttributeDoc._secInfo.apply(AttributeDoc)
 
 
@@ -381,28 +452,92 @@
   '''return location (module) of class *c*.'''
   return getattr(c,'__module__',None)
 
+def _getComment(obj):
+  '''return comment preceeding *obj*.'''
+  try: return getcomments(obj)
+  except: return ''
 
+
 def _getType(v):
   '''return a nice representation of the *v* type.'''
   tn= type(v).__name__
-  if tn == 'instance': tn= '%s %s' % (v.__class__.__name__,tn)
-  elif tn == 'instance method': tn= '%s %s' % (v.im_class.__name__,tn)
+  if tn == 'instance':
+    tn= '%s %s' % (v.__class__.__name__,tn)
+  elif tn == 'instance method':
+    tn= '%s %s' % (v.im_class.__name__,tn)
   return tn
 
 
 def _getClass(obj):
   '''return the class of *obj*.'''
-  return hasattr(obj,'_klass') and obj._klass or obj.__class__
+  m= {}
+  if getattr(obj,'_klass',m) is not m:
+    return obj._klass
+  else:
+    return obj.__class__
 
 
+_MROCache= {}
+def _getMro(class_):
+  '''*class_* s method resolution order (cached).'''
+  mro= _MROCache.get(class_)
+  if mro is None:
+    mro= _MROCache[class_]= getmro(class_)
+  return mro
+
+
 # DFT
 def _getDoc(obj, simple_types=simple_types):
     '''return the docstring of *obj*.'''
-    if simple_types is not None and type(obj) in simple_types:
-        return _getType(obj)
+    if obj is Acquired:
+        return 'Acquisition.Acquired'
+    if obj is None:
+        return 'None'
+    if isinstance(obj, DateTime):
+        return 'DateTime'
+    if simple_types.has_key(type(obj)) or not _isNonPrimitive(obj):
+        return ''
+    if isinstance(obj, (staticmethod, classmethod)):
+        return obj.__get__(obj).__doc__
+    if FILTER_METHODS:
+        if isfunction(obj) or ismethod(obj) or ismethoddescriptor(obj):
+            if not obj.__doc__: return 'method'
     return obj.__doc__
 
 
+# DFT
+def _getRoles(roles):
+    '''return nice names for *roles*.'''
+    if FILTER_ROLES:
+        if roles is ACCESS_PUBLIC: roles= 'public'
+        elif roles == ACCESS_PRIVATE: roles= 'private'
+        elif roles is ACCESS_NONE: roles= 'none'
+        else: roles= _filterRoles(roles)
+    else:
+        if roles is ACCESS_PUBLIC: roles= 'ACCESS_PUBLIC'
+        elif roles == ACCESS_PRIVATE: roles= 'ACCESS_PRIVATE'
+        elif roles is ACCESS_NONE: roles= 'ACCESS_NONE'
+    return roles
+
+
+# DFT
+def _filterRoles(roles):
+    '''filter out faux roles.'''
+    if not isinstance(roles, (list, tuple)):
+        return roles
+
+    def fauxRole(role):
+        return role.startswith('_') and role.endswith('_Permission')
+
+    unique= {}
+    for role in roles:
+        if not fauxRole(role):
+            unique[role]= 1
+    roles= unique.keys()
+    roles.sort()
+    return '(%s)' % ', '.join(roles)
+
+
 def _lookup(obj,key):
   '''emulate Pythons name lookup; return pair (class,attr) or 'None'.'''
   m= {}
@@ -414,9 +549,27 @@
 
 
 def _lookupClassHierarchy(c,k,m):
-  v= c.__dict__.get(k,m)
-  if v is not m: return (c,v)
-  for c in c.__bases__:
-    v= _lookupClassHierarchy(c,k,m)
-    if v is not None: return v
+  for cl in _getMro(c):
+    v= cl.__dict__.get(k,m)
+    if v is not m: return (cl,v)
   return None
+
+
+def _id(self): return self
+
+def _findArgSpec(maybeFunction):
+  '''the argument specification for *maybeFunction* or an exception.'''
+  if isclass(maybeFunction):
+    maybeFunction= getattr(maybeFunction,'__init__',_id)
+  if isinstance(maybeFunction, (staticmethod, classmethod)):  # DFT
+    maybeFunction= maybeFunction.__get__(maybeFunction)
+  if ismethod(maybeFunction):
+    maybeFunction= maybeFunction.im_func
+  return formatargspec(*getargspec(maybeFunction))[1:-1]    # DFT
+
+try:
+  from ZPublisher.BaseRequest import typeCheck
+  _isNonPrimitive= typeCheck
+except ImportError:
+  def _isNonPrimitive(value): return 1
+

Added: zope-docfindertab/branches/upstream/current/config.py
===================================================================
--- zope-docfindertab/branches/upstream/current/config.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/config.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -0,0 +1,16 @@
+
+# Set to false to make AttributeDoc.Roles()
+# return the raw list or tuple.
+
+FILTER_ROLES = 1
+
+# Set to false to show the "raw" type of
+# methods and method-like attributes.
+
+FILTER_METHODS = 1
+
+# Set to true to enable reST for docstrings
+# (not implemented yet)
+
+DOCSTRINGS_USE_REST = 0
+

Modified: zope-docfindertab/branches/upstream/current/dtml/showDocumentation.dtml
===================================================================
--- zope-docfindertab/branches/upstream/current/dtml/showDocumentation.dtml	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/dtml/showDocumentation.dtml	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,3 +1,4 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <dtml-let target__="_.has_key('ObjToDoc__') and ObjToDoc__ or this()">
 
 <dtml-if "REQUEST.has_key('expert__')">
@@ -22,8 +23,13 @@
   <dtml-call "RESPONSE.setCookie('DF_filter', filter__, path='/')">
 </dtml-if>
 
-<html><head><title>Documentation for object <dtml-var "target__.getId()" html_quote></title>
+<html><head><title>Documentation for <dtml-var "target__.getId()" html_quote></title>
 <dtml-comment> The following is partially ripped from manage_page_header </dtml-comment>
+<dtml-unless management_page_charset>
+<dtml-call "REQUEST.set('management_page_charset','iso-8859-1')">
+</dtml-unless>
+<meta http-equiv="content-type" content="text/html;charset=&dtml-management_page_charset;" />
+<dtml-call "RESPONSE.setHeader('content-type','text/html;charset='+management_page_charset)">
 <dtml-let ag="_.string.lower(REQUEST.get('HTTP_USER_AGENT', ''))"
           find="_.string.find"
           is_nav4="ag[:9]=='mozilla/4' and find(ag,'msie')<0"
@@ -48,37 +54,40 @@
 <style type="text/css">
 <!--
 body                  { background-color: white; }
-form                  { padding: 0; margin: 0; }
+form                  { padding: 0px; margin: 0px; }
 .list-header          { background-color: #6699cc; border: none; }
 .row-hilite           { background-color: #cfcfcf; border: none; }
-.row-normal           { background-color: #efefef; border: none; } 
-                              /* t r  b l */
-.list-header h3       { padding: 0 0  3 0; margin: 0; }
-.list-header p        { padding: 0 0 15 0; margin: 0; }
-.list-header .nodoc   { padding: 0 0 13 0; margin: 0; }
-.list-header .module  { padding: 0 0  6 0; margin: 0; color: black; }
-.row-hilite  p        { padding: 4 2  4 2; margin: 0; }
-.row-normal  p        { padding: 4 2  4 2; margin: 0; }
+.row-normal           { background-color: #efefef; border: none; }
+                              /* t   r    b   l */
+.list-header h3       { padding: 0px 0px  3px 0px; margin: 0px; }
+.list-header p        { padding: 0px 0px 15px 0px; margin: 0px; }
+.list-header .nodoc   { padding: 0px 0px 13px 0px; margin: 0px; }
+.list-header .module  { padding: 0px 0px  6px 0px; margin: 0px; color: black; }
+.row-hilite  p        { padding: 4px 2px  4px 2px; margin: 0px; }
+.row-normal  p        { padding: 4px 2px  4px 2px; margin: 0px; }
 .black                { color: black; }
 .structured-text      { color: #333333; }
-.structured-text h1   { padding: 2 0  2 0; margin: 0; font-size: 12pt; color: #333333; }  
-.structured-text h2   { padding: 2 0  2 0; margin: 0; font-size: 11pt; color: #333333; }  
-.structured-text h3   { padding: 2 0  2 0; margin: 0; font-size: 10pt; color: #333333; }  
-.structured-text h4   { padding: 2 0  2 0: margin: 0; font-size: 10pt; color: #333333; font-style: italic; }  
-.structured-text ul   { margin-top: 5; margin-bottom: 5; font-size: 10pt; color: #333333; }  
-.structured-text ol   { margin-top: 5; margin-bottom: 5; font-size: 10pt; color: #333333; }  
+.structured-text h1   { padding: 2px 0px  2px 0px; margin: 0px; font-size: 12pt; color: #333333; }
+.structured-text h2   { padding: 2px 0px  2px 0px; margin: 0px; font-size: 11pt; color: #333333; }
+.structured-text h3   { padding: 2px 0px  2px 0px; margin: 0px; font-size: 10pt; color: #333333; }
+.structured-text h4   { padding: 2px 0px  2px 0px; margin: 0px; font-size: 10pt; color: #333333; font-style: italic; }
+.structured-text h5   { padding: 2px 0px  2px 0px; margin: 0px; font-size: 10pt; color: #555555; font-style: italic; }
+.structured-text h6   { padding: 2px 0px  2px 0px; margin: 0px; font-size: 10pt; color: #555555; font-style: italic; }
+.structured-text ul   { margin-top: 5px; margin-bottom: 5px; font-size: 10pt; color: #333333; }
+.structured-text ol   { margin-top: 5px; margin-bottom: 5px; font-size: 10pt; color: #333333; }
+.structured-text dl   { margin-top: 5px; margin-bottom: 5px; font-size: 10pt; color: #333333; }
 <dtml-if is_msiewin>
-  .filter-box         { padding: 0; margin: 0; line-height: 10pt; font-size: 8pt; font-family: Arial,Helvetica,sans-serif; height: 13pt; }
-  .expert-box         { margin-left: 0; height: 13pt; }
-  .shortp             { padding-top: 0.8em; margin-top: 0; }
+  .filter-box         { padding: 0px; margin: 0px; line-height: 10pt; font-size: 8pt; font-family: Arial,Helvetica,sans-serif; height: 13pt; }
+  .expert-box         { margin-left: 0px; height: 13pt; }
+  .shortp             { padding-top: 0.8em; margin-top: 0px; }
 <dtml-elif is_win>
-  .filter-box         { padding: 0; margin: 0; line-height: 10pt; font-size: 8pt; font-family: Arial,Helvetica,sans-serif; }
+  .filter-box         { padding: 0px; margin: 0px; line-height: 10pt; font-size: 8pt; font-family: Arial,Helvetica,sans-serif; }
 </dtml-if>
 <dtml-if is_camino>
-  .filter-box         { padding: 0; margin: 0; line-height: 10pt; font-size: 8pt; font-family: Arial,Helvetica,sans-serif; }
-  .expert-box         { margin-top: 1; margin-left: 0; height: 10pt; }
-<dtml-elif is_mozilla> 
-  .expert-box         { margin-top: 1; margin-left: 2; }
+  .filter-box         { padding: 0px; margin: 0px; line-height: 10pt; font-size: 8pt; font-family: Arial,Helvetica,sans-serif; }
+  .expert-box         { margin-top: 1px; margin-left: 0px; height: 10pt; }
+<dtml-elif is_mozilla>
+  .expert-box         { margin-top: 1px; margin-left: 2px; }
 </dtml-if>
 -->
 </style>
@@ -101,7 +110,7 @@
 <form action="&dtml-URL0;">
 <tr valign="top">
   <td class="std-text" width=100%>
-    Documentation for <b><dtml-with "target__"><dtml-var meta_type html_quote></dtml-with></b> object 
+    Documentation for <b><dtml-with "target__"><dtml-var meta_type html_quote></dtml-with></b> object
     <dtml-if "_.hasattr(target__, 'title_and_id')">
       <b><dtml-var "target__.title_and_id()" html_quote></b>
     <dtml-else>
@@ -172,13 +181,11 @@
         </td>
         <td &dtml.-td_args__; width="40%">
           <span class="form-element">
-            <dtml-let doc="Doc()">
-              <dtml-if "doc and _.string.strip(doc)">
-                <span class=structured-text><dtml-var doc fmt="structured-text"></span>
-              <dtml-else>
-                <dtml-if Type><p><dtml-var Type></p><dtml-else>&nbsp;</dtml-if>
-              </dtml-if>
-            </dtml-let>
+            <dtml-if Doc>
+              <span class=structured-text><dtml-var Doc fmt="structured-text"></span>
+            <dtml-else>
+              <dtml-if Type><p><dtml-var Type></p><dtml-else>&nbsp;</dtml-if>
+            </dtml-if>
           </span>
 	<dtml-call "REQUEST.set('row__', row__+1)">
       </dtml-let td_args__>

Deleted: zope-docfindertab/branches/upstream/current/funcs.py
===================================================================
--- zope-docfindertab/branches/upstream/current/funcs.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/funcs.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,77 +0,0 @@
-# Copyright (C) 1997-2001 by Dr. Dieter Maurer <dieter at hit.handshake.de>
-# D-66386 St. Ingbert, Eichendorffstr. 23, Germany
-#
-#			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
-# modified copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation.
-# 
-# Dieter Maurer DISCLAIMS ALL WARRANTIES WITH
-# REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL Dieter Maurer
-# 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.
-"""Function auxiliaries"""
-
-import types, string
-
-# copied from Python header file
-CO_OPTIMIZED = 0x0001
-CO_NEWLOCALS = 0x0002
-CO_VARARGS = 0x0004
-CO_VARKEYWORDS = 0x0008
-
-def func_props(f,detail='a',name=None):
-  """returns a string describing the function, method or class *f*
-
-  *detail* controls how much properties are included:
-    ''		only the functions name
-    'a'		includes the functions arguments
-    'd'	        the functions first line of documentation
-    'D'		includes the functions complete documentation
-    several options can be concatenated"""
-  (n,a,d)= func_prop_tuple(f)
-  if name is None: name= n
-  args= 'a' in detail and '(' + string.join(a,',') + ')' or ''
-  doc= ''
-  if d:
-    if 'D' in detail: doc= '\n  ' + d
-    elif 'd' in detail: doc= ': ' + d
-  return name + args + doc
-
-
-def func_prop_tuple(f):
-  name=f.__name__
-  doc=f.__doc__
-  t=type(f)
-  if t is types.MethodType: f= f.im_func
-  elif t is types.ClassType:
-    try:
-      f= f.__init__.im_func
-      if f.__doc__: doc=f.__doc__
-    except: f= _emptyfunc
-  c=f.func_code
-  n=c.co_argcount
-  a=list(c.co_varnames[:n])
-  if f.func_defaults:
-    i=n-len(f.func_defaults)
-    for d in f.func_defaults:
-      a[i]= a[i] + '=' + repr(d)
-      i= i+1
-  if c.co_flags & CO_VARARGS:
-    a.append('*' + c.co_varnames[n])
-    n= n+1
-  if c.co_flags & CO_VARKEYWORDS:
-    a.append('**' + c.co_varnames[n])
-    n= n+1
-  if t is types.ClassType: del(a[0])
-  return (name, a, doc)
-    
-def _emptyfunc(self): pass    

Modified: zope-docfindertab/branches/upstream/current/help/README.stx
===================================================================
--- zope-docfindertab/branches/upstream/current/help/README.stx	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/help/README.stx	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,14 +1,15 @@
 Release Notes
 
-    DocFinderTab 0.5.0
+    DocFinderTab 1.0.2
 
 Description
 
-    You can use the "Doc" view to ask Zope for documentation about its objects.
+    You can use the **Doc** tab to ask Zope for documentation about its objects.
 
     This product makes Dieter Maurer's 
     <a href="http://www.dieter.handshake.de/pyprojects/zope/DocFinder.html" target=_blank>DocFinder</a>
     available from a ZMI management tab.  
+
     DocFinder's introspection capabilities make it an important part of the Zopista's 
     toolbox:
 
@@ -26,8 +27,8 @@
 
     - **Attribute** names, roles, arguments, and docstrings.
 
-    DocFinder treats docstrings as structured text which allows you to put nicely formatted 
-    documentation right into the source files, while having it available at the click of a mouse.
+    DocFinder treats docstrings as structured text. This allows you to put nicely formatted 
+    documentation right into the source files, while having it instantly availabe TTW.
 
 Controls
 
@@ -53,14 +54,15 @@
 
 Permission Names
 
-    If you start Zope with 'ZOPE_SECURITY_POLICY' set to 'PYTHON', DocFinder will furthermore
-    return the names of **permissions** protecting the individual attributes.
+    Since Zope 2.7 DocFinder returns the names of **permissions** protecting individual attributes.
 
-    If no permission name is available, DocFinder will indicate the presence of an
-    explicit security declaration for the respective attribute (expert mode only).
+    In earlier versions you had to start Zope with 'ZOPE_SECURITY_POLICY' set to 'PYTHON' to
+    see the permission names.
 
+    If no permission name is available, DocFinder will indicate the presence of
+    explicit security declarations for the respective attributes (expert mode only).
+
 Security
 
-    You can control access to the "Doc" tab via the "View documentation" permission.
+    You can control access to the **Doc** tab via the *View documentation* permission.
 
-

Added: zope-docfindertab/branches/upstream/current/patch_inspect.py
===================================================================
--- zope-docfindertab/branches/upstream/current/patch_inspect.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/patch_inspect.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -0,0 +1,38 @@
+# $Id: patch_inspect.py,v 1.2 2006/02/19 22:18:47 stefan Exp $
+'''Monkey patches for 'inspect' to let it recognize Zopes data types.'''
+
+# prevent refreshing as it would introduce loops
+__refresh_module__= 0
+
+
+import inspect
+
+# patch 'ismethod'
+_ismethod= inspect.ismethod
+
+def implementsMethod(object):
+  return _ismethod(object) or \
+         (hasattr(object,'__doc__') \
+          and hasattr(object,'__name__') \
+          and hasattr(object,'im_class') \
+          and hasattr(object,'im_func') \
+          and hasattr(object,'im_self') \
+          and inspect.isfunction(object.im_func) \
+          )
+
+inspect.ismethod= implementsMethod
+
+# Python 2.1 backward compatibility
+if not hasattr(inspect,'getmro'):
+  def getmro(class_):
+    '''the method resolution order for *class_* (as a tuple).'''
+    r= []; queue= [class_]; cls= {}; seen= cls.has_key
+    while queue:
+      cl= queue.pop(0)
+      if seen(cl): continue
+      cls[cl]= None
+      r.append(cl)
+      queue[0:0]= list(cl.__bases__)
+    return tuple(r)
+
+  inspect.getmro= getmro

Added: zope-docfindertab/branches/upstream/current/patch_zope.py
===================================================================
--- zope-docfindertab/branches/upstream/current/patch_zope.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/patch_zope.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -0,0 +1,64 @@
+# DocFinderTab 1.0.2
+# (c) 2001-2006, Stefan H. Holek, stefan at epy.co.at
+# http://zope.org/Members/shh/DocFinderTab
+# License: ZPL
+# Zope: 2.6-2.10
+
+# Monkey patch wrapper around Dieter Maurer's DocFinder product
+# http://www.dieter.handshake.de/pyprojects/zope/DocFinder.html
+# Adds a Doc tab to all Zope objects
+
+# Thanks to Dieter for his input on how to make this work with
+# PythonScripts and ExternalMethods, and for writing DocFinder
+# in the first place.
+
+__doc__ = 'Add a Doc tab to all Zope objects'
+__version__ = '1.0.2'
+
+__refresh_module__ = 0
+
+try:
+
+    from Globals import HTMLFile
+    from App.Management import Tabs
+    from OFS.SimpleItem import Item
+    from analyse import Doc as DocFinder
+    from AccessControl import getSecurityManager
+    from AccessControl.PermissionRole import PermissionRole
+    from permissions import ViewDocPermission, ViewDocDefaultRoles
+    from logging import getLogger
+
+    def filtered_manage_options(self, REQUEST=None):
+        # Append a Doc tab to an object's management tabs
+        tabs = self._old_filtered_manage_options(REQUEST)
+        security = getSecurityManager()
+        if len(tabs) and security.checkPermission(ViewDocPermission, self.this()):
+            tabs.append( {'label': 'Doc',
+                          'action': 'showDocumentation',
+                          'help': ('DocFinderTab', 'README.stx')} )
+        return tabs
+
+    if not hasattr(Tabs, '_old_filtered_manage_options'):
+        Tabs._old_filtered_manage_options = Tabs.filtered_manage_options
+        Tabs.filtered_manage_options = filtered_manage_options
+
+    showDocumentation = HTMLFile('dtml/showDocumentation', globals())
+
+    def analyseDocumentation(self, object, type='scripter', filter=''):
+        return DocFinder(object, type, filter)
+
+    ViewDocRoles = PermissionRole(ViewDocPermission, ViewDocDefaultRoles)
+
+    Item.showDocumentation = showDocumentation
+    Item.showDocumentation__roles__ = ViewDocRoles
+    Item.analyseDocumentation = analyseDocumentation
+    Item.analyseDocumentation__roles__ = ViewDocRoles
+
+    logger = getLogger('DocFinderTab')
+    logger.info('Applied patch version %s.', __version__)
+
+except:
+
+    import traceback
+    traceback.print_exc()
+

Added: zope-docfindertab/branches/upstream/current/permissions.py
===================================================================
--- zope-docfindertab/branches/upstream/current/permissions.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/permissions.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -0,0 +1,12 @@
+# DocFinderTab 1.0.2
+# (c) 2001-2006, Stefan H. Holek, stefan at epy.co.at
+# http://zope.org/Members/shh/DocFinderTab
+# License: ZPL
+# Zope: 2.6-2.10
+
+__doc__ = 'Add a Doc tab to all Zope objects'
+__version__ = '1.0.2'
+
+ViewDocPermission = 'View documentation'
+ViewDocDefaultRoles = ('Manager',)
+

Deleted: zope-docfindertab/branches/upstream/current/tests/README.txt
===================================================================
--- zope-docfindertab/branches/upstream/current/tests/README.txt	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/tests/README.txt	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,14 +0,0 @@
-
-Tests for DocFinderTab
-
-The tests can be run either directly, e.g.
-
-  python testDocFinderTab.py
-
-or with the testrunner utility, e.g.
-
-  python /Zope/utilities/testrunner.py -qa
-
-Note that you must have the ZopeTestCase 
-package installed.
-

Modified: zope-docfindertab/branches/upstream/current/tests/framework.py
===================================================================
--- zope-docfindertab/branches/upstream/current/tests/framework.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/tests/framework.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -1,44 +1,53 @@
 ##############################################################################
 #
-# ZopeTestCase 
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
 #
-# COPY THIS FILE TO YOUR 'tests' DIRECTORY.
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
 #
-# This version of framework.py will use the SOFTWARE_HOME
-# environment variable to locate Zope and the Testing package.
-#
-# If the tests are run in an INSTANCE_HOME installation of Zope,
-# Products.__path__ and sys.path with be adjusted to include the
-# instance's Products and lib/python directories respectively.
-#
-# If you explicitly set INSTANCE_HOME prior to running the tests,
-# auto-detection is disabled and the specified path will be used 
-# instead.
-#
-# If the 'tests' directory contains a custom_zodb.py file, INSTANCE_HOME
-# will be adjusted to use it.
-#
-# If you set the ZEO_INSTANCE_HOME environment variable a ZEO setup 
-# is assumed, and you can attach to a running ZEO server (via the 
-# instance's custom_zodb.py).
-#
 ##############################################################################
-#
-# The following code should be at the top of every test module:
-#
-# import os, sys
-# if __name__ == '__main__':
-#     execfile(os.path.join(sys.path[0], 'framework.py'))
-#
-# ...and the following at the bottom:
-#
-# if __name__ == '__main__':
-#     framework()
-#
-##############################################################################
+"""ZopeTestCase framework
 
-__version__ = '0.2.3'
+COPY THIS FILE TO YOUR 'tests' DIRECTORY.
 
+This version of framework.py will use the SOFTWARE_HOME
+environment variable to locate Zope and the Testing package.
+
+If the tests are run in an INSTANCE_HOME installation of Zope,
+Products.__path__ and sys.path with be adjusted to include the
+instance's Products and lib/python directories respectively.
+
+If you explicitly set INSTANCE_HOME prior to running the tests,
+auto-detection is disabled and the specified path will be used 
+instead.
+
+If the 'tests' directory contains a custom_zodb.py file, INSTANCE_HOME
+will be adjusted to use it.
+
+If you set the ZEO_INSTANCE_HOME environment variable a ZEO setup 
+is assumed, and you can attach to a running ZEO server (via the 
+instance's custom_zodb.py).
+
+The following code should be at the top of every test module:
+
+  import os, sys
+  if __name__ == '__main__':
+      execfile(os.path.join(sys.path[0], 'framework.py'))
+
+...and the following at the bottom:
+
+  if __name__ == '__main__':
+      framework()
+
+$Id: framework.py,v 1.3 2006/02/18 15:43:19 stefan Exp $
+"""
+
+__version__ = '0.2.4'
+
 # Save start state
 #
 __SOFTWARE_HOME = os.environ.get('SOFTWARE_HOME', '')

Added: zope-docfindertab/branches/upstream/current/tests/runalltests.py
===================================================================
--- zope-docfindertab/branches/upstream/current/tests/runalltests.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/tests/runalltests.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -0,0 +1,48 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Runs all tests in the current directory [and below]
+
+Execute like:
+  python runalltests.py [-R]
+
+$Id: runalltests.py,v 1.1 2006/02/18 15:43:19 stefan Exp $
+"""
+
+__version__ = '0.3.1'
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+import unittest
+TestRunner = unittest.TextTestRunner
+suite = unittest.TestSuite()
+
+def test_finder(recurse, dir, names):
+    if dir == os.curdir or '__init__.py' in names:
+        parts = [x for x in dir[len(os.curdir):].split(os.sep) if x]
+        tests = [x for x in names if x.startswith('test') and x.endswith('.py')]
+        for test in tests:
+            modpath = parts + [test[:-3]]
+            m = __import__('.'.join(modpath))
+            for part in modpath[1:]:
+                m = getattr(m, part)
+            if hasattr(m, 'test_suite'):
+                suite.addTest(m.test_suite())
+    if not recurse:
+        names[:] = []
+
+if __name__ == '__main__':
+    os.path.walk(os.curdir, test_finder, '-R' in sys.argv)
+    TestRunner().run(suite)
+

Added: zope-docfindertab/branches/upstream/current/tests/testAnalyse.py
===================================================================
--- zope-docfindertab/branches/upstream/current/tests/testAnalyse.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/tests/testAnalyse.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -0,0 +1,472 @@
+#
+# Test analyse
+#
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing import ZopeTestCase
+
+ZopeTestCase.installProduct('DocFinderTab')
+
+from Products.DocFinderTab.analyse import DETAIL_PROGRAMMER
+from Products.DocFinderTab.analyse import Doc
+
+from Acquisition import Acquired, aq_base
+from ComputedAttribute import ComputedAttribute
+from OFS.SimpleItem import SimpleItem
+from ExtensionClass import Base as ExtensionClass
+from DateTime import DateTime
+
+from inspect import ismethod, isfunction
+from inspect import ismethoddescriptor, isdatadescriptor
+from types import NoneType
+
+import sys
+PYTHON24 = sys.version_info >= (2, 4)
+NEWSTYLE = issubclass(ExtensionClass, object)
+
+
+def _func(self): pass
+
+def _deco(func):
+    def wrapper(self, *__args, **__kw):
+        return func(self, *__args, **__kw)
+    if PYTHON24:
+        # __name__ is read-only in Python 2.3
+        wrapper.__name__ = func.__name__
+    wrapper.__dict__ = func.__dict__
+    wrapper.__doc__ = func.__doc__
+    return wrapper
+
+class Base(SimpleItem):
+    def _basemethod(self): pass
+
+class Foreign(SimpleItem):
+    def _foreignmethod(self): pass
+
+class Object(Base):
+
+    _str = ''
+    _int = 1
+    _long = 1L
+    _float = 1.0
+    _tuple = ()
+    _list = []
+    _dict = {}
+    _unicode = u''
+    _bool = True
+    _complex = 3.14j
+    _none = None
+    _datetime = DateTime()
+
+    if PYTHON24:
+        _set = set([])
+        _frozenset = frozenset([])
+
+    _acquired = Acquired
+
+    def __computed(self): pass
+    _computed = ComputedAttribute(__computed)
+
+    def __property_get(self): pass
+    def __property_set(self, x): pass
+    _property = property(__property_get, __property_set)
+
+    def _method(self): pass
+    _function = _func
+    _basemethod = Base._basemethod
+    _foreignmethod = Foreign._foreignmethod
+    _basefunc = Base._basemethod.im_func
+    _foreignfunc = Foreign._foreignmethod.im_func
+
+    def __staticmethod(x): pass
+    _staticmethod = staticmethod(__staticmethod)
+
+    def __classmethod(cls, x): pass
+    _classmethod = classmethod(__classmethod)
+
+    _instance = Base()
+
+    # Python 2.3 compatible decorator syntax
+    def __decorated(self): pass
+    _decorated = _deco(__decorated)
+
+    # Python 2.3 compatible decorator syntax
+    def __docdecorated(self):
+        'decorated'
+    _docdecorated = _deco(__docdecorated)
+
+    def __init__(self, id):
+        self.id = id
+
+    def getitem(self, attr):
+        return self.__class__.__dict__[attr]
+
+    def getdoc(self, attr):
+        doc = Doc(self, DETAIL_PROGRAMMER)
+        for c in doc:
+            if c.Name() == 'Object':
+                for a in c:
+                    if a.Name() == attr:
+                        return a
+        return None
+
+
+class TestAnalyse(ZopeTestCase.ZopeTestCase):
+    """ExtensionClass is a new-style class
+    """
+
+    def afterSetUp(self):
+        self.folder._setObject('ob', Object('ob'))
+        self.ob = self.folder.ob
+
+    def testDummy(self):
+        pass
+
+    def testNewStyleClass(self):
+        self.failUnless(issubclass(Object, object))
+
+    def testNewStyleExtensionClass(self):
+        self.failUnless(issubclass(ExtensionClass, object))
+
+    def testStringType(self):
+        self.failUnless(isinstance(self.ob._str, str))
+        self.failUnless(isinstance(self.ob._str, basestring))
+        self.assertEqual(self.ob.getdoc('_str').Type(), 'str')
+        self.assertEqual(self.ob.getdoc('_str').Doc(), '')
+
+    def testIntType(self):
+        self.failUnless(isinstance(self.ob._int, int))
+        self.failIf(isinstance(self.ob._int, long))
+        self.assertEqual(self.ob.getdoc('_int').Type(), 'int')
+        self.assertEqual(self.ob.getdoc('_int').Doc(), '')
+
+    def testLongType(self):
+        self.failUnless(isinstance(self.ob._long, long))
+        self.failIf(isinstance(self.ob._long, int))
+        self.assertEqual(self.ob.getdoc('_long').Type(), 'long')
+        self.assertEqual(self.ob.getdoc('_long').Doc(), '')
+
+    def testFloatType(self):
+        self.failUnless(isinstance(self.ob._float, float))
+        self.assertEqual(self.ob.getdoc('_float').Type(), 'float')
+        self.assertEqual(self.ob.getdoc('_float').Doc(), '')
+
+    def testListType(self):
+        self.failUnless(isinstance(self.ob._list, list))
+        self.assertEqual(self.ob.getdoc('_list').Type(), 'list')
+        self.assertEqual(self.ob.getdoc('_list').Doc(), '')
+
+    def testTupleType(self):
+        self.failUnless(isinstance(self.ob._tuple, tuple))
+        self.assertEqual(self.ob.getdoc('_tuple').Type(), 'tuple')
+        self.assertEqual(self.ob.getdoc('_tuple').Doc(), '')
+
+    def testDictType(self):
+        self.failUnless(isinstance(self.ob._dict, dict))
+        self.assertEqual(self.ob.getdoc('_dict').Type(), 'dict')
+        self.assertEqual(self.ob.getdoc('_dict').Doc(), '')
+
+    def testUnicodeType(self):
+        self.failUnless(isinstance(self.ob._unicode, unicode))
+        self.failUnless(isinstance(self.ob._unicode, basestring))
+        self.assertEqual(self.ob.getdoc('_unicode').Type(), 'unicode')
+        self.assertEqual(self.ob.getdoc('_unicode').Doc(), '')
+
+    def testBooleanType(self):
+        self.failUnless(isinstance(self.ob._bool, bool))
+        self.failUnless(isinstance(self.ob._bool, int))
+        self.assertEqual(self.ob.getdoc('_bool').Type(), 'bool')
+        self.assertEqual(self.ob.getdoc('_bool').Doc(), '')
+
+    def testComplexType(self):
+        self.failUnless(isinstance(self.ob._complex, complex))
+        self.assertEqual(self.ob.getdoc('_complex').Type(), 'complex')
+        self.assertEqual(self.ob.getdoc('_complex').Doc(), '')
+
+    def testNoneType(self):
+        self.failUnless(isinstance(self.ob._none, NoneType))
+        self.assertEqual(self.ob.getdoc('_none').Type(), 'NoneType')
+        self.assertEqual(self.ob.getdoc('_none').Doc(), 'None')
+
+    def testDateTime(self):
+        self.failUnless(isinstance(self.ob._datetime, DateTime))
+        self.assertEqual(self.ob.getdoc('_datetime').Type(), 'DateTime instance')
+        self.assertEqual(self.ob.getdoc('_datetime').Doc(), 'DateTime')
+
+    if PYTHON24:
+        def testSetType(self):
+            self.failUnless(isinstance(self.ob._set, set))
+            self.failIf(isinstance(self.ob._set, frozenset))
+            self.assertEqual(self.ob.getdoc('_set').Type(), 'set')
+            self.assertEqual(self.ob.getdoc('_set').Doc(), '')
+
+        def testFrozenSetType(self):
+            self.failUnless(isinstance(self.ob._frozenset, frozenset))
+            self.failIf(isinstance(self.ob._frozenset, set))
+            self.assertEqual(self.ob.getdoc('_frozenset').Type(), 'frozenset')
+            self.assertEqual(self.ob.getdoc('_frozenset').Doc(), '')
+
+    def testAcquiredType(self):
+        # Acquisition.Acquired is a marker object and not a type!
+        self.assertEqual(self.ob.getitem('_acquired'), Acquired)
+        self.assertEqual(self.ob.getdoc('_acquired').Type(), 'str')
+        self.assertEqual(self.ob.getdoc('_acquired').Doc(), 'Acquisition.Acquired')
+
+    def testComputedAttributeType(self):
+        self.assertEqual(type(self.ob.getitem('_computed')), ComputedAttribute)
+        self.assertEqual(self.ob.getdoc('_computed').Type(), 'ComputedAttribute')
+        self.assertEqual(self.ob.getdoc('_computed').Doc(), '')
+
+    def testPropertyType(self):
+        self.failUnless(isinstance(self.ob.getitem('_property'), property))
+        self.failUnless(isdatadescriptor(self.ob.getitem('_property')))
+        self.assertEqual(self.ob.getdoc('_property').Type(), 'property')
+        self.assertEqual(self.ob.getdoc('_property').Doc(), None)
+        #item = self.ob.getitem('_property')
+        #print dir(item)
+        #print item.fget, item.fset, item.fdel, item.__doc__
+
+    def testMethodType(self):
+        self.failUnless(ismethod(self.ob._method))
+        self.assertEqual(type(self.ob._method).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_method')))
+        self.assertEqual(type(self.ob.getitem('_method')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_method').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_method').Doc(), 'method')
+
+    def testFunctionType(self):
+        self.failUnless(ismethod(self.ob._function))
+        self.assertEqual(type(self.ob._function).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_function')))
+        self.assertEqual(type(self.ob.getitem('_function')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_method').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_method').Doc(), 'method')
+
+    def testBaseMethodType(self):
+        self.failUnless(ismethod(self.ob._basemethod))
+        self.assertEqual(type(self.ob._basemethod).__name__, 'instancemethod')
+
+        self.failUnless(ismethod(self.ob.getitem('_basemethod')))
+        self.assertEqual(type(self.ob.getitem('_basemethod')).__name__, 'instancemethod')
+
+        self.assertEqual(self.ob.getdoc('_basemethod').Type(), 'instancemethod')
+        self.assertEqual(self.ob.getdoc('_basemethod').Doc(), 'method')
+
+    def testBaseFuncType(self):
+        self.failUnless(ismethod(self.ob._basefunc))
+        self.assertEqual(type(self.ob._basefunc).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_basefunc')))
+        self.assertEqual(type(self.ob.getitem('_basefunc')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_basefunc').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_basefunc').Doc(), 'method')
+
+    def testForeignMethodType(self):
+        self.failUnless(ismethod(self.ob._foreignmethod))
+        self.assertEqual(type(self.ob._foreignmethod).__name__, 'instancemethod')
+
+        self.failUnless(ismethod(self.ob.getitem('_foreignmethod')))
+        self.assertEqual(type(self.ob.getitem('_foreignmethod')).__name__, 'instancemethod')
+
+        self.assertEqual(self.ob.getdoc('_foreignmethod').Type(), 'instancemethod')
+        self.assertEqual(self.ob.getdoc('_foreignmethod').Doc(), 'method')
+
+    def testForeignFuncType(self):
+        self.failUnless(ismethod(self.ob._foreignfunc))
+        self.assertEqual(type(self.ob._foreignfunc).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_foreignfunc')))
+        self.assertEqual(type(self.ob.getitem('_foreignfunc')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_foreignfunc').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_foreignfunc').Doc(), 'method')
+
+    def testStaticMethodType(self):
+        self.failUnless(isfunction(self.ob._staticmethod))
+        self.assertEqual(type(self.ob._staticmethod).__name__, 'function')
+
+        self.failUnless(ismethoddescriptor(self.ob.getitem('_staticmethod')))
+        self.failUnless(isinstance(self.ob.getitem('_staticmethod'), staticmethod))
+        self.assertEqual(type(self.ob.getitem('_staticmethod')).__name__, 'staticmethod')
+
+        self.assertEqual(self.ob.getdoc('_staticmethod').Type(), 'staticmethod')
+        self.assertEqual(self.ob.getdoc('_staticmethod').Doc(), None)
+        #item = self.ob.getitem('_staticmethod')
+        #print dir(item)
+        #print item.__get__(item).__name__
+
+    def testClassMethodType(self):
+        self.failUnless(ismethod(self.ob._classmethod))
+        self.assertEqual(type(self.ob._classmethod).__name__, 'instancemethod')
+
+        self.failUnless(ismethoddescriptor(self.ob.getitem('_classmethod')))
+        self.failUnless(isinstance(self.ob.getitem('_classmethod'), classmethod))
+        self.assertEqual(type(self.ob.getitem('_classmethod')).__name__, 'classmethod')
+
+        self.assertEqual(self.ob.getdoc('_classmethod').Type(), 'classmethod')
+        self.assertEqual(self.ob.getdoc('_classmethod').Doc(), None)
+        #item = self.ob.getitem('_classmethod')
+        #print dir(item)
+        #print item.__get__(item).__name__
+
+    def testInstanceType(self):
+        self.failUnless(isinstance(self.ob._instance, Base))
+        self.assertEqual(self.ob.getdoc('_instance').Type(), 'Base')
+        #self.assertEqual(self.ob.getdoc('_instance').Doc(), None)
+
+    def testDecoratedType(self):
+        self.failUnless(ismethod(self.ob._decorated))
+        self.assertEqual(type(self.ob._decorated).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_decorated')))
+        self.assertEqual(type(self.ob.getitem('_decorated')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_decorated').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_decorated').Doc(), 'method')
+
+    def testDocDecoratedType(self):
+        self.failUnless(ismethod(self.ob._docdecorated))
+        self.assertEqual(type(self.ob._docdecorated).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_docdecorated')))
+        self.assertEqual(type(self.ob.getitem('_docdecorated')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_docdecorated').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_docdecorated').Doc(), 'decorated')
+
+
+class TestAnalyseClassic(TestAnalyse):
+    """ExtensionClass is a classic class
+
+       The method-ish types look slightly different. In fact, stuff like
+       properties won't even work with classic classes.
+    """
+
+    def testNewStyleClass(self):
+        self.failIf(issubclass(Object, object))
+
+    def testNewStyleExtensionClass(self):
+        self.failIf(issubclass(ExtensionClass, object))
+
+    def testMethodType(self):
+        self.failUnless(ismethod(self.ob._method))
+        #self.assertEqual(type(self.ob._method).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_method')))
+        self.assertEqual(type(self.ob.getitem('_method')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_method').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_method').Doc(), 'method')
+
+    def testFunctionType(self):
+        self.failUnless(ismethod(self.ob._function))
+        #self.assertEqual(type(self.ob._function).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_function')))
+        self.assertEqual(type(self.ob.getitem('_function')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_method').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_method').Doc(), 'method')
+
+    def testBaseMethodType(self):
+        self.failUnless(ismethod(self.ob._basemethod))
+        #self.assertEqual(type(self.ob._basemethod).__name__, 'instancemethod')
+
+        self.failUnless(ismethod(self.ob.getitem('_basemethod')))
+        #self.assertEqual(type(self.ob.getitem('_basemethod')).__name__, 'instancemethod')
+
+        #self.assertEqual(self.ob.getdoc('_basemethod').Type(), 'instancemethod')
+        self.assertEqual(self.ob.getdoc('_basemethod').Doc(), 'method')
+
+    def testBaseFuncType(self):
+        self.failUnless(ismethod(self.ob._basefunc))
+        #self.assertEqual(type(self.ob._basefunc).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_basefunc')))
+        self.assertEqual(type(self.ob.getitem('_basefunc')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_basefunc').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_basefunc').Doc(), 'method')
+
+    def testForeignMethodType(self):
+        self.failUnless(ismethod(self.ob._foreignmethod))
+        #self.assertEqual(type(self.ob._foreignmethod).__name__, 'instancemethod')
+
+        self.failUnless(ismethod(self.ob.getitem('_foreignmethod')))
+        #self.assertEqual(type(self.ob.getitem('_foreignmethod')).__name__, 'instancemethod')
+
+        #self.assertEqual(self.ob.getdoc('_foreignmethod').Type(), 'instancemethod')
+        self.assertEqual(self.ob.getdoc('_foreignmethod').Doc(), 'method')
+
+    def testForeignFuncType(self):
+        self.failUnless(ismethod(self.ob._foreignfunc))
+        #self.assertEqual(type(self.ob._foreignfunc).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_foreignfunc')))
+        self.assertEqual(type(self.ob.getitem('_foreignfunc')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_foreignfunc').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_foreignfunc').Doc(), 'method')
+
+    def testStaticMethodType(self):
+        #self.failUnless(isfunction(self.ob._staticmethod))
+        #self.assertEqual(type(self.ob._staticmethod).__name__, 'function')
+
+        self.failUnless(ismethoddescriptor(self.ob.getitem('_staticmethod')))
+        self.failUnless(isinstance(self.ob.getitem('_staticmethod'), staticmethod))
+        self.assertEqual(type(self.ob.getitem('_staticmethod')).__name__, 'staticmethod')
+
+        self.assertEqual(self.ob.getdoc('_staticmethod').Type(), 'staticmethod')
+        self.assertEqual(self.ob.getdoc('_staticmethod').Doc(), None)
+
+    def testClassMethodType(self):
+        #self.failUnless(ismethod(self.ob._classmethod))
+        #self.assertEqual(type(self.ob._classmethod).__name__, 'instancemethod')
+
+        self.failUnless(ismethoddescriptor(self.ob.getitem('_classmethod')))
+        self.failUnless(isinstance(self.ob.getitem('_classmethod'), classmethod))
+        self.assertEqual(type(self.ob.getitem('_classmethod')).__name__, 'classmethod')
+
+        self.assertEqual(self.ob.getdoc('_classmethod').Type(), 'classmethod')
+        self.assertEqual(self.ob.getdoc('_classmethod').Doc(), None)
+
+    def testDecoratedType(self):
+        self.failUnless(ismethod(self.ob._decorated))
+        #self.assertEqual(type(self.ob._decorated).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_decorated')))
+        self.assertEqual(type(self.ob.getitem('_decorated')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_decorated').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_decorated').Doc(), 'method')
+
+    def testDocDecoratedType(self):
+        self.failUnless(ismethod(self.ob._docdecorated))
+        #self.assertEqual(type(self.ob._docdecorated).__name__, 'instancemethod')
+
+        self.failUnless(isfunction(self.ob.getitem('_docdecorated')))
+        self.assertEqual(type(self.ob.getitem('_docdecorated')).__name__, 'function')
+
+        self.assertEqual(self.ob.getdoc('_docdecorated').Type(), 'function')
+        self.assertEqual(self.ob.getdoc('_docdecorated').Doc(), 'decorated')
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    if NEWSTYLE:
+        suite.addTest(makeSuite(TestAnalyse))
+    else:
+        suite.addTest(makeSuite(TestAnalyseClassic))
+    return suite
+
+if __name__ == '__main__':
+    framework()

Modified: zope-docfindertab/branches/upstream/current/tests/testDocFinderTab.py
===================================================================
--- zope-docfindertab/branches/upstream/current/tests/testDocFinderTab.py	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/tests/testDocFinderTab.py	2006-11-28 11:32:36 UTC (rev 532)
@@ -8,16 +8,16 @@
 
 from Testing import ZopeTestCase
 
+ZopeTestCase.installProduct('DocFinderTab')
+
 from AccessControl import Unauthorized
-from Products.DocFinderTab.Permissions import ViewDocPermission
+from Products.DocFinderTab.permissions import ViewDocPermission
 
 standard_permissions = ZopeTestCase.standard_permissions
-access_permissions   = [ViewDocPermission] 
-all_permissions      = standard_permissions+access_permissions
+access_permissions = [ViewDocPermission]
+all_permissions = standard_permissions + access_permissions
 
-ZopeTestCase.installProduct('DocFinderTab')
 
-
 class TestDocFinderTab(ZopeTestCase.ZopeTestCase):
 
     def test_00_ItemPatched(self):
@@ -33,7 +33,7 @@
             dummy = self.folder.restrictedTraverse('showDocumentation')
         except Unauthorized:
             self.fail('Access to showDocumentation was denied')
-            
+
     def test_02_AccessDenied(self):
         'showDocumentation should be protected'
         self.setPermissions(standard_permissions)
@@ -43,7 +43,7 @@
             pass
         else:
             self.fail('Access to showDocumentation was allowed')
-            
+
     def test_03_ManagerAccessAllowed(self):
         'showDocumentation should be accessible to Managers'
         self.setRoles(['Manager'])
@@ -51,7 +51,7 @@
             dummy = self.folder.restrictedTraverse('showDocumentation')
         except Unauthorized:
             self.fail('Access to showDocumentation was denied to Manager')
-            
+
     def test_04_ManagerAccessDenied(self):
         'showDocumentation should be protected from Managers'
         self.folder.manage_permission(ViewDocPermission, ['Owner'], acquire=0)
@@ -62,7 +62,7 @@
             pass
         else:
             self.fail('Access to showDocumentation was allowed to Manager')
-            
+
     def test_05_AccessAllowed(self):
         'analyseDocumentation should be accessible'
         self.setPermissions(standard_permissions+access_permissions)
@@ -70,7 +70,7 @@
             dummy = self.folder.restrictedTraverse('analyseDocumentation')
         except Unauthorized:
             self.fail('Access to analyseDocumentation was denied')
-            
+
     def test_06_AccessDenied(self):
         'analyseDocumentation should be protected'
         self.setPermissions(standard_permissions)
@@ -80,7 +80,7 @@
             pass
         else:
             self.fail('Access to analyseDocumentation was allowed')
-            
+
     def test_07_ManagerAccessAllowed(self):
         'analyseDocumentation should be accessible to Managers'
         self.setRoles(['Manager'])
@@ -88,7 +88,7 @@
             dummy = self.folder.restrictedTraverse('analyseDocumentation')
         except Unauthorized:
             self.fail('Access to analyseDocumentation was denied to Manager')
-            
+
     def test_08_ManagerAccessDenied(self):
         'analyseDocumentation should be protected from Managers'
         self.folder.manage_permission(ViewDocPermission, ['Owner'], acquire=0)
@@ -99,13 +99,13 @@
             pass
         else:
             self.fail('Access to analyseDocumentation was allowed to Manager')
-            
+
     # b/w compatibility clutch
     if not hasattr(ZopeTestCase.ZopeTestCase, 'setPermissions'):
         setPermissions = ZopeTestCase.ZopeTestCase._setPermissions
         setRoles = ZopeTestCase.ZopeTestCase._setRoles
 
-            
+
 def test_suite():
     from unittest import TestSuite, makeSuite
     suite = TestSuite()

Modified: zope-docfindertab/branches/upstream/current/version.txt
===================================================================
--- zope-docfindertab/branches/upstream/current/version.txt	2006-11-28 11:30:48 UTC (rev 531)
+++ zope-docfindertab/branches/upstream/current/version.txt	2006-11-28 11:32:36 UTC (rev 532)
@@ -1 +1 @@
-0.5.0
+1.0.2




More information about the pkg-zope-commits mailing list