[Checkins] SVN: Sandbox/ulif/grok-adminui/src/grok/admin/ Added docgrok support for text files.

Uli Fouquet uli at gnufix.de
Sun Jul 1 22:52:16 EDT 2007


Log message for revision 77284:
  Added docgrok support for text files.

Changed:
  U   Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.py
  U   Sandbox/ulif/grok-adminui/src/grok/admin/static/grok.css
  U   Sandbox/ulif/grok-adminui/src/grok/admin/view.py
  U   Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgrokpackageview.pt
  A   Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgroktextfileview.pt

-=-
Modified: Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.py
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.py	2007-07-01 14:27:04 UTC (rev 77283)
+++ Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.py	2007-07-02 02:52:13 UTC (rev 77284)
@@ -12,6 +12,7 @@
 from zope.proxy import removeAllProxies
 
 import os
+import sys # for sys.path
 import types
 import grok
 import inspect
@@ -24,16 +25,56 @@
 
 from zope.app.apidoc.codemodule.module import Module
 from zope.app.apidoc.codemodule.class_ import Class
+from zope.app.apidoc.codemodule.text import TextFile
 from zope.app.apidoc.utilities import renderText
 
 grok.context(IRootFolder)
 grok.define_permission('grok.ManageApplications')
 
+def find_filepath( dotted_path ):
+    """Find the filepath for a dotted name.
 
+    If a dotted name denotes a filename we try to find its path
+    by concatenating it with the system paths and looking for an
+    existing file. Every dot in the filename thereby can be part
+    of the filename or of its path. Therefore we check the
+    several possible dirname/filename combinations possible.
 
+    Returns None if no suitable filepath can be found.
+
+    This functions does *not* look for Python elements like classes,
+    interfaces and the files where they were defined. Use `resolve()`
+    and the `__file__` attribute for examining this kind of stuff
+    instead.
+
+    This function finds the location of text files and the like, as
+    far as they are placed inside some Python path.
+    """
+    currpath = dotted_path
+    currname = ""
+    while '.' in currpath:
+        currpath, name = currpath.rsplit('.', 1)
+        if currname != "":
+            currname = "." + currname
+        currname = name + currname
+        tmp_path = ""
+        for elem in currpath.split( '.' ):
+            tmp_path = os.path.join( tmp_path, elem )
+        for syspath in sys.path:
+            filepath_to_check = os.path.join(syspath, tmp_path, currname)
+            if os.path.isfile(filepath_to_check):
+                return filepath_to_check
+    return None
+
+
 def handle_module( dotted_path, ob=None ):
+    """Determine, whether the given path/obj references a Python module.
+    """
     if ob is None:
-        ob = resolve( dotted_path )
+        try:
+            ob = resolve( dotted_path )
+        except ImportError:
+            return None
     if not hasattr(ob, '__file__'):
         return None
     if not is_package(os.path.dirname(ob.__file__)):
@@ -45,8 +86,13 @@
     return DocGrokModule(dotted_path)
 
 def handle_package( dotted_path, ob=None):
+    """Determine, whether the given path/obj references a Python package.
+    """
     if ob is None:
-        ob = resolve( dotted_path )
+        try:
+            ob = resolve( dotted_path )
+        except ImportError:
+            return None
     if not hasattr(ob, '__file__'):
         return None
     if not is_package(os.path.dirname(ob.__file__)):
@@ -58,27 +104,50 @@
     return DocGrokPackage(dotted_path)
 
 def handle_interface(dotted_path, ob=None):
+    """Determine, whether the given path/obj references an interface.
+    """
     if ob is None:
-        ob = resolve(dotted_path)
+        try:
+            ob = resolve(dotted_path)
+        except ImportError:
+            return None
     if not isinstance(
         removeAllProxies(ob), InterfaceClass):
         return None
     return DocGrokInterface(dotted_path)
 
 def handle_class(dotted_path, ob=None):
+    """Determine, whether the given path/obj references a Python class.
+    """
     if ob is None:
-        ob = resolve(dotted_path)
+        try:
+            ob = resolve(dotted_path)
+        except ImportError:
+            return None
     if not isinstance(ob, (types.ClassType, type)):
         return None
     return DocGrokClass(dotted_path)
 
 def handle_grokapplication( dotted_path, ob=None):
+    """Determine, whether the given path/obj references a Grok application.
+    """
     if ob is None:
-        ob = resolve(dotted_path)
+        try:
+            ob = resolve(dotted_path)
+        except ImportError:
+            None
     if not IApplication.implementedBy( ob ):
         return None
     return DocGrokGrokApplication(dotted_path)
 
+def handle_textfile( dotted_path, ob=None):
+    if ob is not None:
+        # Textfiles that are objects, are not text files.
+        return None
+    if os.path.splitext( dotted_path )[1] != u'.txt':
+        return None
+    return DocGrokTextFile(dotted_path)
+
 # The docgroks registry.
 #
 # We register 'manually', because the handlers
@@ -93,7 +162,9 @@
     { 'name' : 'grokapplication',
       'handler' : handle_grokapplication },
     { 'name' : 'class',
-      'handler' : handle_class } ]
+      'handler' : handle_class },
+    { 'name' : 'textfile',
+      'handler' : handle_textfile}]
 
 
 def handle(dotted_path):
@@ -102,12 +173,15 @@
     try:
         ob = resolve( dotted_path )
     except ImportError:
-        # There is no package of that name. Give back 404.
+        # There is no object of that name. Give back 404.
         # XXX Do something more intelligent, offer a search.
-        return None
+        if not find_filepath( dotted_path ):
+            return None
+        ob = None
     except:
         return None
 
+
     for handler in docgrok_handlers:
         spec_handler = handler['handler']
         doc_grok = spec_handler( dotted_path, ob )
@@ -300,8 +374,12 @@
         return self.msg
 
     def getFilePath( self ):
-        ob = resolve( self.path )
-        return hasattr(ob, __file__) and os.path.dirname(ob.__file__) or None
+        try:
+            ob = resolve( self.path )
+            return hasattr(ob, __file__) and os.path.dirname(ob.__file__) or None
+        except ImportError:
+            pass
+        return find_filepath(self.path)
 
     def getDoc(self, heading_only=False):
         """Get the doc string of the module STX formatted.
@@ -440,12 +518,19 @@
         filter_func = lambda x: x.isPackage()
         return self._getModuleInfos( filter_func )
 
+    def getTextFiles( self ):
+        """Get the text files inside a package.
+        """
+        filter_func = lambda x: x.isinstance( TextFile )
+        return self._getModuleInfos( filter_func )
+
     def getChildren( self ):
         result = self.apidoc.items()
         result.sort( lambda x,y:cmp(x[0], y[0]) )
         return result
 
 
+
 class DocGrokModule(DocGrokPackage):
     """This doctor cares for python modules.
     """
@@ -500,3 +585,30 @@
     """This doctor cares for Grok applications and components.
     """
     pass
+
+class DocGrokTextFile(DocGrok):
+    """This doctor cares for text files.
+    """
+
+    def __init__(self,dotted_path):
+        self.path = dotted_path
+        self.filepath = find_filepath( self.path )
+        self.filename = os.path.basename( self.filepath )
+
+
+    def getPackagePath(self):
+        """Return package path as dotted name.
+        """
+        #return os.path.dirname( self.filepath )
+        dot_num_in_filename = len([x for x in self.filename if x == '.'])
+        parts = self.path.rsplit('.', dot_num_in_filename + 1)
+        return parts[0]
+
+    def getContent(self):
+        """Get file content UTF-8 encoded.
+        """
+        file = open(self.filepath, 'rU')
+        content = file.read()
+        file.close()
+        return content.decode('utf-8')
+

Modified: Sandbox/ulif/grok-adminui/src/grok/admin/static/grok.css
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/admin/static/grok.css	2007-07-01 14:27:04 UTC (rev 77283)
+++ Sandbox/ulif/grok-adminui/src/grok/admin/static/grok.css	2007-07-02 02:52:13 UTC (rev 77284)
@@ -468,6 +468,20 @@
        font-family: courier;
        color: #00f;
 }
+.docgrok-sourcetext { 
+       border: 2px groove #eee;
+       bo/rder-top: none;
+       padding: 15px;
+       background-color: #f8f8f8;
+       margin: 10px;
+}
+.docgrok-sourceheader { 
+       bo/rder: 2px groove #eee;
+       bo/rder-bottom: none;
+       background-color: #fff;
+       pa/dding: 5px;
+       pa/dding-top: 0px;
+}
 .docgrok-elemname1 { /* Element names in headings */
        color: #555555;
 }
\ No newline at end of file

Modified: Sandbox/ulif/grok-adminui/src/grok/admin/view.py
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/admin/view.py	2007-07-01 14:27:04 UTC (rev 77283)
+++ Sandbox/ulif/grok-adminui/src/grok/admin/view.py	2007-07-02 02:52:13 UTC (rev 77284)
@@ -1,6 +1,7 @@
 import grok
 from grok.admin.docgrok import DocGrok, DocGrokPackage, DocGrokModule, getThingsType
 from grok.admin.docgrok import DocGrokClass, DocGrokInterface, DocGrokGrokApplication
+from grok.admin.docgrok import DocGrokTextFile
 
 import zope.component
 from zope.app.folder.interfaces import IRootFolder
@@ -186,6 +187,8 @@
         """
         if path is None:
             path = self.context.path
+        if path is None:
+            return None
         result = []
         part_path = ""
         for part in path.split( '.' ):
@@ -214,7 +217,7 @@
                          removeAllProxies(obj), InterfaceClass) and self.getDocHeading(obj.getDoc())) or  None,
                     # only for interfaces; should be done differently somewhen
                     'path': getPythonPath(removeAllProxies(obj)),
-                    'url': ("%s.%s" % (self.context.path, name)).replace('.','/'),
+                    'url': ("%s/%s" % (self.context.path.replace('.','/'), name)),
                     'ispackage': getThingsType(
                          "%s.%s" % (self.context.path,name) ) == "package",
                     'ismodule': getThingsType(
@@ -282,4 +285,18 @@
     grok.context(DocGrokGrokApplication)
     grok.name( 'index' )
 
+class DocGrokTextFileView(DocGrokView):
+    grok.context(DocGrokTextFile)
+    grok.name( 'index' )
+    
+    def getContent(self):
+        lines = self.context.getContent()
+        if self.context.path.endswith('.stx'):
+            format = 'zope.source.stx'
+        else:
+            format = 'zope.source.rest'
+        return renderText(lines, format=format)
 
+    def getPackagePathParts(self):
+        return self.getPathParts(
+            self.context.getPackagePath())

Modified: Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgrokpackageview.pt
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgrokpackageview.pt	2007-07-01 14:27:04 UTC (rev 77283)
+++ Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgrokpackageview.pt	2007-07-02 02:52:13 UTC (rev 77284)
@@ -91,7 +91,36 @@
 	  </div>
 	</div>
 
+	<h2>Textfiles:</h2>
+
+	<div class="docgrok-entry" tal:repeat="item view/getEntries">
+	  <div tal:condition="item/istextfile">
+	    <div class="docgrok-pathvalue">
+	      
+	      <a href=""
+		 tal:attributes="href string:${view/root_url}/docgrok/${item/url}" 
+		 tal:content="string: ${item/name}">
+		moduleName
+	      </a>
+	    </div>
+	    <div class="docgrok-annotation2"
+		 tal:condition="item/doc"
+		 tal:content="structure item/doc">
+	    </div>
+	    <div class="docgrok-annotation2"
+		 tal:condition="not: item/doc">
 <!--
+	      You can use <span class="docgrok-pycode1">import <span
+	      tal:replace="string: ${context/path}.${item/name}">a.b</span>
+	    </span>
+	    to make the elements of this package available in your 
+	    application or component.
+-->
+	    </div>
+	  </div>
+	</div>
+
+<!--
 	<div tal:content="context/msg" />
 -->
 

Added: Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgroktextfileview.pt
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgroktextfileview.pt	                        (rev 0)
+++ Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgroktextfileview.pt	2007-07-02 02:52:13 UTC (rev 77284)
@@ -0,0 +1,40 @@
+<html metal:use-macro="view/app_root/@@macros/gaia-page">
+  <head>
+    <title>DocGrok page title</title>
+  </head>
+  <body>
+    <div metal:fill-slot="content">
+
+      <div class="docgrok-sourceheader">
+	<h1>
+	  <span class="docgrok-pathvalue"
+		tal:content="view/context/filename">
+	    filename.txt
+	  </span>
+	  (Text file in
+	  <span class="docgrok-pathvalue">
+	    <span tal:repeat="part view/getPackagePathParts"><a href=""
+							 tal:attributes="href string:${view/root_url}${part/url}"
+							 tal:content="part/name">part</a></span>
+	  </span>) 
+	</h1>
+	<div class="docgrok-entry">
+	  <span class="docgrok-description1">File path:</span>
+
+	  <span class="docgrok-pathvalue"
+		tal:content="view/context/getFilePath"
+		>
+	    /home/uli/blah...
+	  </span>
+	  <div class="docgrok-annotation1">
+	    This is, where this text file can be found.
+	  </div>
+	</div>
+      </div>
+      <div class="docgrok-sourcetext" 
+	   tal:content="structure view/getContent">
+      </div>
+    </div>
+    <div metal:fill-slot="footer"></div>
+  </body>
+</html>



More information about the Checkins mailing list