summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docutils/HISTORY.txt1
-rw-r--r--docutils/docs/ref/doctree.txt20
-rw-r--r--docutils/docs/ref/docutils.dtd2
-rw-r--r--docutils/docutils/parsers/rst/states.py24
-rwxr-xr-xdocutils/test/test_parsers/test_rst/test_section_headers.py6
5 files changed, 10 insertions, 43 deletions
diff --git a/docutils/HISTORY.txt b/docutils/HISTORY.txt
index 0a73e1e48..b673af09a 100644
--- a/docutils/HISTORY.txt
+++ b/docutils/HISTORY.txt
@@ -59,6 +59,7 @@ Changes Since 0.3.5
- Moved ``escape2null`` and ``unescape`` functions to docutils/utils.py.
- Changed role function API: the "text" parameter now takes
null-escaped interpreted text content.
+ - Empty sections and documents are allowed now.
* docutils/parsers/rst/directives/__init__.py:
diff --git a/docutils/docs/ref/doctree.txt b/docutils/docs/ref/doctree.txt
index 34784a2ed..fc8e9ae3a 100644
--- a/docutils/docs/ref/doctree.txt
+++ b/docutils/docs/ref/doctree.txt
@@ -4806,18 +4806,14 @@ Entity definition:
( ( (`%body.elements;`_ | topic_ | sidebar_)+,
(transition_, (`%body.elements;`_ | topic_ | sidebar_)+ )*,
( (`%section.elements;`_), (transition_?, (`%section.elements;`_) )* )? )
- | ( (`%section.elements;`_), (transition_?, (`%section.elements;`_) )* ) ) ">
-
-Each document_ or section_ contains either:
-
-- multiple body elements, topics, and/or sidebars, optionally
- interspersed with transitions (but transitions cannot occur at the
- beginning or end, nor may there be two transitions in a row),
- followed by zero or more sections optionally interspersed with
- transitions; or
-
-- one or more sections (whose contents are recursively the same as
- this model) optionally interspersed with transitions.
+ | ( (`%section.elements;`_), (transition_?, (`%section.elements;`_) )* ) )? ">
+
+Each document_ or section_ contains zero or more body elements,
+topics, and/or sidebars, optionally interspersed with transitions (but
+transitions cannot occur at the beginning or end, nor may there be two
+transitions in a row), followed by zero or more sections (whose
+contents are recursively the same as this model) optionally
+interspersed with transitions.
The `%structure.model;`_ parameter entity is directly employed in the
content models of the document_ and section_ elements.
diff --git a/docutils/docs/ref/docutils.dtd b/docutils/docs/ref/docutils.dtd
index 6d0e947b3..3d3ae4956 100644
--- a/docutils/docs/ref/docutils.dtd
+++ b/docutils/docs/ref/docutils.dtd
@@ -144,7 +144,7 @@ resolve to either an internal or external reference.
" ( ( (%body.elements; | topic | sidebar)+,
(transition, (%body.elements; | topic | sidebar)+ )*,
( (%section.elements;), (transition?, (%section.elements;) )* )? )
- | ( (%section.elements;), (transition?, (%section.elements;) )* ) ) ">
+ | ( (%section.elements;), (transition?, (%section.elements;) )* ) )? ">
<!ENTITY % text.model
" (#PCDATA | %inline.elements;)* ">
diff --git a/docutils/docutils/parsers/rst/states.py b/docutils/docutils/parsers/rst/states.py
index 7de9165a8..b6954fe99 100644
--- a/docutils/docutils/parsers/rst/states.py
+++ b/docutils/docutils/parsers/rst/states.py
@@ -170,16 +170,8 @@ class RSTStateMachine(StateMachineWS):
results = StateMachineWS.run(self, input_lines, input_offset,
input_source=document['source'])
assert results == [], 'RSTStateMachine.run() results should be empty!'
- self.check_document()
self.node = self.memo = None # remove unneeded references
- def check_document(self):
- """Check for illegal structure: empty document."""
- if len(self.document) == 0:
- error = self.reporter.error(
- 'Document empty; must have contents.', line=0)
- self.document += error
-
class NestedStateMachine(StateMachineWS):
@@ -384,27 +376,11 @@ class RSTState(StateWS):
self.state_machine.input_lines[offset:], input_offset=absoffset,
node=section_node, match_titles=1)
self.goto_line(newabsoffset)
- self.check_section(section_node)
if memo.section_level <= mylevel: # can't handle next section?
raise EOFError # bubble up to supersection
# reset section_level; next pass will detect it properly
memo.section_level = mylevel
- def check_section(self, section):
- """
- Check for illegal structure: empty section, misplaced transitions.
- """
- lineno = section.line
- if len(section) <= 1:
- error = self.reporter.error(
- 'Section empty; must have contents.', line=lineno)
- section += error
- return
- if not isinstance(section[0], nodes.title): # shouldn't ever happen
- error = self.reporter.error(
- 'First element of section must be a title.', line=lineno)
- section.insert(0, error)
-
def paragraph(self, lines, lineno):
"""
Return a list (paragraph & messages) & a boolean: literal_block next?
diff --git a/docutils/test/test_parsers/test_rst/test_section_headers.py b/docutils/test/test_parsers/test_rst/test_section_headers.py
index e1119f32a..f95ee6f89 100755
--- a/docutils/test/test_parsers/test_rst/test_section_headers.py
+++ b/docutils/test/test_parsers/test_rst/test_section_headers.py
@@ -853,9 +853,6 @@ Empty Section
<section id="empty-section" name="empty section">
<title>
Empty Section
- <system_message level="3" line="2" source="test data" type="ERROR">
- <paragraph>
- Section empty; must have contents.
"""],
["""\
===
@@ -891,9 +888,6 @@ Without it, the parser ends up in an infinite loop.
""",
"""\
<document source="test data">
- <system_message level="3" line="0" source="test data" type="ERROR">
- <paragraph>
- Document empty; must have contents.
"""],
]