[Zope-Checkins] CVS: Zope/lib/python/Products/ZReST - Makefile:1.2 README.txt:1.2 TODO.txt:1.2 ZReST.py:1.2 __init__.py:1.2 refresh.txt:1.2 version.txt:1.2

Andreas Jung andreas@andreas-jung.com
Sat, 1 Feb 2003 04:29:04 -0500


Update of /cvs-repository/Zope/lib/python/Products/ZReST
In directory cvs.zope.org:/tmp/cvs-serv20197/ZReST

Added Files:
	Makefile README.txt TODO.txt ZReST.py __init__.py refresh.txt 
	version.txt 
Log Message:
merge from ajung-restructuredtext-integration-branch

=== Zope/lib/python/Products/ZReST/Makefile 1.1 => 1.2 ===
--- /dev/null	Sat Feb  1 04:29:03 2003
+++ Zope/lib/python/Products/ZReST/Makefile	Sat Feb  1 04:28:30 2003
@@ -0,0 +1,15 @@
+FILES = ZReST.py __init__.py refresh.txt version.txt TODO.txt README.txt
+DTML = dtml/manage_addZReSTForm.dtml dtml/manage_editForm.dtml
+VERSION := $(shell cat version.txt)
+
+all: ${FILES} ${DTML}
+	rm -rf dist
+	mkdir dist
+	mkdir dist/ZReST
+	mkdir dist/ZReST/dtml
+	cp ${FILES} dist/ZReST
+	cp ${DTML}  dist/ZReST/dtml
+	(cd dist; tar zcf ZReST-${VERSION}.tgz ZReST)
+	mv dist/ZReST-${VERSION}.tgz .
+	rm -rf dist
+


=== Zope/lib/python/Products/ZReST/README.txt 1.1 => 1.2 ===
--- /dev/null	Sat Feb  1 04:29:04 2003
+++ Zope/lib/python/Products/ZReST/README.txt	Sat Feb  1 04:28:30 2003
@@ -0,0 +1,45 @@
+----------------------------------
+ReStructuredText Document for Zope
+----------------------------------
+
+Requirements
+============
+
+To use this product, you will need:
+
+python2.1+
+   see http://www.python.org/
+Zope 2.5+
+   see http://www.zope.org/
+A docutils snapshot from later than 21 August 2002
+   see http://docutils.sourceforge.net/#development-snapshots
+
+Installation
+============
+
+To install this product, unpack it so the ZReST directory is in the Zope
+lib/python/Products directory. You should then restart Zope.
+
+You will now be able to add objects of type "ReStructuredText Document".
+
+Usage
+=====
+
+See the docutils user documentation section:
+
+   http://docutils.sourceforge.net/#user-documentation
+
+I recommend starting with the ReST "primer":
+
+   http://docutils.sourceforge.net/docs/rst/quickstart.html
+
+
+Footnotes
+=========
+
+This product was written by Richard Jones, rjones@ekit-inc.com.
+
+Please direct questions about ReStructureText to the docutils mailing lists.
+
+This package is placed in the Public Domain.
+


=== Zope/lib/python/Products/ZReST/TODO.txt 1.1 => 1.2 ===
--- /dev/null	Sat Feb  1 04:29:04 2003
+++ Zope/lib/python/Products/ZReST/TODO.txt	Sat Feb  1 04:28:30 2003
@@ -0,0 +1,5 @@
+. charset configuration, defaulting to 'latin-1'
+. add "level" and "header" args to render / as_html
+  - level indicates the header level to start at
+  - header boolean turns page header tags on/off
+


=== Zope/lib/python/Products/ZReST/ZReST.py 1.1 => 1.2 ===
--- /dev/null	Sat Feb  1 04:29:04 2003
+++ Zope/lib/python/Products/ZReST/ZReST.py	Sat Feb  1 04:28:30 2003
@@ -0,0 +1,301 @@
+# 
+# $Id$
+#
+''' ReStructuredText Product for Zope
+
+This Product stores two texts - a "source" text in ReStructureText format,
+and a HTML "formatted" version of that text.
+
+'''
+import docutils.core, docutils.io
+
+from Globals import InitializeClass, DTMLFile
+from OFS.SimpleItem import Item
+from OFS.PropertyManager import PropertyManager
+from OFS.History import Historical, html_diff
+from Acquisition import Implicit
+from Persistence import Persistent
+from AccessControl import ClassSecurityInfo
+from AccessControl import ModuleSecurityInfo
+from DateTime.DateTime import DateTime
+import sys
+modulesecurity = ModuleSecurityInfo()
+
+modulesecurity.declareProtected('View management screens',
+    'manage_addZReSTForm')
+manage_addZReSTForm = DTMLFile('dtml/manage_addZReSTForm', globals())
+
+modulesecurity.declareProtected('Add Z Roundups', 'manage_addZReST')
+def manage_addZReST(self, id, file='', REQUEST=None):
+    """Add a ZReST product """
+    # validate the instance_home
+    self._setObject(id, ZReST(id))
+    self._getOb(id).manage_upload(file)
+    if REQUEST:
+        return self.manage_main(self, REQUEST)
+
+class Warnings:
+    def __init__(self):
+        self.messages = []
+    def write(self, message):
+        self.messages.append(message)
+
+class ZReST(Item, PropertyManager, Historical, Implicit, Persistent):
+    '''An instance of this class provides an interface between Zope and
+       ReStructuredText for one text.
+    '''
+    meta_type =  'ReStructuredText Document'
+    security = ClassSecurityInfo()
+
+    def __init__(self, id):
+        self.id = id
+        self.title = id
+        self.stylesheet = 'default.css'
+        self.report_level = '2'
+        self.source = self.formatted = ''
+
+    # define the properties that define this object
+    _properties = (
+        {'id':'stylesheet', 'type': 'string', 'mode': 'w',
+            'default': 'default.css'},
+        {'id':'report_level', 'type': 'string', 'mode': 'w', 'default': '2'},
+    )
+    property_extensible_schema__ = 0
+
+    # define the tabs for the management interface
+    manage_options= ( {'label': 'Edit', 'action':'manage_main'},
+                      {'label': 'View', 'action':'index_html'},
+                      {'label': 'Source', 'action':'source_txt'},
+                    ) \
+        + PropertyManager.manage_options \
+        + Historical.manage_options \
+        + Item.manage_options
+
+    # access to the source text and formatted text
+    security.declareProtected('View', 'index_html')
+    def index_html(self, REQUEST=None):
+        ''' Getting the formatted text
+        '''
+        REQUEST.RESPONSE.setHeader('content-type', 'text/html')
+        return self.formatted
+    security.declareProtected('View', 'source_txt')
+    def source_txt(self, REQUEST=None):
+        ''' Getting the source text
+        '''
+        REQUEST.RESPONSE.setHeader('content-type', 'text/plain')
+        return self.source
+
+    # edit form, which is also the primary interface
+    security.declareProtected('Edit ReStructuredText', 'manage_editForm')
+    manage_main = DTMLFile('dtml/manage_editForm', globals())
+
+    # edit action
+    security.declareProtected('Edit ReStructuredText', 'manage_edit')
+    def manage_edit(self, data, SUBMIT='Change',dtpref_cols='50',
+                    dtpref_rows='20', REQUEST=None):
+        '''Alias index_html to roundup's index
+        '''
+        if self._size_changes.has_key(SUBMIT):
+            return self._er(data, SUBMIT, dtpref_cols, dtpref_rows, REQUEST)
+        if data != self.source:
+            self.source = data
+            self.render()
+
+        if REQUEST:
+            message="Saved changes."
+            return self.manage_main(self, REQUEST, manage_tabs_message=message)
+
+    # handle edit window size changes
+    _size_changes = {
+        'Bigger': (5,5),
+        'Smaller': (-5,-5),
+        'Narrower': (0,-5),
+        'Wider': (0,5),
+        'Taller': (5,0),
+        'Shorter': (-5,0),
+    }
+    def _er(self, data, SUBMIT, dtpref_cols, dtpref_rows, REQUEST):
+        dr,dc = self._size_changes[SUBMIT]
+        rows=max(1,int(dtpref_rows)+dr)
+        cols=max(40,int(dtpref_cols)+dc)
+        e=(DateTime('GMT') + 365).rfc822()
+        resp=REQUEST['RESPONSE']
+        resp.setCookie('dtpref_rows',str(rows),path='/',expires=e)
+        resp.setCookie('dtpref_cols',str(cols),path='/',expires=e)
+        return self.manage_main(self, REQUEST, __str__=self.quotedHTML(data),
+            dtpref_cols=cols, dtpref_rows=rows)
+    security.declarePrivate('quotedHTML')
+    def quotedHTML(self,
+                   text=None,
+                   character_entities=(
+                       (('&'), '&'),
+                       (("<"), '&lt;' ),
+                       ((">"), '&gt;' ),
+                       (('"'), '&quot;'))): #"
+        if text is None: text=self.read_raw()
+        for re,name in character_entities:
+            if text.find(re) >= 0: text=name.join(text.split(re))
+        return text
+
+
+    # handle uploads too
+    security.declareProtected('Edit ReStructuredText', 'manage_upload')
+    def manage_upload(self, file='', REQUEST=None):
+        ''' Replaces the current source with the upload.
+        '''
+        if isinstance(file, type('')):
+            self.source = file
+        else:
+            self.source = file.read()
+        self.render()
+
+        if REQUEST:
+            message="Saved changes."
+            return self.manage_main(self, REQUEST, manage_tabs_message=message)
+
+    security.declarePrivate('render')
+    def render(self):
+        ''' Render the source to HTML
+        '''
+        # format with strings
+        pub = docutils.core.Publisher()
+        pub.set_reader('standalone', None, 'restructuredtext')
+        pub.set_writer('html')
+
+        # go with the defaults
+        pub.get_settings()
+
+        # this is needed, but doesn't seem to do anything
+        pub.settings._destination = ''
+
+        # use the stylesheet chosen by the user
+        pub.settings.stylesheet = self.stylesheet
+
+        # set the reporting level to something sane
+        pub.settings.report_level = int(self.report_level)
+
+        # don't break if we get errors
+        pub.settings.halt_level = 6
+
+        # remember warnings
+        pub.settings.warning_stream = Warnings()
+
+        # input
+        pub.source = docutils.io.StringInput(
+            source=self.source, encoding=sys.getdefaultencoding())
+
+        # output - not that it's needed
+        pub.destination = docutils.io.StringOutput(
+            encoding=sys.getdefaultencoding())
+
+        # parse!
+        document = pub.reader.read(pub.source, pub.parser, pub.settings)
+        self.warnings = ''.join(pub.settings.warning_stream.messages)
+
+        if document.children:
+            item = document.children[0]
+            if item.tagname == 'title':
+                self.title = str(item.children[0])
+
+        # do the format
+        self.formatted = pub.writer.write(document, pub.destination)
+
+
+    security.declareProtected('Edit ReStructuredText', 'PUT', 'manage_FTPput')
+    def PUT(self, REQUEST, RESPONSE):
+        ''' Handle HTTP PUT requests
+        '''
+        data = REQUEST.get('BODY', '')
+        if data != self.source:
+            if data.startswith('.. '):
+                data = data.splitlines()
+                new = []
+                for i in range(len(data)):
+                    line = data[i]
+                    if not line.startswith('.. '):
+                        break
+                    if line.startswith('.. stylesheet='):
+                        self.stylesheet = line.split('=')[1]
+                    elif line.startswith('.. report_level='):
+                        self.report_level = line.split('=')[1]
+                    else:
+                        pass # ignore
+                data = '\n'.join(new) + '\n'.join(data[i:])
+            self.source = data
+            self.render()
+        RESPONSE.setStatus(204)
+        return RESPONSE        
+
+    manage_FTPput = PUT
+
+    def manage_FTPget(self):
+        ''' Get source for FTP download
+        '''
+        self.REQUEST.RESPONSE.setHeader('Content-Type', 'text/plain')
+        s = [
+            '.. This is a ReStructuredText Document. Initial comment lines '
+                '(".. ") will be stripped.',
+            '.. stylesheet='+self.stylesheet,
+            '.. report_level='+self.report_level
+        ]
+        if self.warnings:
+            s.append('.. ')
+            s.append('.. ' + '\n.. '.join(self.warnings.splitlines()))
+        s.append('.. ')
+        return '\n'.join(s) + '\n' + self.source
+
+    def __str__(self):
+        ''' Stringfy .. return the source
+        '''
+        return self.quotedHTML(self.source)
+
+    def PrincipiaSearchSource(self):
+        ''' Support for searching - the document's contents are searched.
+        '''
+        return self.source
+
+    def manage_historyCompare(self, rev1, rev2, REQUEST,
+                              historyComparisonResults=''):
+        return ZReST.inheritedAttribute('manage_historyCompare')(
+            self, rev1, rev2, REQUEST,
+            historyComparisonResults=html_diff(rev1.source, rev2.source))
+
+InitializeClass(ZReST)
+modulesecurity.apply(globals())
+
+
+#
+# $Log$
+# Revision 1.2  2003/02/01 09:28:30  andreasjung
+# merge from ajung-restructuredtext-integration-branch
+#
+# Revision 1.1.2.5  2003/01/30 19:00:24  andreasjung
+# forgot to import sys
+#
+# Revision 1.1.2.4  2003/01/30 18:10:57  andreasjung
+# using Pythons  default encoding instead of the docutils defaults
+#
+# Revision 1.1.2.3  2003/01/30 18:09:44  andreasjung
+# update from RIchards sandbox
+#
+# Revision 1.6  2002/11/28 03:44:50  goodger
+# updated
+#
+# Revision 1.5  2002/11/05 05:27:56  goodger
+# fixed Reader name
+#
+# Revision 1.4  2002/10/18 05:10:33  goodger
+# Refactored names (options -> settings; etc.); updated.
+#
+# Revision 1.3  2002/08/15 05:02:41  richard
+# pull out the document title too
+#
+# Revision 1.2  2002/08/15 04:36:56  richard
+# FTP interface and Reporter message snaffling
+#
+# Revision 1.1  2002/08/14 05:15:37  richard
+# Zope ReStructuredText Product
+#
+#
+#
+# vim: set filetype=python ts=4 sw=4 et si


=== Zope/lib/python/Products/ZReST/__init__.py 1.1 => 1.2 ===
--- /dev/null	Sat Feb  1 04:29:04 2003
+++ Zope/lib/python/Products/ZReST/__init__.py	Sat Feb  1 04:28:30 2003
@@ -0,0 +1,33 @@
+# 
+# $Id$
+#
+__version__='1.0'
+
+# product initialisation
+import ZReST
+def initialize(context):
+    context.registerClass(
+        ZReST, meta_type = 'ReStructuredText Document',
+        constructors = (
+            ZReST.manage_addZReSTForm, ZReST.manage_addZReST
+        )
+    )
+
+
+#
+# $Log$
+# Revision 1.2  2003/02/01 09:28:30  andreasjung
+# merge from ajung-restructuredtext-integration-branch
+#
+# Revision 1.1.2.2  2002/11/06 16:09:36  andreasjung
+# updated to ZReST 1.1
+#
+# Revision 1.2  2002/08/15 04:36:56  richard
+# FTP interface and Reporter message snaffling
+#
+# Revision 1.1  2002/08/14 05:15:37  richard
+# Zope ReStructuredText Product
+#
+#
+#
+# vim: set filetype=python ts=4 sw=4 et si


=== Zope/lib/python/Products/ZReST/refresh.txt 1.1 => 1.2 ===
--- /dev/null	Sat Feb  1 04:29:04 2003
+++ Zope/lib/python/Products/ZReST/refresh.txt	Sat Feb  1 04:28:30 2003
@@ -0,0 +1 @@
+This is a flag that tells Zope that the product may be auto-refreshed.


=== Zope/lib/python/Products/ZReST/version.txt 1.1 => 1.2 ===
--- /dev/null	Sat Feb  1 04:29:04 2003
+++ Zope/lib/python/Products/ZReST/version.txt	Sat Feb  1 04:28:30 2003
@@ -0,0 +1 @@
+1.1