[Zope-Checkins] CVS: Zope2 - HelpContext.py:1.1.2.1 ProductHelp.py:1.1.2.1 Util.py:1.1.2.1 APIHelpTopic.py:1.10.32.1 HelpSys.py:1.19.32.1 HelpTopic.py:1.13.6.1 __init__.py:1.4.160.1

Michel Pelletier michel@digicool.com
Thu, 17 May 2001 12:00:13 -0400 (EDT)


Update of /cvs-repository/Zope2/lib/python/HelpSys
In directory korak.digicool.com:/tmp/cvs-serv10291

Modified Files:
      Tag: APIDocs-branch
	APIHelpTopic.py HelpSys.py HelpTopic.py __init__.py 
Added Files:
      Tag: APIDocs-branch
	HelpContext.py ProductHelp.py Util.py 
Log Message:
first whack at framework docs interface


--- Added File HelpContext.py in package Zope2 ---

_registry = []
global _registry

class HelpContext:

    """ Core packages must register themsevles at import time, but
    they can't be loaded into the ZODB then because the database may
    not even be open (and the database may itself want to register
    help!).  This context maintains a registry of packages that want
    to provide help in Zope's help system.  After Product registration,
    an extra step will ge taken to tool through this registry and
    add ProductHelp objects to the top level 'HelpSys' container.
    """

    def registerHelp(self, package):
        _registry.append(package)
        

    

--- Added File ProductHelp.py in package Zope2 ---
import Acquisition
from OFS.ObjectManager import ObjectManager
from OFS.SimpleItem import Item
from Persistence import Persistent
import Globals
from Globals import Persistent, DTMLFile, HTML
from Products.ZCatalog.ZCatalog import ZCatalog
from Products.ZCatalog.Lazy import LazyCat
from KWHierarchy import KWHierarchy
import HelpTopic

class TreeCollection:
    """
    A temporary wrapper for a collection of objects
    objects, used for help topic browsing to make a collection
    of objects appear as a single object.
    """

    def __init__(self, id, objs, simple=1):
        self.id=self.title=id
        self.objs=objs
        self.simple=simple
        
    def tpValues(self):
        values=[]
        if self.simple:
            values=self.objs
        else:
            for obj in self.objs:
                values=values + list(obj.tpValues())
        # resolve overlap
        ids={}
        for value in values:
            if ids.has_key(value.id):
                ids[value.id].append(value)
            else:
                ids[value.id]=[value]
        results=[]
        for k,v in ids.items():
            if len(v)==1:
                results.append(v[0])
            else:
                values=[]
                for topic in v:
                    values=values + list(topic.tpValues())
                results.append(TreeCollection(k, values)) 
        results.sort(lambda x, y: cmp(x.id, y.id))
        return results

    def tpId(self):
        return self.id

def addProductHelp(self, id='Help', title=''):
    h = ProductHelp(id, title)
    self._setObject(id, h)
    

class ProductHelp(Acquisition.Implicit, ObjectManager, Item, Persistent):
    """
    Manages a collection of Help Topics for a given Product.
    
    Provides searching services to HelpSystem.
    """

    meta_type='Product Help'
    icon='p_/ProductHelp_icon'

    lastRegistered=None
    
    meta_types=({'name':'Help Topic',
                 'action':'addTopicForm',
                 'permission':'Add Documents, Images, and Files'},
                )

    manage_options=(
        ObjectManager.manage_options +
        Item.manage_options
        )

    __ac_permissions__=(
        ('Add Documents, Images, and Files', ('addTopicForm', 'addTopic')),
        ('View managment screens', ('index_html', '')),
        )
    
    def __init__(self, id='Help', title=''):
        self.id=id
        self.title=title
        self.catalog=ZCatalog('catalog')
        c=self.catalog._catalog
        # clear catalog
        for index in c.indexes.keys():
            c.delIndex(index)
        for col in c.schema.keys():
            c.delColumn(col)
        c.addIndex('SearchableText', 'TextIndex')
        c.addIndex('categories', 'KeywordIndex') # we'll keep this here for now

##         c.indexes['categories'] = KWHierarchy('keywords', 'Keyword Hierarchy',
##                                                      c.data, c.schema.keys(), [])
        
        c.addIndex('permissions', 'KeywordIndex')
        c.addColumn('categories')
        c.addColumn('permissions')
        c.addColumn('title_or_id')
        c.addColumn('url')
        c.addColumn('id')

    index_html=DTMLFile('dtml/index_html', globals())

    addTopicForm=DTMLFile('dtml/addTopic', globals())

    def addTopic(self, id, title=None, REQUEST=None):
        "Add a Help Topic"
        if type(id) is type(""):
            topic=HelpTopic.DTMLDocumentTopic(
                HelpTopic.default_topic_content, __name__=id)
            topic.title=title
        else:
            topic = id
            id = topic.id
            title = topic.title

        self._setObject(id, topic)
        if REQUEST is not None:
            return self.manage_main(self, REQUEST,
                                    manage_tabs_message='Help Topic added.')

    def helpValues(self, REQUEST=None):
        """
        Lists contained Help Topics.
        Help Topics for which the user is not authorized
        are not listed.
        """
        topics=self.objectValues('Help Topic')
        if REQUEST is None:
            return topics
        return filter(
            lambda ht, u=REQUEST.AUTHENTICATED_USER: ht.authorized(u), topics)

    def tpValues(self):
        """
        Tree protocol - child nodes
        """
        topics=[]
        apitopics=[]
        dtmltopics=[]
        helptopics=[]
        for topic in self.objectValues('Help Topic'):
            if hasattr(topic,'isAPIHelpTopic') and topic.isAPIHelpTopic:
                apitopics.append(topic)
            else:
                if callable(topic.id):
                    id=topic.id()
                else:
                    id=topic.id
                if id[:5]=='dtml-':
                    dtmltopics.append(topic)
                else:
                    helptopics.append(topic)
        if helptopics:
            topics = topics + [TreeCollection(' Help Screens', helptopics)]
        if dtmltopics:
            topics = topics + [TreeCollection(' DTML Reference', dtmltopics)]
        if apitopics:
            topics = topics + [TreeCollection(' API Reference', apitopics)]
        return topics
        
    def all_meta_types(self):
        f=lambda x: x['name'] in ('Image', 'File')
        return filter(f, Products.meta_types) + self.meta_types

    def __call__(self, *args, **kw):
        """
        Searchable interface
        """
        return apply(self.catalog.__call__, args, kw)

    searchResults=__call__

    def uniqueValuesFor(self, i):
        return self.catalog.uniqueValuesFor(i)

    standard_html_header=DTMLFile('dtml/topic_header', globals())
    standard_html_footer=DTMLFile('dtml/topic_footer', globals())




Globals.default__class_init__(ProductHelp)











--- Added File Util.py in package Zope2 ---

import HelpTopic, APIHelpTopic
import Globals
import re, os, string

title_re=re.compile(r'<title>(.+?)</title>', re.I)

def makeHelp(id, path, file, context, permissions=None, categories=None):
    """ Factor this out of ProductContext so Product authors can call
    it and register their own topics """
    ext=os.path.splitext(file)[1]
    ext=string.lower(ext)
    if ext in ('.dtml',):
        contents = open(os.path.join(path,file),'rb').read()
        m = title_re.search(contents)
        if m:
            title = m.group(1)
        else:
            title = ''
        ht=HelpTopic.DTMLTopic(file, '', os.path.join(path,file),
                               permissions=permissions, categories=categories)
        context.registerHelpTopic(file, ht)
    elif ext in ('.html', '.htm'):
        contents = open(os.path.join(path,file),'rb').read()
        m = title_re.search(contents)
        if m:
            title = m.group(1)
        else:
            title = ''
        ht=HelpTopic.TextTopic(file, title, os.path.join(path,file),
                               permissions=permissions, categories=categories)
        context.registerHelpTopic(file, ht)
    elif ext in ('.stx', '.txt'):
        title=string.split(open(os.path.join(path,file),'rb').readline(), ':')[0]
        ht=HelpTopic.STXTopic(file, title, os.path.join(path, file),
                              permissions=permissions, categories=categories)
        context.registerHelpTopic(file, ht)
    elif ext in ('.jpg', '.gif', '.png'):
        ht=HelpTopic.ImageTopic(file, '', os.path.join(path, file),
                                permissions=permissions, categories=categories)
        context.registerHelpTopic(file, ht)
    elif ext in ('.py',):
        ht=APIHelpTopic.APIHelpTopic(file, '', os.path.join(path, file),
                                     permissions=permissions, categories=categories)
        context.registerHelpTopic(file, ht)


def lazySetup(path, product_help, categories=None):
    """ Do a lazy setup, tool through the 'help' directory turning files
    into help topics. """

    for file in os.listdir(path):
        ext=os.path.splitext(file)[1]
        ext=string.lower(ext)
        if ext in ('.dtml',):
            contents = open(os.path.join(path,file),'rb').read()
            m = title_re.search(contents)
            if m:
                title = m.group(1)
            else:
                title = ''
            ht=HelpTopic.DTMLTopic(file, '', os.path.join(path,file), categories=categories)
            product_help.addTopic(ht)
        elif ext in ('.html', '.htm'):
            contents = open(os.path.join(path,file),'rb').read()
            m = title_re.search(contents)
            if m:
                title = m.group(1)
            else:
                title = ''
            ht=HelpTopic.TextTopic(file, title, os.path.join(path,file), categories=categories)
            product_help.addTopic(ht)
        elif ext in ('.stx', '.txt'):
            title=string.split(open(os.path.join(path,file),'rb').readline(), ':')[0]
            categories = None
            if file[:5]=='dtml-':
                categories = ('DTML',)
            ht=HelpTopic.STXTopic(file, title, os.path.join(path, file), categories=categories)
            product_help.addTopic(ht)
        elif ext in ('.jpg', '.gif', '.png'):
            ht=HelpTopic.ImageTopic(file, '', os.path.join(path, file), categories=categories)
            product_help.addTopic(ht)
        elif ext in ('.py',) and not file=='__init__.py':
            ht=APIHelpTopic.APIHelpTopic(file, '', os.path.join(path, file),
                                         categories=categories)
            product_help.addTopic(ht)








--- Updated File APIHelpTopic.py in package Zope2 --
--- APIHelpTopic.py	2001/02/19 20:17:26	1.10
+++ APIHelpTopic.py	2001/05/17 15:59:42	1.10.32.1
@@ -105,13 +105,16 @@
     """
 
     isAPIHelpTopic=1
+
+    categories = ('API',)
     
-    def __init__(self, id, title, file):
+    def __init__(self, id, title, file, categories=None):
         self.id=id
         self.title=title
         dict={}
         execfile(file, dict)
         self.doc=dict.get('__doc__','')
+        self.categories = categories
 
         self.apis=[]
         for k, v in dict.items():
@@ -137,8 +140,8 @@
                 if not lines:
                     break
         # otherwise get title from first class name
-        if not self.title:
-            self.title=self.apis[0].name
+##         if not self.title:
+##             self.title=self.apis[0].name
 
     index_html=DTMLFile('dtml/APIHelpView', globals())
 

--- Updated File HelpSys.py in package Zope2 --
--- HelpSys.py	2001/02/12 19:13:22	1.19
+++ HelpSys.py	2001/05/17 15:59:42	1.19.32.1
@@ -89,10 +89,13 @@
 from Globals import Persistent, DTMLFile, HTML
 from Products.ZCatalog.ZCatalog import ZCatalog
 from Products.ZCatalog.Lazy import LazyCat
+from ProductHelp import ProductHelp, addProductHelp
 import Products
 import HelpTopic
 import Globals
+from ProductHelp import TreeCollection
 
+
 class HelpSys(Acquisition.Implicit, ObjectManager, Item, Persistent):
     """
     Zope Help System
@@ -140,16 +143,38 @@
                     perms.append(p[0])
             REQUEST.set('permissions',perms)
         results=[]
-        for ph in self.helpValues():
+        for ph in self.helpValues() + self.objectValues('Product Help'):
             results.append(apply(getattr(ph, '__call__'), (REQUEST,) , kw))
         return LazyCat(results)   
         
     searchResults=__call__
+
+    def uniqueValuesFor(self, i, REQUEST=None):
+        "Searchable interface"
+        if REQUEST is not None:
+            perms=[]
+            user=REQUEST.AUTHENTICATED_USER
+            for p in self.ac_inherited_permissions():
+                if user.has_permission(p[0], self):
+                    perms.append(p[0])
+            REQUEST.set('permissions',perms)
+        results=[]
+        for ph in self.helpValues() + self.objectValues('Product Help'):
+            results.append(ph.uniqueValuesFor(i))
+        unique= []
+        for i in results:
+            if i in unique:
+                continue
+            unique.append(i)
+        return LazyCat(unique)
+        
     
-    index_html=DTMLFile('dtml/frame', globals())
+    index_html=DTMLFile('dtml/sys_index', globals())
     menu=DTMLFile('dtml/menu', globals())
     search=DTMLFile('dtml/search', globals())
     results=DTMLFile('dtml/results', globals())
+    sys_results=DTMLFile('dtml/sys_results', globals())
+    adv_search=DTMLFile('dtml/adv_search', globals())
     main=HTML("""<html></html>""")
     standard_html_header=DTMLFile('dtml/menu_header', globals())
     standard_html_footer=DTMLFile('dtml/menu_footer', globals())
@@ -194,7 +219,7 @@
         Aggregates Product Helps with the same title.
         """
         helps={}
-        for help in self.helpValues():
+        for help in self.helpValues() + self.objectValues('Product Help'):
             if helps.has_key(help.title):
                 helps[help.title].append(help)
             else:
@@ -204,157 +229,16 @@
             cols.append(TreeCollection(k,v,0))
         return cols
 
-Globals.default__class_init__(HelpSys)
-
-
-class TreeCollection:
-    """
-    A temporary wrapper for a collection of objects
-    objects, used for help topic browsing to make a collection
-    of objects appear as a single object.
-    """
-
-    def __init__(self, id, objs, simple=1):
-        self.id=self.title=id
-        self.objs=objs
-        self.simple=simple
-        
-    def tpValues(self):
-        values=[]
-        if self.simple:
-            values=self.objs
-        else:
-            for obj in self.objs:
-                values=values + list(obj.tpValues())
-        # resolve overlap
-        ids={}
-        for value in values:
-            if ids.has_key(value.id):
-                ids[value.id].append(value)
-            else:
-                ids[value.id]=[value]
-        results=[]
-        for k,v in ids.items():
-            if len(v)==1:
-                results.append(v[0])
-            else:
-                values=[]
-                for topic in v:
-                    values=values + list(topic.tpValues())
-                results.append(TreeCollection(k, values)) 
-        results.sort(lambda x, y: cmp(x.id, y.id))
-        return results
 
-    def tpId(self):
-        return self.id
 
+Globals.default__class_init__(HelpSys)
 
-class ProductHelp(Acquisition.Implicit, ObjectManager, Item, Persistent):
-    """
-    Manages a collection of Help Topics for a given Product.
-    
-    Provides searching services to HelpSystem.
-    """
 
-    meta_type='Product Help'
-    icon='p_/ProductHelp_icon'
 
-    lastRegistered=None
-    
-    meta_types=({'name':'Help Topic',
-                 'action':'addTopicForm',
-                 'permission':'Add Documents, Images, and Files'},
-                )
 
-    manage_options=(
-        ObjectManager.manage_options +
-        Item.manage_options
-        )
-
-    __ac_permissions__=(
-        ('Add Documents, Images, and Files', ('addTopicForm', 'addTopic')),
-        )
-    
-    def __init__(self, id='Help', title=''):
-        self.id=id
-        self.title=title
-        self.catalog=ZCatalog('catalog')
-        c=self.catalog._catalog
-        # clear catalog
-        for index in c.indexes.keys():
-            c.delIndex(index)
-        for col in c.schema.keys():
-            c.delColumn(col)
-        c.addIndex('SearchableText', 'TextIndex')
-        c.addIndex('categories', 'KeywordIndex')
-        c.addIndex('permissions', 'KeywordIndex')
-        c.addColumn('categories')
-        c.addColumn('permissions')
-        c.addColumn('title_or_id')
-        c.addColumn('url')
-        c.addColumn('id')
-
-    addTopicForm=DTMLFile('dtml/addTopic', globals())
-
-    def addTopic(self, id, title, REQUEST=None):
-        "Add a Help Topic"
-        topic=HelpTopic.DTMLDocumentTopic(
-            HelpTopic.default_topic_content, __name__=id)
-        topic.title=title
-        self._setObject(id, topic)
-        if REQUEST is not None:
-            return self.manage_main(self, REQUEST,
-                                    manage_tabs_message='Help Topic added.')
 
-    def helpValues(self, REQUEST=None):
-        """
-        Lists contained Help Topics.
-        Help Topics for which the user is not authorized
-        are not listed.
-        """
-        topics=self.objectValues('Help Topic')
-        if REQUEST is None:
-            return topics
-        return filter(
-            lambda ht, u=REQUEST.AUTHENTICATED_USER: ht.authorized(u), topics)
 
-    def tpValues(self):
-        """
-        Tree protocol - child nodes
-        """
-        topics=[]
-        apitopics=[]
-        dtmltopics=[]
-        for topic in self.objectValues('Help Topic'):
-            if hasattr(topic,'isAPIHelpTopic') and topic.isAPIHelpTopic:
-                apitopics.append(topic)
-            else:
-                if callable(topic.id):
-                    id=topic.id()
-                else:
-                    id=topic.id
-                if id[:5]=='dtml-':
-                    dtmltopics.append(topic)
-                else:
-                    topics.append(topic)
-        if dtmltopics:
-            topics = topics + [TreeCollection(' DTML Reference', dtmltopics)]
-        if apitopics:
-            topics = topics + [TreeCollection(' API Reference', apitopics)]
-        return topics
-        
-    def all_meta_types(self):
-        f=lambda x: x['name'] in ('Image', 'File')
-        return filter(f, Products.meta_types) + self.meta_types
 
-    def __call__(self, *args, **kw):
-        """
-        Searchable interface
-        """
-        return apply(self.catalog.__call__, args, kw)
 
-    standard_html_header=DTMLFile('dtml/topic_header', globals())
-    standard_html_footer=DTMLFile('dtml/topic_footer', globals())
 
 
-Globals.default__class_init__(ProductHelp)

--- Updated File HelpTopic.py in package Zope2 --
--- HelpTopic.py	2001/05/02 21:05:49	1.13
+++ HelpTopic.py	2001/05/17 15:59:42	1.13.6.1
@@ -105,7 +105,8 @@
         )
 
     # default values
-    categories=('Content Manager Information',)
+    categories=()
+
     permissions=('View',)
 
     def _permissions_values(self):
@@ -116,6 +117,7 @@
     
     permissions_values=ComputedAttribute(_permissions_values, 1)
 
+    # what's this for?
     categories_values=(
         'Content Manager Information',
         'DTML Programmer Information',
@@ -133,6 +135,12 @@
             if user.has_permission(perm, self):
                 return 1
         return 0
+
+    def setCategories(self, cats):
+        self.categories = cats
+
+    def getCategories(self):
+        return self.categories
     
     # Indexable methods
     # -----------------
@@ -179,7 +187,7 @@
     """
     Abstract base class for Help Topics
     """
-    
+
     meta_type='Help Topic'
     icon='p_/HelpTopic_icon'
     _v_last_read = 0
@@ -241,6 +249,7 @@
     """
     A basic Help Topic. Holds a HTMLFile object.
     """
+
     def __init__(self, id, title, file, permissions=None, categories=None):
         self.id=id
         self.title=title
@@ -261,6 +270,7 @@
     """
     A basic Help Topic. Holds a text file.
     """
+
     def __init__(self, id, title, file, permissions=None, categories=None):
         self.id=id
         self.title=title
@@ -286,6 +296,19 @@
     """
     A structured-text topic. Holds a HTMLFile object.
     """
+    def __init__(self, id, title, file, permissions=None, categories=None):
+        self.id=id
+        self.file = file
+        self.obj=open(file).read()
+        self.title = self.obj.split("\n")[0]
+        if not self.title:
+            self.title = title
+        self._set_last_read(file)
+        if permissions is not None:
+            self.permissions=permissions
+        if categories is not None:
+            self.categories=categories
+
     def index_html(self, REQUEST=None):
         """ View the STX Help Topic """
         self._check_for_update()
@@ -325,4 +348,10 @@
     def SearchableText(self):
         "The full text of the Help Topic, for indexing purposes"
         return ''
+
+
+
+
+
+
 

--- Updated File __init__.py in package Zope2 --
--- __init__.py	2000/05/16 18:37:50	1.4
+++ __init__.py	2001/05/17 15:59:42	1.4.160.1
@@ -87,3 +87,11 @@
 import HelpSys
 import sys
 sys.modules['HelpSys.HelpSystem']=HelpSys
+
+try:
+    from HelpContext import HelpContext as con
+    con().registerHelp('HelpSys/help')
+    
+except:
+    ImportError
+