Revision: 595ef62880a7
Branch:   default
Author:   Pekka Klärck
Date:     Fri Sep 27 07:31:44 2013 UTC
Log:      Support plain text (code blocks) in reST parser.

This is a patch by Asko Soukka <asko.sou...@iki.fi> and Vivek Kumar Verma <1990vivekkumarve...@gmail.com> implemented as part of GSOC 2013. Thanks guys!

Update issue 1495
Status: Started
Patch applied. I'll refactor it later to match our coding conventions a bit better. It's nevertheless certain that RF 2.8.2 will contain plain text reST support!
http://code.google.com/p/robotframework/source/detail?r=595ef62880a7

Added:
 /atest/robot/parsing/data_formats/rest_directives.txt
 /atest/testdata/parsing/data_formats/rest_directives/sample.rst
Modified:
 /doc/userguide/src/CreatingTestData/TestDataSyntax.rst
 /src/robot/parsing/restreader.py

=======================================
--- /dev/null
+++ /atest/robot/parsing/data_formats/rest_directives.txt Fri Sep 27 07:31:44 2013 UTC
@@ -0,0 +1,21 @@
+*** Settings ***
+Suite Setup     Run keywords
+...             Check is docutils installed
+Test Setup      Run keywords
+... Make test non-critical and fail it if docutils is not installed
+Force Tags      regression  jybot  pybot
+Resource        formats_resource.txt
+
+*** Test Cases ***
+
+One ReST using code-directive
+    [Setup]
+ ${status} ${msg} = Run Keyword And Ignore Error Run sample file and check tests parsing${/}data_formats${/}rest_directives${/}sample.rst + Run Keyword If "${DOCUTILS INSTALLED}" == "YES" and "${status}" == "FAIL" FAIL ${msg} + Run Keyword Unless "${DOCUTILS INSTALLED}" == "YES" Clear error should be given when docutils is not installed
+
+*** Keywords ***
+
+Clear Error Should Be Given When Docutils Is Not Installed
+    ${stderr} =  Get Stderr
+ Should Match RegExp ${stderr} \\[ ERROR \\] Parsing '.*[/\\\\]sample.rst' failed: Using reStructuredText test data requires having 'docutils' module installed.\n \n Try --help for usage information.\n
=======================================
--- /dev/null
+++ /atest/testdata/parsing/data_formats/rest_directives/sample.rst Fri Sep 27 07:31:44 2013 UTC
@@ -0,0 +1,104 @@
+ReST Test Data Example
+======================
+
+This text should be ignored, even though it's no a comment.
+We have a devious plan to rule the world with robots.
+
+.. code:: robotframework
+
+   *Setting*      *Value*
+
+   Document       A complex testdata file   in rst format.
+   Default Tags   default1
+   Force Tags     force1   force2
+
+   Suite Setup    Log   Setup
+   Test Teardown  Log   Test Teardown
+   Resource       ../resources/rest_resource.rst
+   Variables      ../resources/variables.py
+   Library       OperatingSystem
+
+.. code:: robotframework
+
+   * Variable
+
+   ${table_var}   foo
+   @{table_listvar}   bar   ${table_var}
+   ${quoted}   """this has """"many "" quotes """""
+   ${single_quoted}   s'ingle'qu'ot'es''
+
+.. code:: robotframework
+
+   ***Test Case***
+
+   Passing   Log   Passing test case.
+
+   Failing        [Document]   FAIL    Failing test case.
+      Fail                     Failing test case.
+   User Keyword   [Document]   FAIL    A cunning argument. != something
+      My Keyword With Arg      A cunning argument.
+
+   Own Tags   [Tags]   own1   own2
+      Log   tags test
+
+   Default Tags   No Operation
+
+   Variable Table   Equals   ${table_var}   foo
+      Equals   @{table_listvar}[0]   bar
+      Equals   @{table_listvar}[1]   foo
+
+   Resource File   Keyword from ReST resource
+      Keyword from ReST resource 2
+      Equals   ${rest_resource_var}   ReST Resource Variable
+ Equals ${rest_resource_var2} ReST Resource Variable From Recursive Resource
+
+   Variable File   Equals   @{file_listvar}[0]   ${True}
+      Equals   @{file_listvar}[1]   ${3.14}
+      Equals   @{file_listvar}[2]   Hello, world!!
+      Equals   ${file_var1}   ${-314}
+      Equals   ${file_var2}   file variable 2
+
+   Library Import   Fail If Dir Empty   ${CURDIR}
+
+   Test Timeout   [Timeout]   1second
+      [Document]   FAIL   Test timeout 1 second exceeded.
+      Sleep   2
+
+   Keyword Timeout   [Document]   FAIL   Keyword timeout 1 second exceeded.
+      Timeouted Keyword
+
+   Empty Rows
+ [Document] Testing that empty rows are ignored. FAIL Expected failure.
+
+      Noop
+
+      Fail   Expected failure.
+
+   Document   [Document]   Testing the metadata parsing.
+      noop
+
+   Default Fixture   Noop
+
+   Overridden Fixture   [Teardown]   Fail   Failing Teardown
+      [Setup]   Log   Own Setup
+      [Document]   FAIL   Teardown failed:\n Failing Teardown
+      NOOP
+
+   Quotes   Equals   ${quoted}   """this has """"many "" quotes """""
+      Equals   ${single_quoted}   s'ingle'qu'ot'es''
+
+.. code:: robotframework
+
+   *User Keywords*   *Action*   *Argument*   *Argument*   *Argument*
+
+   My Keyword With Arg   [Arguments]   ${arg1}
+      Keyword with no arguments
+      Another Keyword   ${arg1}
+
+   Another Keyword   [Arguments]   ${arg1}   ${arg2}=something
+      Equals   ${arg1}   ${arg2}
+
+   Timeouted Keyword   [Timeout]   1second
+      Sleep   2
+
+   Keyword With No Arguments   Log   Hello world!
=======================================
--- /doc/userguide/src/CreatingTestData/TestDataSyntax.rst Sun Jun 9 11:28:05 2013 UTC +++ /doc/userguide/src/CreatingTestData/TestDataSyntax.rst Fri Sep 27 07:31:44 2013 UTC
@@ -404,6 +404,51 @@
     \             Directory Should Exist  ${path}
     ============  ======================  ============  ==========

+.. note:: In reST files, also Space separated format is
+          supported starting from Robot Framework 2.8.2.
+
+Apart from writing the test cases in reStructuredText documents using table
+format, user can write the test cases in space separated format also. For
+writing test case in space separated format, ``.. code::
+robotframework``-directive should be used to indicate that test suite in space +separated text syntax is starting. The actual test suite would start from the
+next line with proper indentation.
+
+The actual test suite can be written in a manner similar to shown earlier (in +`space separated format`_). Also same escaping rule needs to be followed. For
+example::
+
+    .. code:: robotframework
+
+       *** Settings ***
+
+       Library  OperatingSystem
+
+       *** Variables ***
+
+       ${MESSAGE}  Hello, world!
+
+       *** Test Cases ***
+
+       My Test
+           [Documentation]  Example test
+           Log  ${MESSAGE}
+           My Keyword  /tmp
+
+       Another Test
+           Should Be Equal  ${MESSAGE}  Hello, world!
+
+       *** Keywords ***
+
+       My Keyword
+           [Arguments]  ${path}
+           Directory Should Exist  ${path}
+
+.. note:: If a single reST document contains multiple
+          ``.. code:: robotframework``-directives, their contents are
+          concatenated into a text file before parsing with space separated
+          format parser.
+
 Editing test data
 `````````````````

=======================================
--- /src/robot/parsing/restreader.py    Thu Jun  6 14:00:44 2013 UTC
+++ /src/robot/parsing/restreader.py    Fri Sep 27 07:31:44 2013 UTC
@@ -12,18 +12,18 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.

-import tempfile
 import os
-
+import tempfile
 from robot.errors import DataError
-
 from .htmlreader import HtmlReader
+from .txtreader import TxtReader


 def RestReader():
     try:
-        from docutils.core import publish_cmdline
-        from docutils.parsers.rst import directives
+        import docutils.core
+        from docutils.parsers.rst.directives import register_directive
+        from docutils.parsers.rst.directives import body
     except ImportError:
         raise DataError("Using reStructuredText test data requires having "
                         "'docutils' module installed.")
@@ -32,25 +32,75 @@
     # See e.g. ug2html.py for an example how custom directives are created.
     ignorer = lambda *args: []
     ignorer.content = 1
-    directives.register_directive('sourcecode', ignorer)
+    register_directive('sourcecode', ignorer)

-    class RestReader(HtmlReader):
+    # Override default CodeBlock with a derived custom directive, which can
+ # capture Robot Framework test suite snippets and then discard the content
+    # to speed up the parser.
+    class RobotAwareCodeBlock(body.CodeBlock):
+        def run(self):
+            if u'robotframework' in self.arguments:
+                document = self.state_machine.document
+                if RestReader.has_robotdata(document):
+                    robotdata = RestReader.get_robotdata(document) + u'\n'
+                    robotdata += u'\n'.join(self.content)
+                else:
+                    robotdata = u'\n'.join(self.content)
+                RestReader.set_robotdata(document, robotdata)
+ return [] # Parsed content is not required for testing purposes
+    register_directive('code', RobotAwareCodeBlock)

+    class RestReader:
         def read(self, rstfile, rawdata):
-            htmlpath = self._rest_to_html(rstfile.name)
-            htmlfile = None
+            doctree = docutils.core.publish_doctree(rstfile.read())
+            if RestReader.has_robotdata(doctree):
+                delegate = RestReader.txtreader_read
+            else:
+                delegate = RestReader.htmlreader_read
+            return delegate(doctree, rawdata)
+
+        @staticmethod
+        def has_robotdata(doctree):
+            return hasattr(doctree, '_robotdata')
+
+        @staticmethod
+        def set_robotdata(doctree, robotdata):
+            setattr(doctree, '_robotdata', robotdata)
+
+        @staticmethod
+        def get_robotdata(doctree, default=u''):
+            return getattr(doctree, '_robotdata', default)
+
+        @staticmethod
+        def txtreader_read(doctree, rawdata):
+            txtfile = tempfile.NamedTemporaryFile(suffix='.robot')
+ txtfile.write(RestReader.get_robotdata(doctree).encode('utf-8'))
+            txtfile.seek(0)
+            txtreader = TxtReader()
             try:
-                htmlfile = open(htmlpath, 'rb')
-                return HtmlReader.read(self, htmlfile, rawdata)
+                return txtreader.read(txtfile, rawdata)
             finally:
+                # Ensure that the temp file gets closed and deleted:
+                if txtfile:
+                    txtfile.close()
+                if os.path.isfile(txtfile.name):
+                    os.remove(txtfile.name)
+
+        @staticmethod
+        def htmlreader_read(doctree, rawdata):
+            htmlfile = tempfile.NamedTemporaryFile(suffix='.html')
+            htmlfile.write(docutils.core.publish_from_doctree(
+                doctree, writer_name='html',
+                settings_overrides={'output_encoding': 'utf-8'}))
+            htmlfile.seek(0)
+            htmlreader = HtmlReader()
+            try:
+                return htmlreader.read(htmlfile, rawdata)
+            finally:
+                # Ensure that the temp file gets closed and deleted:
                 if htmlfile:
                     htmlfile.close()
-                os.remove(htmlpath)
-
-        def _rest_to_html(self, rstpath):
-            filedesc, htmlpath = tempfile.mkstemp('.html')
-            os.close(filedesc)
-            publish_cmdline(writer_name='html', argv=[rstpath, htmlpath])
-            return htmlpath
+                if os.path.isfile(htmlfile.name):
+                    os.remove(htmlfile.name)

     return RestReader()

--

--- You received this message because you are subscribed to the Google Groups "robotframework-commit" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to robotframework-commit+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to