From ba84cdf7047cf4c7c093b7479ff052ea751507ec Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Sun, 29 Jun 2014 10:29:55 +0100
Subject: [PATCH] Documentation for fsl.utils modules

---
 fsl/utils/__init__.py  |   7 ++
 fsl/utils/runwindow.py | 147 +++++++++++++++++++++--------------------
 fsl/utils/webpage.py   |   8 +++
 3 files changed, 89 insertions(+), 73 deletions(-)

diff --git a/fsl/utils/__init__.py b/fsl/utils/__init__.py
index e69de29bb..058ddca06 100644
--- a/fsl/utils/__init__.py
+++ b/fsl/utils/__init__.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+#
+# __init__.py - Small utility modules for doing random things.
+#
+# Author: Paul McCarthy <pauldmccarthy@gmail.com>
+#
+"""A collection of small utility modules for doing random things."""
diff --git a/fsl/utils/runwindow.py b/fsl/utils/runwindow.py
index 2f4d8604c..f615ea98a 100644
--- a/fsl/utils/runwindow.py
+++ b/fsl/utils/runwindow.py
@@ -1,11 +1,14 @@
 #!/usr/bin/env python
 #
 # runwindow.py - Run a process, display its output in a wx window.
-#                The checkAndRun() and run() functions are the entry
-#                points for this module.
 #
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
+"""Run a process, display its output in a :class:`RunPanel`.
+
+This module has two entry points - the :func:`checkAndRun` function, and the
+:func:`run` function.
+"""
 
 import os
 import signal
@@ -22,18 +25,20 @@ log = logging.getLogger(__name__)
 
 
 class RunPanel(wx.Panel):
-    """
-    A panel which displays a multiline text control, and a couple of
-    buttons along the bottom.
+    """A panel which displays a multiline text control, and a couple of buttons
+    along the bottom.
     """
 
     def __init__(self, parent):
-        """
-        Creates and lays out a text control, and two buttons. One of
-        the buttons is intended to closes the window in which this
-        panel is contained. The second button is intended to terminate
-        the running process. Both buttons are unbound by default, so
-        must be manually bound to callback functions.
+        """Creates and lays out a text control, and two buttons.
+
+        One of the buttons is intended to closes the window in which this
+        panel is contained. The second button is intended to terminate the
+        running process. Both buttons are unbound by default, so must be
+        manually bound to callback functions.
+
+        :ivar closeButton: The `Close window` button.
+        :ivar killButton:  The `Terminate process` button.
         """
         wx.Panel.__init__(self, parent)
 
@@ -43,9 +48,9 @@ class RunPanel(wx.Panel):
         # Horizontal scrolling no work in OSX
         # mavericks. I think it's a wxwidgets bug.
         self.text  = wx.TextCtrl(self,
-                                 style=wx.TE_MULTILINE | \
-                                       wx.TE_READONLY  | \
-                                       wx.TE_DONTWRAP  | \
+                                 style=wx.TE_MULTILINE |
+                                       wx.TE_READONLY  |
+                                       wx.TE_DONTWRAP  |
                                        wx.HSCROLL)
 
         self.sizer.Add(self.text, flag=wx.EXPAND, proportion=1)
@@ -64,26 +69,24 @@ class RunPanel(wx.Panel):
 
 
 class ProcessManager(thread.Thread):
-    """
-    A thread which manages the execution of a child process, and
-    capture of its output.
+    """A thread which manages the execution of a child process, and capture of its
+    output.
     """
 
     def __init__(self, cmd, parent, runPanel, onFinish):
-        """
-        Create a ProcessManager thread object. Does nothing special.
-        Parameters:
-          - cmd:      String or list of strings, the command to be
-                      executed.
+        """Create a ProcessManager thread object. Does nothing special.
+        
+        :arg cmd:      String or list of strings, the command to be
+                       executed.
         
-          - parent:   GUI parent object.
+        :arg parent:   GUI parent object.
         
-          - runPanel: RunPanel object, for displaying the child process
-                      output.
+        :arg runPanel: :class:`RunPanel` object, for displaying the child 
+                       process output.
         
-          - onFinish: Callback function to be called when the process
-                      finishes. May be None. Must accept two parameters,
-                      the GUI parent object, and the process return code.
+        :arg onFinish: Callback function to be called when the process
+                       finishes. May be ``None``. Must accept two parameters,
+                       the GUI parent object, and the process return code.
         """
         thread.Thread.__init__(self, name=cmd[0])
         
@@ -108,10 +111,9 @@ class ProcessManager(thread.Thread):
 
 
     def writeToPanel(self):
-        """
-        Reads a string from the output queue, and appends it
-        to the runPanel. This method is intended to be
-        executed via wx.CallAfter.
+        """Reads a string from the output queue, and appends it
+        to the :class:`RunPanel`. This method is intended to be
+        executed via :func:`wx.CallAfter`.
         """
         
         try:                output = self.outq.get_nowait()
@@ -126,12 +128,11 @@ class ProcessManager(thread.Thread):
  
 
     def run(self):
-        """
-        Starts the process, then reads its output line by
-        line, writing each line asynchronously to the runPanel.
-        When the process ends, the onFinish method (if there is
-        one) is called. If the process finishes abnormally (with
-        a non-0 exit code) a warning dialog is displayed.
+        """Starts the process, then reads its output line by line, writing
+        each line asynchronously to the :class:`RunPanel`.  When the
+        process ends, the ``onFinish`` method (if there is one) is called. 
+        If the process finishes abnormally (with a non-0 exit code) a warning
+        dialog is displayed.
         """
 
         # Run the command. The preexec_fn parameter creates
@@ -146,7 +147,7 @@ class ProcessManager(thread.Thread):
 
         # read process output, line by line, pushing
         # each line onto the output queue and
-       # asynchronously writing it to the runPanel
+        # asynchronously writing it to the runPanel
         for line in self.proc.stdout:
             
             log.debug('Process output: {}'.format(line.strip()))
@@ -181,11 +182,9 @@ class ProcessManager(thread.Thread):
 
         
     def termProc(self):
-        """
-        Attempts to kill the running child process.
-        """
+        """Attempts to kill the running child process."""
         try:
-            log.debug('Attempting to send SIGTERM to '\
+            log.debug('Attempting to send SIGTERM to '
                       'process group with pid {}'.format(self.proc.pid))
             os.killpg(self.proc.pid, signal.SIGTERM)
 
@@ -194,27 +193,25 @@ class ProcessManager(thread.Thread):
             wx.CallAfter(self.writeToPanel)
             
         except:
-            pass # why am i ignoring errors here?
+            pass  # why am i ignoring errors here?
 
 
 def run(name, cmd, parent, onFinish=None, modal=True):
-    """
-    Runs the given command, displaying the output in a wx window.
-    Parameters:
+    """Runs the given command, displaying the output in a :class:`RunPanel`.
     
-      - name:     Name of the tool to be run, used in the window title.
+    :arg name:     Name of the tool to be run, used in the window title.
     
-      - cmd:      String or list of strings, specifying the command to be
-                  executed.
+    :arg cmd:      String or list of strings, specifying the command to be
+                   executed.
     
-      - parent:   wx parent object.
+    :arg parent:   :mod:`wx` parent object.
     
-      - modal:    If True, the command window will be modal.
+    :arg modal:    If ``True``, the command frame will be modal.
 
-      - onFinish: Function to be called when the process ends. Must
-                  accept two parameters - a reference to the wx
-                  frame/dialog displaying the process output, and
-                  the exit code of the application.
+    :arg onFinish: Function to be called when the process ends. Must
+                   accept two parameters - a reference to the :mod:`wx`
+                   frame/dialog displaying the process output, and
+                   the exit code of the application.
     """
 
     # Create the GUI - if modal, the easiest approach is to use a wx.Dialog
@@ -244,31 +241,36 @@ def run(name, cmd, parent, onFinish=None, modal=True):
     else:     frame.Show()
  
 
-def checkAndRun(name, opts, parent, cmdFunc,
+def checkAndRun(name,
+                opts,
+                parent,
+                cmdFunc,
                 optLabels={},
                 modal=True,
                 onFinish=None):
-    """
-    Validates the given options. If invalid, a dialog is shown, informing
-    the user about the errors. Otherwise, the tool is executed, and its
-    output shown in a dialog window. Parameters:
+    """Validates the given options. If invalid, a dialog is shown,
+    informing the user about the errors. Otherwise, the tool is
+    executed, and its output shown in a dialog window. Parameters:
     
-      - name:      Name of the tool, used in the window title
+    :arg name:      Name of the tool, used in the window title.
     
-      - opts:      HasProperties object to be validated
+    :arg opts:      A :class:`~props.properties.HasProperties` object to be
+                    validated.
     
-      - parent:    wx object to be used as parent
+    :arg parent:    :mod:`wx` object to be used as parent.
     
-      - cmdFunc:   Function which takes a HasProperties object, and
-                   returns a command to be executed (as a list of
-                   strings), which will be passed to the run() function.
+    :arg cmdFunc:   Function which takes a
+                    :class:`~props.properties.HasProperties` object, 
+                    and returns a command to be executed (as a list of
+                    strings), which will be passed to the :func:`run`
+                    function.
     
-      - optLabels: Dictionary containing property name -> label mappings.
-                   Used in the error dialog, if any options are invalid.
+    :arg optLabels: Dictionary containing property ``{name : label}`` mappings.
+                    Used in the error dialog, if any options are invalid.
     
-      - modal:     If true, the command window will be modal.
+    :arg modal:     If true, the command window will be modal.
 
-      - onFinish:  Function to be called when the process ends.
+    :arg onFinish:  Function to be called when the process ends.
     """
 
     errors = opts.validateAll()
@@ -278,7 +280,7 @@ def checkAndRun(name, opts, parent, cmdFunc,
         msg = 'There are numerous errors which need '\
               'to be fixed before {} can be run:\n'.format(name)
 
-        for opt,error in errors:
+        for opt, error in errors:
             
             if opt in optLabels: name = optLabels[opt]
             msg = msg + '\n - {}: {}'.format(opt, error)
@@ -291,4 +293,3 @@ def checkAndRun(name, opts, parent, cmdFunc,
     else:
         cmd = cmdFunc(opts)
         run(name, cmd, parent, onFinish, modal)
-
diff --git a/fsl/utils/webpage.py b/fsl/utils/webpage.py
index 53c621274..4b9ea369b 100644
--- a/fsl/utils/webpage.py
+++ b/fsl/utils/webpage.py
@@ -4,16 +4,24 @@
 #
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
+"""Convenience functions for opening a URL in a web browser."""
 
 import os
 import webbrowser
 
 import wx
 
+
 def openPage(url):
+    """Opens the given URL in the system-default web browser."""
     webbrowser.open(url)
 
+    
 def openFSLHelp(toolName):
+    """Attempts to open the FSL help documentation for the given FSL tool.
+    If the ``$FSLDIR`` environment variable is not set, pops up a warning
+    message instead.
+    """
 
     fsldir = os.environ.get('FSLDIR', None)
     url    = 'file://{}/doc/redirects/{}.html'.format(fsldir, toolName)
-- 
GitLab