Browse Source

qubes: Add parser for property docstring

From now, docstrings in properties cannot contain sphinx-specific features,
because there is no sphinx in dom0.
Wojtek Porczyk 9 years ago
parent
commit
091ffa5444
2 changed files with 46 additions and 20 deletions
  1. 29 6
      qubes/__init__.py
  2. 17 14
      qubes/vm/qubesvm.py

+ 29 - 6
qubes/__init__.py

@@ -26,6 +26,8 @@ import warnings
 
 import __builtin__
 
+import docutils.core
+import docutils.io
 import lxml.etree
 import xml.parsers.expat
 
@@ -501,7 +503,7 @@ class property(object):
     :param object default: default value; if callable, will be called with holder as first argument
     :param int load_stage: stage when property should be loaded (see :py:class:`Qubes` for description of stages)
     :param int order: order of evaluation (bigger order values are later)
-    :param str doc: docstring; you may use RST markup
+    :param str doc: docstring; this should be one paragraph of plain RST, no sphinx-specific features
 
     Setters and savers have following signatures:
 
@@ -630,6 +632,26 @@ class property(object):
         return self.__name__ == other.__name__
 
 
+    def format_doc(self):
+        '''Return parsed documentation string, stripping RST markup.
+        '''
+
+        if not self.__doc__: return ''
+
+        output, pub = docutils.core.publish_programmatically(
+            source_class=docutils.io.StringInput,
+            source=' '.join(self.__doc__.strip().split()),
+            source_path=None,
+            destination_class=docutils.io.NullOutput, destination=None,
+            destination_path=None,
+            reader=None, reader_name='standalone',
+            parser=None, parser_name='restructuredtext',
+            writer=None, writer_name='null',
+            settings=None, settings_spec=None, settings_overrides=None,
+            config_section=None, enable_exit_status=None)
+        return pub.writer.document.astext()
+
+
     #
     # exceptions
     #
@@ -1004,17 +1026,18 @@ class Qubes(PropertyHolder):
     '''
 
     default_netvm = VMProperty('default_netvm', load_stage=3, default=None,
-        doc='''Default NetVM for AppVMs. Initial state is :py:obj:`None`, which
-            means that AppVMs are not connected to the Internet.''')
+        doc='''Default NetVM for AppVMs. Initial state is `None`, which means
+            that AppVMs are not connected to the Internet.''')
     default_fw_netvm = VMProperty('default_fw_netvm', load_stage=3, default=None,
-        doc='''Default NetVM for ProxyVMs. Initial state is :py:obj:`None`, which
-            means that ProxyVMs (including FirewallVM) are not connected to the
+        doc='''Default NetVM for ProxyVMs. Initial state is `None`, which means
+            that ProxyVMs (including FirewallVM) are not connected to the
             Internet.''')
     default_template = VMProperty('default_template', load_stage=3,
         vmclass=qubes.vm.templatevm.TemplateVM,
         doc='Default template for new AppVMs')
     updatevm = VMProperty('updatevm', load_stage=3,
-        doc='Which VM to use as ``yum`` proxy for updating AdminVM and TemplateVMs')
+        doc='''Which VM to use as `yum` proxy for updating AdminVM and
+            TemplateVMs''')
     clockvm = VMProperty('clockvm', load_stage=3,
         doc='Which VM to use as NTP proxy for updating AdminVM')
     default_kernel = property('default_kernel', load_stage=3,

+ 17 - 14
qubes/vm/qubesvm.py

@@ -114,17 +114,17 @@ class QubesVM(qubes.vm.BaseVM):
     netvm = qubes.VMProperty('netvm', load_stage=4, allow_none=True,
         default=(lambda self: self.app.default_fw_netvm if self.provides_network
             else self.app.default_netvm),
-        doc='VM that provides network connection to this domain. '
-            'When :py:obj:`None`, machine is disconnected. '
-            'When absent, domain uses default NetVM.')
+        doc='''VM that provides network connection to this domain. When
+            `None`, machine is disconnected. When absent, domain uses default
+            NetVM.''')
 
     provides_network = qubes.property('provides_network', type=bool,
-        doc=':py:obj:`True` if it is NetVM or ProxyVM, false otherwise')
+        doc='`True` if it is NetVM or ProxyVM, false otherwise.')
 
     qid = qubes.property('qid', type=int,
         setter=_setter_qid,
-        doc='Internal, persistent identificator of particular domain. '
-            'Note this is different from Xen domid.')
+        doc='''Internal, persistent identificator of particular domain. Note
+            this is different from Xen domid.''')
 
     name = qubes.property('name', type=str,
         doc='User-specified name of the domain.')
@@ -146,19 +146,20 @@ class QubesVM(qubes.vm.BaseVM):
 
     installed_by_rpm = qubes.property('installed_by_rpm', type=bool, default=False,
         setter=qubes.property.bool,
-        doc="If this domain's image was installed from package tracked by "
-            "package manager.")
+        doc='''If this domain's image was installed from package tracked by
+            package manager.''')
 
     memory = qubes.property('memory', type=int, default=qubes.config.defaults['memory'],
         doc='Memory currently available for this VM.')
 
     maxmem = qubes.property('maxmem', type=int, default=None,
-        doc='Maximum amount of memory available for this VM '
-            '(for the purpose of memory balancer).')
+        doc='''Maximum amount of memory available for this VM (for the purpose
+            of the memory balancer).''')
 
     internal = qubes.property('internal', type=bool, default=False,
         setter=qubes.property.bool,
-        doc="Internal VM (not shown in qubes-manager, doesn't create appmenus entries.")
+        doc='''Internal VM (not shown in qubes-manager, don't create appmenus
+            entries.''')
 
     # XXX what is that
     vcpus = qubes.property('vcpus', default=None,
@@ -201,12 +202,14 @@ class QubesVM(qubes.vm.BaseVM):
 #           return self._default_user
 
     qrexec_timeout = qubes.property('qrexec_timeout', type=int, default=60,
-        doc='Time in seconds after which qrexec connection attempt is deemed failed. '
-            'Operating system inside VM should be able to boot in this time.')
+        doc='''Time in seconds after which qrexec connection attempt is deemed
+            failed. Operating system inside VM should be able to boot in this
+            time.''')
 
     autostart = qubes.property('autostart', type=bool, default=False,
         setter=qubes.property.bool,
-        doc='Setting this to :py:obj:`True` means that VM should be autostarted on dom0 boot.')
+        doc='''Setting this to `True` means that VM should be autostarted on dom0
+            boot.''')
 
     # XXX I don't understand backups
     include_in_backups = qubes.property('include_in_backups', type=bool, default=True,