From edaad4c78245c36c4c2ecb44390704e9238ac073 2012-06-22 03:02:13
From: Fernando Perez <fernando.perez@berkeley.edu>
Date: 2012-06-22 03:02:13
Subject: [PATCH] Merge pull request #2002 from bfroehle/lsmagic_docs

Refactor %magic into using a new lsmagic_docs method.

Added a `lsmagic_docs` method which returns a dictionary of magic function docstrings.  It optionally takes parameters `brief` (list only first line of the docstring) and `missing` (to use in lieu of an empty docstring).
---

diff --git a/IPython/core/magic.py b/IPython/core/magic.py
index 36f2d15..154b63c 100644
--- a/IPython/core/magic.py
+++ b/IPython/core/magic.py
@@ -340,6 +340,30 @@ class MagicsManager(Configurable):
         """
         return self.magics
 
+    def lsmagic_docs(self, brief=False, missing=''):
+        """Return dict of documentation of magic functions.
+
+        The return dict has the keys 'line' and 'cell', corresponding to the
+        two types of magics we support. Each value is a dict keyed by magic
+        name whose value is the function docstring. If a docstring is
+        unavailable, the value of `missing` is used instead.
+
+        If brief is True, only the first line of each docstring will be returned.
+        """
+        docs = {}
+        for m_type in self.magics:
+            m_docs = {}
+            for m_name, m_func in self.magics[m_type].iteritems():
+                if m_func.__doc__:
+                    if brief:
+                        m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
+                    else:
+                        m_docs[m_name] = m_func.__doc__.rstrip()
+                else:
+                    m_docs[m_name] = missing
+            docs[m_type] = m_docs
+        return docs
+
     def register(self, *magic_objects):
         """Register one or more instances of Magics.
 
diff --git a/IPython/core/magics/basic.py b/IPython/core/magics/basic.py
index 61519eb..6748637 100644
--- a/IPython/core/magics/basic.py
+++ b/IPython/core/magics/basic.py
@@ -59,6 +59,24 @@ class BasicMagics(Magics):
         """List currently available magic functions."""
         print(self._lsmagic())
 
+    def _magic_docs(self, brief=False, rest=False):
+        """Return docstrings from magic functions."""
+        mman = self.shell.magics_manager
+        docs = mman.lsmagic_docs(brief, missing='No documentation')
+
+        if rest:
+            format_string = '**%s%s**::\n\n\t%s\n\n'
+        else:
+            format_string = '%s%s:\n\t%s\n'
+
+        return ''.join(
+            [format_string % (ESC_MAGIC, fname, fndoc)
+             for fname, fndoc in sorted(docs['line'].items())]
+            +
+            [format_string % (ESC_MAGIC*2, fname, fndoc)
+             for fname, fndoc in sorted(docs['cell'].items())]
+        )
+
     @line_magic
     def magic(self, parameter_s=''):
         """Print information about the magic function system.
@@ -74,45 +92,15 @@ class BasicMagics(Magics):
         except IndexError:
             pass
 
-        magic_docs = []
-        escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC*2)
-        magics = self.shell.magics_manager.magics
-
-        for mtype in ('line', 'cell'):
-            escape = escapes[mtype]
-            for fname, fn in sorted(magics[mtype].items()):
-
-                if mode == 'brief':
-                    # only first line
-                    if fn.__doc__:
-                        fndoc = fn.__doc__.split('\n',1)[0]
-                    else:
-                        fndoc = 'No documentation'
-                else:
-                    if fn.__doc__:
-                        fndoc = fn.__doc__.rstrip()
-                    else:
-                        fndoc = 'No documentation'
-
-                if mode == 'rest':
-                    rest_docs.append('**%s%s**::\n\n\t%s\n\n' %
-                                     (escape, fname, fndoc))
-                else:
-                    magic_docs.append('%s%s:\n\t%s\n' %
-                                      (escape, fname, fndoc))
-
-        magic_docs = ''.join(magic_docs)
-
-        if mode == 'rest':
-            return "".join(rest_docs)
+        brief = (mode == 'brief')
+        rest = (mode == 'rest')
+        magic_docs = self._magic_docs(brief, rest)
 
         if mode == 'latex':
             print(self.format_latex(magic_docs))
             return
         else:
             magic_docs = format_screen(magic_docs)
-        if mode == 'brief':
-            return magic_docs
 
         out = ["""
 IPython's 'magic' functions
@@ -304,7 +292,7 @@ Defaulting color scheme to 'NoColor'"""
     def quickref(self,arg):
         """ Show a quick reference sheet """
         from IPython.core.usage import quick_reference
-        qr = quick_reference + self.magic('-brief')
+        qr = quick_reference + self._magic_docs(brief=True)
         page.page(qr)
 
     @line_magic