[Checkins] SVN: grok/trunk/doc/ Brought in macros howto from Ulifs sandbox, added link to main menu and brief index page for howto directory

Darryl Cousins darryl at darrylcousins.net.nz
Sat Jul 7 18:19:53 EDT 2007


Log message for revision 77594:
  Brought in macros howto from Ulifs sandbox, added link to main menu and brief index page for howto directory

Changed:
  U   grok/trunk/doc/grok2html.py
  U   grok/trunk/doc/index.txt
  A   grok/trunk/doc/minitutorials/index.txt
  A   grok/trunk/doc/minitutorials/macros.txt
  U   grok/trunk/doc/minitutorials/searching.txt
  U   grok/trunk/doc/template.pt

-=-
Modified: grok/trunk/doc/grok2html.py
===================================================================
--- grok/trunk/doc/grok2html.py	2007-07-07 21:45:44 UTC (rev 77593)
+++ grok/trunk/doc/grok2html.py	2007-07-07 22:19:52 UTC (rev 77594)
@@ -1,129 +1,144 @@
 import os
+import codecs
+import sys
 
-from zope.pagetemplate.pagetemplate import PageTemplate
+sys.path.append('/opt/odd-bobs/Zope3/src')
 
 import docutils.core
-from docutils.writers.html4css1 import HTMLTranslator
 from docutils.writers.html4css1 import Writer
 
-class ZopeTranslator(HTMLTranslator):
-    """
-    The ZopeTranslator extends the base HTML processor for reST.  It
-    augments reST by:
+from zope.app.renderer.rest import ZopeTranslator
+from zope.pagetemplate.pagetemplate import PageTemplate
+from zope.pagetemplate.pagetemplatefile import PageTemplateFile
 
-    - Outputs *only* the 'body' parts of the document tree, using the
-    internal docutils structure.
-    """
-
-    def astext(self):
-        """
-        This is where we join the document parts that we want in
-        the output.
-        """
-        # use the title, subtitle, author, date, etc., plus the content
-        body = self.body_pre_docinfo + self.docinfo + self.body
-        return u"".join(body)
-
-
 class ReStructuredTextToHTMLRenderer:
-    """convert from Restructured Text to HTML.
+    """Convert from Restructured Text to HTML."""
 
-    """
-
     def __init__(self,content):
         self.content = content 
 
     def render(self):
         settings_overrides = {
             'halt_level': 6,
+            'input_encoding': 'utf8',
             'output_encoding': 'utf8',
             'initial_header_level': 2
         }
-            # 'input_encoding': 'unicode',
-            # 'output_encoding': 'unicode',
+            # 'output_encoding': 'utf8',
         writer = Writer()
         writer.translator_class = ZopeTranslator
         html = docutils.core.publish_string(
-        self.content,
-        writer=writer,settings_overrides=settings_overrides,)
+                        self.content,
+                        writer=writer,
+                        settings_overrides=settings_overrides,)
         return html
 
+class RestFile(object):
+    
+    source = ''
+    target = ''
+    url = ''
+    title = ''
+    active = True
 
-Menu = [
-        {'href':'index.html','title':u'Home','klass':''},
-        {'href':'about.html','title':u'About','klass':''},
-        {'href':'tutorial.html','title':u'Tutorial','klass':''},
-        ]
+    def __init__(self, url, source, target):
+        self.url = url
+        self.target = target
+        if os.path.isfile(target):
+            if os.path.getmtime(source) < os.path.getmtime(target):
+                self.active = False
+        if os.path.isfile(source):
+            self.source = codecs.open(source,"r",'utf8').read()
+        else:
+            self.source = source
+        srctxt = self.source.split('\n')
+        title = srctxt[0]
+        if title.startswith("====="): title = srctxt[1]
+        self.title = title
 
+    def set_rest_content(self):
+        renderer = ReStructuredTextToHTMLRenderer(self.source)
+        self.content = renderer.render().strip()
+
+    def create_html(self, page, settings):
+        if not self.active:
+            pass
+        print 'Processing ', self.url
+        self.set_rest_content()
+
+        settings["context"] = Context(self.url, self.title, self.content)
+        content = page.pt_render(namespace=settings)
+        #fp = open(self.target, 'w')
+        fp = codecs.open(self.target,"w",'utf8')
+        fp.write(content)
+        fp.close()
+
 class Context:
     """Set up the context for rendering the rest as html through zpt"""
 
-    id = u''
-    title = u''
-    menu = []
-    content = u''
-
-    def __init__(self, id, title=u''):
-        self.id = id
+    def __init__(self, url, title=u'', content=u''):
+        self.url = url
         self.title = title
+        self.content = content
 
-    def restSource(self, source_file):
-        fp = open(source_file)
-        # try to locate a title for the document if not given
-        if not self.title:
-            self.title = fp.readline()
-            if self.title.startswith("="):
-                self.title = fp.readline()
-        fp.close()
-        #rest = codecs.open(source_file,"r",'utf8').read()
-        rest = open(source_file).read()
-        renderer = ReStructuredTextToHTMLRenderer(rest)
-        return renderer.render().strip()
-    
-    def setRestContent(self, source_file):
-        self.content = self.restSource(source_file)
-
     @property
     def menu(self):
         for item in Menu:
-            if item.get('href').split('.')[0] == self.id:
+            if item.get('href') == self.url:
                 item['klass'] = u'selected'
             else:
                 item['klass'] = u''
+            # just for tutorial files
+            if len(self.url.split('/')) > 2:
+                if item.get('href').split('/')[:-1] == self.url.split('/')[:-1]:
+                    item['klass'] = u'selected'
             if not item.get('description', None):
                 item['description'] = item['title']
         return Menu
 
-def handler_html(pageid, restpath):
+def create_html(rest_files, template):
+    settings = {}
+    settings["here"] = { "layout": template }
+    page = PageTemplate()
+    page.write("""<metal:block use-macro="here/layout/macros/pagelayout" />""")
 
-# we could rename about_grok.txt to about.txt that we could use only 
-# a pageid to identify the source document and the html result.
-    if os.path.exists(restpath):
-        layout_file = os.path.join('template.pt')
-        layout = PageTemplate()
-        layout.write(open(layout_file,"r").read())
+    for restfile in rest_files:
+        restfile.create_html(page, settings)
 
-        page = PageTemplate()
-        page.write("""<metal:block use-macro="here/layout/macros/pagelayout" />""")
+# Menu should later be generated if site becomes more complex
+Menu = [
+        {'href':'/index.html','title':u'Home','klass':''},
+        {'href':'/about.html','title':u'About','klass':''},
+        {'href':'/tutorial.html','title':u'Tutorial','klass':''},
+        {'href':'/minitutorials/index.html','title':u'How Tos','klass':''},
+        ]
 
-        context = Context(pageid)
-        context.setRestContent(restpath)
-
-        settings = {}
-        settings["here"] = { "layout": layout }
-        settings["context"] = context
-
-        content = page.pt_render(namespace=settings)
-
-        print content
-
-
 if __name__ == '__main__':
-    import sys
-    args = sys.argv
+    source_dir = '.'
+    www_dir = '/opt/odd-bobs/grok-www'
+    rest_files = []
+    if www_dir == '':
+        print 'Please define the target directory for html files'
+        import sys
+        sys.exit()
+    rest_files.append(RestFile('index', 
+                              os.path.join(source_dir, 'index.txt'),
+                              os.path.join(www_dir, 'index.html')))
+    rest_files.append(RestFile('about', 
+                              os.path.join(source_dir, 'about.txt'),
+                              os.path.join(www_dir, 'about.html')))
+    rest_files.append(RestFile('tutorial', 
+                              os.path.join(source_dir, 'tutorial.txt'),
+                              os.path.join(www_dir, 'tutorial.html')))
+    rest_files.append(RestFile('mini-index', 
+                              os.path.join(source_dir, 'minitutorials', 'index.txt'),
+                              os.path.join(www_dir, 'minitutorials', 'index.html')))
+    rest_files.append(RestFile('searching', 
+                              os.path.join(source_dir, 'minitutorials', 'searching.txt'),
+                              os.path.join(www_dir, 'minitutorials', 'searching.html')))
+    rest_files.append(RestFile('macros', 
+                              os.path.join(source_dir, 'minitutorials', 'macros.txt'),
+                              os.path.join(www_dir, 'minitutorials', 'macros.html')))
+    template = PageTemplateFile(os.path.join(source_dir, 'template.pt'))
+    create_html(rest_files, template)
 
-    if len(args) < 2:
-      print """  Usage: ./grok2html.py pageid restsource > pageid.html
-      Prints to stdout the results of parsing restsource with grok template."""
-    else:
-        handler_html(args[1], args[2])

Modified: grok/trunk/doc/index.txt
===================================================================
--- grok/trunk/doc/index.txt	2007-07-07 21:45:44 UTC (rev 77593)
+++ grok/trunk/doc/index.txt	2007-07-07 22:19:52 UTC (rev 77594)
@@ -105,10 +105,11 @@
 
   svn co svn://svn.zope.org/repos/main/grok/trunk grok
 
-ME GROK MINI-TUTORIALS
-----------------------
+ME GROK MINI-TUTORIALS!
+-----------------------
 
-* `Newbie Search Tutorial <searching.html>`_
+* `Newbie Search HowTo <minitutorials/searching.html>`_
+* `Newbie Macros HowTo <minitutorials/macros.html>`_
 
 ME GROK SPRINTS AND BLOGS!
 --------------------------

Added: grok/trunk/doc/minitutorials/index.txt
===================================================================
--- grok/trunk/doc/minitutorials/index.txt	                        (rev 0)
+++ grok/trunk/doc/minitutorials/index.txt	2007-07-07 22:19:52 UTC (rev 77594)
@@ -0,0 +1,23 @@
+================
+Grok Mini-HowTos
+================
+
+.. image:: /resources/evencaveman.jpg
+   :alt: Now even cavemen can use Zope3
+   :class: right
+
+These mini-tutorials have been contributed by members of the Grok community.
+
+* `Newbie Search Tutorial </minitutorials/searching.html>`_:
+  Grok supports the vanilla indexing services available in Zope 3 straight out of
+  the box. Catalog uses developer defined indexes for searching. In other words,
+  you have to define the indexes you want to use to search you objects before you
+  perform the actual search.
+
+* `Macros With Grok </minitutorials/macros.html>`_:
+  Grok supports the vanilla indexing services available in Zope 3 straight out of
+  the box. Catalog uses developer defined indexes for searching. In other words,
+  you have to define the indexes you want to use to search you objects before you
+  perform the actual search.
+
+


Property changes on: grok/trunk/doc/minitutorials/index.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/trunk/doc/minitutorials/macros.txt
===================================================================
--- grok/trunk/doc/minitutorials/macros.txt	                        (rev 0)
+++ grok/trunk/doc/minitutorials/macros.txt	2007-07-07 22:19:52 UTC (rev 77594)
@@ -0,0 +1,247 @@
+============================
+Mini-Howto: Macros with Grok
+============================
+
+Intended Audience:
+
+  * Python Developers
+
+  * Zope 2 Developers
+
+  * Zope 3 Developers
+
+
+
+Introduction
+------------
+
+Macros are a way to define a chunk of presentation in one template,
+and share it in others. Changes to the macro are immediately reflected
+in all of the places, that share it.
+
+Such, a developer can easily write some sort of 'page-skeleton' (the
+macro), which can be reused in other pages to take care, for instance,
+for a certain and consistent look-and-feel of a whole site with less
+maintenance.
+
+Technically, macros are made available by ``METAL``, a Macro Expansion
+for TAL, which ships with nearly every Zope installation. They can be
+used in Zope Page Templates. See the `TAL`_ and `METAL`_ pages for
+details.
+
+.. _`TAL`: http://wiki.zope.org/ZPT/TAL
+
+.. _`METAL`: http://wiki.zope.org/ZPT/METAL
+
+
+
+Defining a simple macro
+-----------------------
+
+In Grok macros are defined in usual views, where the associated page
+templates contain `metal`-statements to define the desired
+macros. Macros generally are attributes of the page template wherein they
+are defined, but to get them rendered, we usually use views.
+
+We define a view ``MyMacros`` the usual way in ``app.py``::
+
+   import grok
+
+   class Sample(grok.Application, grok.Container):
+       pass
+
+   class Index(grok.View):
+       pass # see app_templates/index.pt
+
+   class MyMacros(grok.View):
+       """The macro holder"""
+       grok.context(Sample) # The default model this view is bound to.
+
+In the associated page template ``app_templates/mymacros.pt`` we
+define the macros we like to have available. You define macros with
+the ``METAL`` attribute::
+
+    metal:define-macro="<macro-name>"
+
+and the slots therein with::
+
+    metal:define-slots=<slot-name> 
+
+Let's define a very plain page macro::
+
+   <html metal:define-macro="mypage">
+     <head></head>
+     <body>
+       The content:
+       <div metal:define-slot="mycontent">
+         Put your content here...
+       </div>
+     </body>
+   </html>
+
+Here we defined a single macro ``mypage`` with only one slot
+``mycontent``. 
+
+If we restart our Zope instance (don't forget to put some ``index.pt``
+into ``app_templates/``) and have created our application as ``test``,
+we now can go to the following URL::
+
+    http://localhost:8080/test/mymacros
+
+and see the output::
+
+    The content:
+    Put your content here...
+
+Allright.
+
+
+Referencing a simple macro
+--------------------------
+
+In ``index.pt`` we now want to *use* the macro defined in
+``mymacros.pt``. Using a macro means to let it render a part of
+another page template, especially, filling the slots defined in
+``mymacros.pt`` with content defined in ``index.pt``. You call macros
+with the ``METAL`` attribute::
+
+     metal:use-macro="<macro-location>" 
+
+Our ``app_templates/index.pt`` can be that simple::
+
+    <html metal:use-macro="context/@@mymacros/mypage">
+    </html>
+
+Watching::
+
+	http://localhost:8080/test/index
+
+should now give the same result as above, although we didn't call
+``mymacros`` in browser, but ``index``. That's what macros are made
+for.
+
+When we fill the slots, we get different content rendered within
+the same macro. You can fill slots using
+
+    metal:fill-slot="<slot-name>"
+
+where the slot-name must be defined in the macro. Now, change
+``indext.pt`` to::
+
+    <html metal:use-macro="context/@@mymacros/mypage">
+      <body>
+        <div metal:fill-slot="body">
+          My content from index.pt
+        </div>
+      </body>
+    </html>
+
+and you will get the output::
+
+    The content:
+    My content from index.pt
+
+The pattern of the macro reference (the <macro-location>) used here
+is::
+
+    context/<view-name>/<macro-name>
+
+whereas ``context`` references the object being viewed, which in our
+case is the ``Sample`` application. In plain English we want Zope to
+look for a view for a ``Sample`` application object (``test``) which
+is called ``mymacros`` and contains a macro called ``mypage``.
+
+The logic behind this is, that views are always registered for certain
+object types. Registering a view with some kind of object (using
+``grok.context()`` for example), means, that we promise, that this
+view can render objects of that type. (It is up to you to make sure,
+that the view can handle rendering of that object type).
+
+It is not a bad idea to register views for interfaces (instead of
+implementing classes), because it means, that a view will remain
+usable, while an implementation of an interface can change. [FIXME: Is
+this a lie?] This is done in the section `Defining 'all-purpose'
+macros`_ below.
+
+
+Background: how ``grok.View`` and macros interact
+-------------------------------------------------
+
+In case of ``grok.View`` views are in fact ``BrowserPage`` objects
+with an attribute ``template``, which is the associated page
+template. The associated page template in turn has got an attribute
+``macros``, which is a dictionary containing all the macros defined in
+the page template with their names as keys (or ``None``). 
+
+This means, that you can also reference a macro of a ``grok.View``
+using::
+
+     context/<view-name>/template/macros/<macro-name>
+
+Grok shortens this path for you by mapping the ``macros`` dictionary
+keys to the associated ``grok.View``. If you define a macro
+``mymacro`` in a template associated with a ``grok.View`` called
+``myview``, this view will map ``mymacro`` as an own attribute, so
+that you can ask for the attribute ``mymacro`` of the *view*, wheras
+it is in fact an attribute of the associated template.
+
+Such, you can write in short for the above pattern::
+
+      context/<view-name>/<macro-name>
+
+View names always start with the 'eyes' (``@@``) which is a shortcut
+for ``++view++<view-name>``.
+
+
+Defining 'all-purpose' macros
+------------------------------
+
+To define an 'all-purpose' macro, i.e. a macro, that can render
+objects of (nearly) any type and thus be accessed from any
+other page template, just set a very general context for your macro
+view::
+
+    from zope.interface import Interface
+    import grok
+
+    class Master(grok.View):
+        grok.context(Interface)
+
+and reference the macros of the associated pagetemplate like this::
+
+    context/@@master/<macro-name>
+
+Because the macros in ``Master`` now are 'bound' (in fact their view
+is bound) to ``Interface`` and every Grok application, model or
+container implements some interface, the ``Master`` macros will be
+accessible from nearly every other context. ``Master`` promises to be
+a view for every object, which implements ``Interface``.
+
+
+Accessing Zope3 standard macros
+-------------------------------
+
+The standard macros of Zope 3, which render also the default ZMI
+pages, are accessible under the view-name ``standard_macros`` and usually
+provide slots ``title``, ``headers`` and ``body``. It is
+good style to provide this slots with your homegrown views as well.
+
+To give your pages standard Zope3 look, you can do something like
+this in your page template::
+
+        <html metal:use-macro="context/@@standard_macros/page">
+          <head>
+            <title metal:fill-slot="title">
+              Document Title
+            </title>
+            <metal:headers fill-slot="headers">
+              <!-- Additional headers here... -->
+            </metal:headers>
+          </head>
+          <body>
+            <div metal:fill-slot="body">
+              Your content here...
+            </div>
+          </body>
+        </html>
+


Property changes on: grok/trunk/doc/minitutorials/macros.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Modified: grok/trunk/doc/minitutorials/searching.txt
===================================================================
--- grok/trunk/doc/minitutorials/searching.txt	2007-07-07 21:45:44 UTC (rev 77593)
+++ grok/trunk/doc/minitutorials/searching.txt	2007-07-07 22:19:52 UTC (rev 77594)
@@ -4,20 +4,29 @@
 
 Introduction
 ------------
-Grok supports the vanilla indexing services available in Zope 3 straight out of the box. Catalog uses developer defined indexes for searching. In other words, you have to define the indexes you want to use to search you objects before you perform the actual search.
+Grok supports the vanilla indexing services available in Zope 3 straight out of
+the box. Catalog uses developer defined indexes for searching. In other words,
+you have to define the indexes you want to use to search you objects before you
+perform the actual search.
 
 * FieldIndex: search matching an entire field
 * SetIndex: search for keywords in a field
 * TextIndex: full-text searching
 * ValueSearch: search for values using ranges
 
-The time for Zope to generate a new index is proportional to the amount of objects that need to be analysed.
+The time for Zope to generate a new index is proportional to the amount of
+objects that need to be analysed.
 
 Setup
 -----
-The egg (package) containing the search functionality is called [zc.catalog-x.x.x-py2.x.egg] and is installed when "buildout.cfg" contains "zope.app.catalog" in the list of the directive "zcml=". This is the default configuration.
+The egg (package) containing the search functionality is called
+[zc.catalog-x.x.x-py2.x.egg] and is installed when "buildout.cfg" contains
+"zope.app.catalog" in the list of the directive "zcml=". This is the default
+configuration.
 
-Some applications might require specific versions of catalog. This is specified in the "setup.py" script. The following directive indicates that zc.catalog version 1.1.1 is required.
+Some applications might require specific versions of catalog. This is specified
+in the "setup.py" script. The following directive indicates that zc.catalog
+version 1.1.1 is required.
 
 ::
 
@@ -28,7 +37,8 @@
                   'hurry.workflow',
                   ],
 
-The "hurry.query" package gives you some simple tools to perform advanced searching. (add "hurry.query" to "zcml=" in "buildout.cfg")
+The "hurry.query" package gives you some simple tools to perform advanced
+searching. (add "hurry.query" to "zcml=" in "buildout.cfg")
 
 Example
 -------
@@ -110,8 +120,11 @@
 
 Note
 ----
-In the above example, the indexes are only added when a new application is installed. You will have to manually create new indexes if you wish to add them to an existing application.
+In the above example, the indexes are only added when a new application is
+installed. You will have to manually create new indexes if you wish to add them
+to an existing application.
 
 Learning More
 -------------
-The "hurry.query" package contains the DocTest "query.txt" that shows how to perform more complex search queries.
\ No newline at end of file
+The "hurry.query" package contains the DocTest "query.txt" that shows how to
+perform more complex search queries.

Modified: grok/trunk/doc/template.pt
===================================================================
--- grok/trunk/doc/template.pt	2007-07-07 21:45:44 UTC (rev 77593)
+++ grok/trunk/doc/template.pt	2007-07-07 22:19:52 UTC (rev 77594)
@@ -8,14 +8,14 @@
   <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
   <meta name="description" content="Grok - now even cavemen can use Zope3" />
   <meta name="keywords" content="Grok, internet, zope, zope3, software, web apps, web applications, python" />
-	<style type="text/css"><!-- @import url(./resources/grok.css); --></style>
+	<style type="text/css"><!-- @import url(/resources/grok.css); --></style>
 </head>
 
 <body>
 <div class="header">
 	
 	<a href="http://grok.zope.org">
-	<img src="./resources/grok-header.jpg" alt="GROK"/></a>
+	<img src="/resources/grok-header.jpg" alt="GROK"/></a>
 	<ul id="navigation">
         <li tal:repeat="item context/menu">
             <a tal:content="item/title"
@@ -29,7 +29,7 @@
 <div class="roundcont">
 	
   <div class="roundtop">
-    <img src="./resources/corner-topleft.jpg" alt="" 
+    <img src="/resources/corner-topleft.jpg" alt="" 
            width="45" height="45" class="corner" 
            style="display: none" />
   </div>
@@ -41,7 +41,7 @@
   </div>
 
   <div class="roundbottom">
-     <img src="./resources/corner-bottomleft.jpg" alt="" 
+     <img src="/resources/corner-bottomleft.jpg" alt="" 
      width="45" height="45" class="corner" 
      style="display: none" />
   </div>
@@ -52,10 +52,10 @@
 	
 	<table><tr><td>
 	Grok cooks around the campfire of <br />
-	<a href="http://wiki.zope.org/zope3/FrontPage"><img src="./resources/zopelogo.gif" alt="Zope" style="padding: 0.5em;" /></a>
+	<a href="http://wiki.zope.org/zope3/FrontPage"><img src="/resources/zopelogo.gif" alt="Zope" style="padding: 0.5em;" /></a>
 	</td><td>
 	 and roams free on the savannah of<br />
-	<a href="http://www.python.org"><img src="./resources/python-logo.gif" style="padding: 0.5em;" alt="Python" /></a>
+	<a href="http://www.python.org"><img src="/resources/python-logo.gif" style="padding: 0.5em;" alt="Python" /></a>
 	</td></tr>
 	</table>
 



More information about the Checkins mailing list