Commit cff4baf4 authored by Hanno Schlichting's avatar Hanno Schlichting

Removed `Products.ZReST` and the `reStructuredText` wrapper, you can use...

Removed `Products.ZReST` and the `reStructuredText` wrapper, you can use `docutils` directly to gain `reST` support.
parent 1a3dbdc0
...@@ -41,6 +41,9 @@ Features Added ...@@ -41,6 +41,9 @@ Features Added
Restructuring Restructuring
+++++++++++++ +++++++++++++
- Removed `Products.ZReST` and the `reStructuredText` wrapper, you can use
`docutils` directly to gain `reST` support.
- Removed special code to create user folders and page templates while creating - Removed special code to create user folders and page templates while creating
new `OFS.Folder` instances. new `OFS.Folder` instances.
......
...@@ -12,14 +12,6 @@ ...@@ -12,14 +12,6 @@
# #
############################################################################## ##############################################################################
"""Simple access to configuration values.
The configuration values are represented as a single object with
attributes for each bit of information.
"""
import sys
_config = None _config = None
def getConfiguration(): def getConfiguration():
...@@ -89,13 +81,6 @@ class DefaultConfiguration: ...@@ -89,13 +81,6 @@ class DefaultConfiguration:
self.enable_product_installation = False self.enable_product_installation = False
self.locale = None self.locale = None
# restructured text
default_enc = sys.getdefaultencoding()
self.rest_input_encoding = default_enc
self.rest_output_encoding = default_enc
self.rest_header_level = 3
self.rest_language_code = 'en'
# ZServer.HTTPServer # ZServer.HTTPServer
self.http_header_max_length = 8196 self.http_header_max_length = 8196
......
----------------------------------
ReStructuredText Document for Zope
----------------------------------
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
Character set encoding issues
=============================
ZReST instances have a property "input_encoding" to specify
the encoding of your reST document. "output_encoding" is
used the encoding of the output. You can specify any valid
encoding that is known to Python (e.g. "iso-8859-1" or "utf-8").
Footnotes
=========
This product was written by Richard Jones, rjones@ekit-inc.com.
Minor extensions for the Zope 2.7 integration by Andreas Jung,
andreas@andreas-jung.com.
Please direct questions about ReStructureText to the docutils mailing lists.
This package is placed in the Public Domain.
This diff is collapsed.
# product initialisation
import ZReST
def initialize(context):
context.registerClass(
ZReST.ZReST,
meta_type = 'ReStructuredText Document',
constructors = (ZReST.manage_addZReSTForm, ZReST.manage_addZReST)
)
<dtml-var manage_page_header>
<dtml-var "manage_form_title(this(), _, form_title='Add ReStructureText Document')">
<p class="form-help">
You may optionally select a file to upload from your local computer by
clicking the <em>Browse</em> button.
</p>
<form action="manage_addZReST" method="post" enctype="multipart/form-data">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-optional">
File
</div>
</td>
<td align="left" valign="top">
<input type="file" name="file" size="25" value="" />
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Add " />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<p class="form-help">
You may edit the source for this document using the form below. You
may also upload the source for this document from a local file. Click
the <em>browse</em> button to select a local file to upload.
</p>
<dtml-if warnings>
<pre class="system-msg">
&dtml-warnings;
</pre>
</dtml-if>
<p class="form-help"><strong>Help:</strong> ReStructuredText
<a href="http://docutils.sourceforge.net/docs/rst/quickstart.html">primer</a>
for beginners,
<a href="http://docutils.sourceforge.net/docs/rst/quickref.html">quick
reference</a> for the more advanced and
<a href="http://docutils.sourceforge.net/rst.html">home page</a> for all
the details.
</p>
<form action="manage_edit" method="post">
<table cellpadding="2" cellspacing="0" width="100%" border="0">
<dtml-with keyword_args mapping>
<tr>
<td align="left" valign="top" colspan="2">
<div style="width: 100%;">
<dtml-let cols="REQUEST.get('dtpref_cols', '100%')"
rows="REQUEST.get('dtpref_rows', '20')">
<dtml-if "cols[-1]=='%'">
<textarea name="data:text" wrap="off" style="width: &dtml-cols;;"
<dtml-else>
<textarea name="data:text" wrap="off" cols="&dtml-cols;"
</dtml-if>
rows="&dtml-rows;"><dtml-var __str__></textarea>
</dtml-let>
</div>
</td>
</tr>
</dtml-with>
<tr>
<td align="left" valign="top" colspan="2">
<div class="form-element">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" name="SUBMIT" value="Save Changes">
</dtml-if>
&nbsp;&nbsp;
<input class="form-element" type="submit" name="SUBMIT" value="Taller">
<input class="form-element" type="submit" name="SUBMIT" value="Shorter">
<input class="form-element" type="submit" name="SUBMIT" value="Wider">
<input class="form-element" type="submit" name="SUBMIT" value="Narrower">
</div>
</td>
</tr>
</table>
</form>
<form action="manage_upload" method="post" enctype="multipart/form-data">
<table cellpadding="2" cellspacing="0" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
File &nbsp;
</div>
</td>
<td align="left" valign="top">
<input type="file" name="file" size="25" value="">
</td>
</tr>
<tr>
<td></td>
<td align="left" valign="top">
<div class="form-element">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" value="Upload File">
</dtml-if>
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
""" Unit tests for ZReST product.
"""
# -*- coding: utf-8 -*-
""" Unit tests for ZReST objects
"""
import unittest
import cgi
import tempfile
txt = """Hello World
============
text text
Von V\xc3\xb6geln und \xc3\x96fen
===================
- some
- more
- text
"""
csv_text = """bin:x:1:1:bin:/bin:/bin/bash
daemon:x:2:2:Daemon:/sbin:/bin/bash
"""
docutils_include_warning = '(WARNING/2) "include" directive disabled.'
docutils_raw_warning = '(WARNING/2) "raw" directive disabled.'
class TestZReST(unittest.TestCase):
def _getTargetClass(self):
from Products.ZReST.ZReST import ZReST
return ZReST
def _makeOne(self, id='test', *args, **kw):
return self._getTargetClass()(id=id, *args, **kw)
def _csvfile(self):
fn = tempfile.mktemp()
open(fn, 'w').write(csv_text)
return fn
def test_empty(self):
empty = self._makeOne()
# New instances should not have non-volatile cache attributes
self.assertRaises(AttributeError, lambda: empty.formatted)
self.assertRaises(AttributeError, lambda: empty.warnings)
self.assertEqual(empty._v_formatted, None)
self.assertEqual(empty._v_warnings, None)
def test_formatted_ignored(self):
resty = self._makeOne()
resty.formatted = 'IGNORE ME'
self.assertFalse('IGNORE ME' in resty.index_html())
def testConversion(self):
resty = self._makeOne()
resty.source = txt
resty.input_encoding = 'utf-8'
resty.output_encoding = 'utf-8'
resty.render()
html = resty.index_html()
s = '<h1>Hello World</h1>'
self.assertEqual(s in html, True)
s = '<h1>Von V\xc3\xb6geln und \xc3\x96fen</h1>'
self.assertEqual(s in html, True)
# ZReST should render a complete HTML document
self.assertEqual('<html' in html, True)
self.assertEqual('<body>' in html, True)
def test_include_directive_raises(self):
resty = self._makeOne()
resty.source = 'hello world\n .. include:: /etc/passwd'
result = resty.render()
warnings = ''.join(resty._v_warnings.messages)
# The include: directive hasn't been rendered, it remains
# verbatimly in the rendered output. Instead a warning
# message is presented:
self.assert_(docutils_include_warning in warnings)
def test_raw_directive_disabled(self):
resty = self._makeOne()
EXPECTED = '<h1>HELLO WORLD</h1>'
resty.source = '.. raw:: html\n\n %s\n' % EXPECTED
result = resty.render()
warnings = ''.join(resty._v_warnings.messages)
# The raw: directive hasn't been rendered, it remains
# verbatimly in the rendered output. Instead a warning
# message is presented:
self.assert_(EXPECTED not in result)
self.assert_(cgi.escape(EXPECTED) in result)
self.assert_(docutils_raw_warning in warnings)
def test_raw_directive_file_directive_raises(self):
resty = self._makeOne()
resty.source = '.. raw:: html\n :file: inclusion.txt'
result = resty.render()
warnings = ''.join(resty._v_warnings.messages)
# The raw: directive hasn't been rendered, it remains
# verbatimly in the rendered output. Instead a warning
# message is presented:
self.assert_(docutils_raw_warning in warnings)
def test_raw_directive_url_directive_raises(self):
resty = self._makeOne()
resty.source = '.. raw:: html\n :url: http://www.zope.org/'
result = resty.render()
warnings = ''.join(resty._v_warnings.messages)
# The raw: directive hasn't been rendered, it remains
# verbatimly in the rendered output. Instead a warning
# message is presented:
self.assert_(docutils_raw_warning in warnings)
def test_csv_table_file_option_raise(self):
resty = self._makeOne()
csv_file = self._csvfile()
resty.source = '.. csv-table:: \n :file: %s' % csv_file
result = resty.render()
self.assertTrue('daemon' not in result,
'csv-table/file directive is not disabled!')
def test_csv_table_url_option_raise(self):
resty = self._makeOne()
csv_file = self._csvfile()
resty.source = '.. csv-table:: \n :url: file://%s' % csv_file
result = resty.render()
self.assertTrue('daemon' not in result,
'csv-table/url directive is not disabled!')
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestZReST))
return suite
...@@ -61,26 +61,6 @@ def suppress_all_site_roots(value): ...@@ -61,26 +61,6 @@ def suppress_all_site_roots(value):
value and _setenv('SUPPRESS_SITEROOT', value) value and _setenv('SUPPRESS_SITEROOT', value)
return value return value
def structured_text_header_level(value):
value is not None and _setenv('STX_DEFAULT_LEVEL', value)
return value
def rest_input_encoding(value):
value and _setenv('REST_INPUT_ENCODING' , value)
return value
def rest_output_encoding(value):
value and _setenv('REST_OUTPUT_ENCODING' , value)
return value
def rest_header_level(value):
value and _setenv('REST_DEFAULT_LEVEL' , value)
return value
def rest_language_code(value):
value and _setenv('REST_LANGUAGE_CODE' , value)
return value
def large_file_threshold(value): def large_file_threshold(value):
import ZServer import ZServer
ZServer.LARGE_FILE_THRESHOLD = value ZServer.LARGE_FILE_THRESHOLD = value
......
...@@ -472,53 +472,6 @@ ...@@ -472,53 +472,6 @@
</description> </description>
</key> </key>
<key name="structured-text-header-level" datatype="integer" default="3"
handler="structured_text_header_level">
<description>
Set the default starting HTML header level for structured text
documents. The default is 3, which implies that top-level headers
will be created with an H3 HTML tag.
</description>
<metadefault>3</metadefault>
</key>
<key name="rest-input-encoding" handler="rest_input_encoding">
<description>
Specifies the input encoding of re-StructuredText documents
(e.g. 'utf-8', 'iso-8859' or any other valid encoding recognized
by Python). The default is your Python's default encoding.
</description>
<metadefault>unset</metadefault>
</key>
<key name="rest-output-encoding" handler="rest_output_encoding">
<description>
Specifies the output encoding of re-StructuredText documents
(e.g. 'utf-8', 'iso-8859' or any other valid encoding recognized
by Python). The default is your Python's default encoding.
</description>
<metadefault>unset</metadefault>
</key>
<key name="rest-header-level" datatype="integer" default="3"
handler="rest_header_level">
<description>
Set the default starting HTML header level for restructured text
documents. The default is 3, which implies that top-level headers
will be created with an H3 HTML tag.
</description>
<metadefault>3</metadefault>
</key>
<key name="rest-language-code" handler="rest_language_code" default="en">
<description>
Language code used for some internal translations inside of the docutils
package and for DTD bibliographic elements mapping. See
lib/python/docutils/languages/ for a list of supported language codes.
</description>
<metadefault>en</metadefault>
</key>
<key name="publisher-profile-file"> <key name="publisher-profile-file">
<description> <description>
Causing this directive to point to a file on the filesystem will Causing this directive to point to a file on the filesystem will
......
##############################################################################
#
# Copyright (c) 2002 Zope Foundation and Contributors.
#
# 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
#
##############################################################################
"""Wrapper to integrate reStructuredText into Zope
"""
# Disable inclusion of files for security reasons. We do this by
# changing the default value of the ``file_insertion_enabled``
# parameter to False.
import docutils.parsers.rst
for title, options, conf in docutils.parsers.rst.Parser.settings_spec[2]:
if options == ['--file-insertion-enabled']:
conf['default'] = 0
break
import sys
from App.config import getConfiguration
from docutils.core import publish_parts
# get encoding
default_enc = sys.getdefaultencoding()
default_output_encoding = getConfiguration().rest_output_encoding or default_enc
default_input_encoding = getConfiguration().rest_input_encoding or default_enc
# starting level for <H> elements (default behaviour inside Zope is <H3>)
default_level = 3
initial_header_level = getConfiguration().rest_header_level or default_level
# default language used for internal translations and language mappings for DTD
# elements
default_lang = 'en'
default_language_code = getConfiguration().rest_language_code or default_lang
class Warnings:
def __init__(self):
self.messages = []
def write(self, message):
self.messages.append(message)
def render(src,
writer='html4css1',
report_level=1,
stylesheet=None,
input_encoding=default_input_encoding,
output_encoding=default_output_encoding,
language_code=default_language_code,
initial_header_level = initial_header_level,
settings = {}):
"""get the rendered parts of the document the and warning object
"""
# Docutils settings:
settings = settings.copy()
settings['input_encoding'] = input_encoding
settings['output_encoding'] = output_encoding
settings['stylesheet'] = stylesheet
settings['stylesheet_path'] = None
settings['file_insertion_enabled'] = 0
settings['raw_enabled'] = 0
if language_code:
settings['language_code'] = language_code
settings['language_code'] = language_code
# starting level for <H> elements:
settings['initial_header_level'] = initial_header_level + 1
# set the reporting level to something sane:
settings['report_level'] = report_level
# don't break if we get errors:
settings['halt_level'] = 6
# remember warnings:
settings['warning_stream'] = warning_stream = Warnings()
parts = publish_parts(source=src, writer_name=writer,
settings_overrides=settings,
config_section='zope application')
return parts, warning_stream
def HTML(src,
writer='html4css1',
report_level=1,
stylesheet=None,
input_encoding=default_input_encoding,
output_encoding=default_output_encoding,
language_code=default_language_code,
initial_header_level = initial_header_level,
warnings = None,
settings = {}):
""" render HTML from a reStructuredText string
- 'src' -- string containing a valid reST document
- 'writer' -- docutils writer
- 'report_level' - verbosity of reST parser
- 'stylesheet' - Stylesheet to be used
- 'input_encoding' - encoding of the reST input string
- 'output_encoding' - encoding of the rendered HTML output
- 'report_level' - verbosity of reST parser
- 'language_code' - docutils language
- 'initial_header_level' - level of the first header tag
- 'warnings' - will be overwritten with a string containing the warnings
- 'settings' - dict of settings to pass in to Docutils, with priority
"""
parts, warning_stream = render(src,
writer = writer,
report_level = report_level,
stylesheet = stylesheet,
input_encoding = input_encoding,
output_encoding = output_encoding,
language_code=language_code,
initial_header_level = initial_header_level,
settings = settings)
header = '<h%(level)s class="title">%(title)s</h%(level)s>\n' % {
'level': initial_header_level,
'title': parts['title'],
}
subheader = '<h%(level)s class="subtitle">%(subtitle)s</h%(level)s>\n' % {
'level': initial_header_level+1,
'subtitle': parts['subtitle'],
}
body = '%(docinfo)s%(body)s' % {
'docinfo': parts['docinfo'],
'body': parts['body'],
}
output = ''
if parts['title']:
output = output + header
if parts['subtitle']:
output = output + subheader
output = output + body
warnings = ''.join(warning_stream.messages)
if output_encoding != 'unicode':
return output.encode(output_encoding)
else:
return output
__all__ = ("HTML", 'render')
# -*- coding: utf-8 -*-
import unittest
import cgi
from docutils.core import publish_parts
from reStructuredText import HTML, Warnings
txt = """Hello World
============
text text
Von V\xc3\xb6geln und \xc3\x96fen
===================
- some
- more
- text
"""
docutils_include_warning = '''\
<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">&lt;string&gt;</tt>, line 2)</p>
<p>&quot;include&quot; directive disabled.</p>'''
docutils_raw_warning = '''\
<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">&lt;string&gt;</tt>, line 1)</p>
<p>&quot;raw&quot; directive disabled.</p>'''
class TestReST(unittest.TestCase):
def testRoman(self):
# Make sure we can import the rst parser
from docutils.parsers import rst
def testEncodings(self):
def _test(txt, in_enc, out_enc):
return HTML(txt,
input_encoding=in_enc,
output_encoding=out_enc)
encoding = 'utf-8'
html = _test(txt, encoding, encoding)
self.assertEqual('V\xc3\xb6gel' in html, True)
self.assertEqual('\xc3\x96fen' in html, True)
html = _test(txt, encoding, 'unicode')
self.assertEqual(unicode('V\xc3\xb6gel', encoding) in html, True)
self.assertEqual(unicode('\xc3\x96fen', encoding) in html, True)
html = _test(unicode(txt, encoding), 'unicode', encoding)
self.assertEqual('V\xc3\xb6gel' in html, True)
self.assertEqual('\xc3\x96fen' in html, True)
html = _test(unicode(txt, encoding), 'unicode', 'unicode')
self.assertEqual(unicode('V\xc3\xb6gel', encoding) in html, True)
self.assertEqual(unicode('\xc3\x96fen', encoding) in html, True)
def testHeaderLevel(self):
encoding = 'utf-8'
for level in range(0, 5):
html = HTML(txt, input_encoding=encoding,
output_encoding=encoding,
initial_header_level=level)
expected = '<h%d>Hello World</h%d>' % (level+1, level+1)
self.assertEqual(expected in html, True)
expected = '<h%d>Von V\xc3\xb6geln und \xc3\x96fen</h%d>' % (
level+1, level+1)
self.assertEqual(expected in html, True)
def testWithSingleSubtitle(self):
input = '''
title
-----
subtitle
++++++++
text
'''
expected='''<h3 class="title">title</h3>
<h4 class="subtitle">subtitle</h4>
<p>text</p>
'''
output = HTML(input)
self.assertEquals(output, expected)
def test_file_insertion_off_by_default(self):
directive = '.. include:: /etc/passwd'
source = 'hello world\n %s' % directive
parts = publish_parts(source=source, writer_name='html4css1',
settings_overrides={'warning_stream': Warnings()})
# The include: directive hasn't been rendered, it remains
# verbatimly in the rendered output. Instead a warning
# message is presented:
self.assert_(directive in parts['body'])
self.assert_(docutils_include_warning in parts['body'])
def test_include_directive_raises(self):
directive = '.. include:: /etc/passwd'
source = 'hello world\n %s' % directive
result = HTML(source)
# The include: directive hasn't been rendered, it remains
# verbatimly in the rendered output. Instead a warning
# message is presented:
self.assert_(directive in result)
self.assert_(docutils_include_warning in result)
def test_raw_directive_disabled(self):
EXPECTED = '<h1>HELLO WORLD</h1>'
source = '.. raw:: html\n\n %s\n' % EXPECTED
result = HTML(source) # don't raise, but don't work either
# The raw: directive hasn't been rendered, it remains
# verbatimly in the rendered output. Instead a warning
# message is presented:
self.assert_(EXPECTED not in result)
self.assert_(cgi.escape(EXPECTED) in result)
self.assert_(docutils_raw_warning in result)
def test_raw_directive_file_option_raises(self):
source = '.. raw:: html\n :file: inclusion.txt'
result = HTML(source)
# The raw: directive hasn't been rendered, it remains
# verbatimly in the rendered output. Instead a warning
# message is presented:
self.assert_(source in result)
self.assert_(docutils_raw_warning in result)
def test_raw_directive_url_option_raises(self):
source = '.. raw:: html\n :url: http://www.zope.org'
result = HTML(source)
# The raw: directive hasn't been rendered, it remains
# verbatimly in the rendered output. Instead a warning
# message is presented:
self.assert_(source in result)
self.assert_(docutils_raw_warning in result)
def test_csv_table_file_option_raise(self):
source = '.. csv-table:: \n :file: inclusion.txt'
result = HTML(source)
self.assertTrue('File and URL access deactivated' in result)
def test_csv_table_url_option_raise(self):
source = '.. csv-table:: \n :url: http://www.evil.org'
result = HTML(source)
self.assertTrue('File and URL access deactivated' in result)
def test_suite():
from unittest import TestSuite, makeSuite
return TestSuite((makeSuite(TestReST),))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment