]> scripts.mit.edu Git - wizard.git/commitdiff
Fill out missing documentation.
authorEdward Z. Yang <ezyang@mit.edu>
Mon, 11 Jan 2010 01:33:05 +0000 (20:33 -0500)
committerEdward Z. Yang <ezyang@mit.edu>
Mon, 11 Jan 2010 01:34:32 +0000 (20:34 -0500)
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
15 files changed:
doc/conf.py
doc/index.rst
doc/module/wizard.git.rst [new file with mode: 0644]
doc/module/wizard.prompt.rst [new file with mode: 0644]
doc/module/wizard.resolve.rst [new file with mode: 0644]
doc/module/wizard.scripts.rst [new file with mode: 0644]
doc/module/wizard.sql.rst [new file with mode: 0644]
doc/module/wizard.tests.rst [new file with mode: 0644]
wizard/app/mediawiki.py
wizard/app/wordpress.py
wizard/git.py
wizard/prompt.py
wizard/resolve.py
wizard/scripts.py
wizard/tests/__init__.py

index c91cb177bc30ac2e2f65f481746a6bd47c8788b1..8379d76a61c5a9ddc34b04f41346a7220da07b84 100644 (file)
@@ -97,7 +97,7 @@ pygments_style = 'sphinx'
 #modindex_common_prefix = []
 
 # Classes to ignore for coverage reporting
-coverage_ignore_classes = ['ProductionCopy', 'WorkingCopy']
+coverage_ignore_classes = ['ProductionCopy', 'WorkingCopy', 'Dialog', 'Prompt', 'FailPrompt']
 
 
 # -- Options for HTML output ---------------------------------------------------
index a2da3b5ad0105512788ac3accdf74ec2863d6b9d..912228ddb237845b3bcf93d3ea81b0d5f06736d8 100644 (file)
@@ -72,11 +72,17 @@ Modules
     module/wizard.app.php
     module/wizard.cache
     module/wizard.deploy
+    module/wizard.git
     module/wizard.install
     module/wizard.merge
+    module/wizard.prompt
+    module/wizard.resolve
+    module/wizard.scripts
     module/wizard.shell
-    module/wizard.util
+    module/wizard.sql
     module/wizard.sset
+    module/wizard.tests
+    module/wizard.util
 
 Indices and tables
 ------------------
diff --git a/doc/module/wizard.git.rst b/doc/module/wizard.git.rst
new file mode 100644 (file)
index 0000000..7688cc4
--- /dev/null
@@ -0,0 +1,9 @@
+:mod:`wizard.git`
+=================
+
+.. automodule:: wizard.git
+
+Functions
+---------
+.. autofunction:: describe
+.. autofunction:: commit_configure
diff --git a/doc/module/wizard.prompt.rst b/doc/module/wizard.prompt.rst
new file mode 100644 (file)
index 0000000..02b555f
--- /dev/null
@@ -0,0 +1,42 @@
+:mod:`wizard.prompt`
+====================
+
+.. automodule:: wizard.prompt
+
+Functions
+---------
+.. autofunction:: make
+
+Interfaces
+----------
+.. autoclass:: PromptInterface
+    :members:
+
+Classes
+-------
+.. autoclass:: Dialog
+    :show-inheritance:
+.. autoclass:: Prompt
+    :show-inheritance:
+.. autoclass:: FailPrompt
+    :show-inheritance:
+
+Utility functions
+-----------------
+.. autofunction:: fill
+.. autofunction:: guess_dimensions
+.. autofunction:: join_or
+.. autofunction:: dialog_wrap
+.. autofunction:: prompt_wrap
+
+Exceptions
+----------
+.. autoexception:: Error
+.. autoexception:: MissingRequiredParam
+    :show-inheritance:
+.. autoexception:: UserCancel
+    :show-inheritance:
+.. autoexception:: DialogError
+    :show-inheritance:
+.. autoexception:: UnsupportedTerminal
+    :show-inheritance:
diff --git a/doc/module/wizard.resolve.rst b/doc/module/wizard.resolve.rst
new file mode 100644 (file)
index 0000000..f61cd85
--- /dev/null
@@ -0,0 +1,14 @@
+:mod:`wizard.resolve`
+=====================
+
+.. automodule:: wizard.resolve
+
+Functions
+---------
+.. autofunction:: resolve
+.. autofunction:: is_conflict
+
+Utility functions
+-----------------
+.. autofunction:: spec_to_regex
+.. autofunction:: result_to_repl
diff --git a/doc/module/wizard.scripts.rst b/doc/module/wizard.scripts.rst
new file mode 100644 (file)
index 0000000..2433e99
--- /dev/null
@@ -0,0 +1,15 @@
+:mod:`wizard.scripts`
+=====================
+
+.. automodule:: wizard.scripts
+
+Functions
+---------
+.. autofunction:: fill_url
+.. autofunction:: get_quota_usage_and_limit
+.. autofunction:: get_disk_usage
+
+Exceptions
+----------
+.. autoexception:: QuotaParseError
+
diff --git a/doc/module/wizard.sql.rst b/doc/module/wizard.sql.rst
new file mode 100644 (file)
index 0000000..75191f5
--- /dev/null
@@ -0,0 +1,10 @@
+:mod:`wizard.sql`
+=================
+
+.. automodule:: wizard.sql
+
+Functions
+---------
+.. autofunction:: connect
+.. autofunction:: fill_url
+
diff --git a/doc/module/wizard.tests.rst b/doc/module/wizard.tests.rst
new file mode 100644 (file)
index 0000000..3f752ae
--- /dev/null
@@ -0,0 +1,9 @@
+:mod:`wizard.tests`
+===================
+
+.. automodule:: wizard.tests
+
+Functions
+---------
+.. autofunction:: getTestFile
+
index 01c931a2dbe9ca1e4720d3401e600ddc48c7d650..8c874e0f2d7734ab8534d2671e640aecb6f87938 100644 (file)
@@ -40,8 +40,6 @@ class Application(app.Application):
         return self.detectVersionFromFile("includes/DefaultSettings.php", php.re_var("wgVersion"))
     def checkWeb(self, deployment):
         return self.checkWebPage(deployment, "/index.php?title=Main_Page", "<!-- Served")
-    def prepareMerge(self, deployment):
-        resolve.fix_newlines("LocalSettings.php")
     def install(self, version, options):
         util.soft_unlink("LocalSettings.php")
         os.chmod("config", 0777) # XXX: vaguely sketchy
index 62a41389b30d037b075bed11c29a603b45990097..9c99f4477762271bfb2590ffb347b56fe9be509e 100644 (file)
@@ -44,11 +44,6 @@ class Application(app.Application):
         return self.checkWebPage(deployment, "", "<html")
     def detectVersion(self, deployment):
         return self.detectVersionFromFile("wp-includes/version.php", php.re_var("wp_version"))
-    def prepareMerge(self, deployment):
-        # This file shouldn't really be edited by users, but be careful: it's
-        # stored as DOS and not as UNIX, so you'll get conflicts if you add this line:
-        # resolve.fix_newlines("wp-config.php")
-        pass
     def install(self, version, options):
         util.soft_unlink("wp-config.php")
 
index 634076612964c2088a4db77d18a1aa85b7911606..d0c50c4cb661fa056abf64141fea6c0ffd9b403f 100644 (file)
@@ -9,6 +9,10 @@ def describe():
     return shell.safeCall("git", "describe", "--tags", strip=True)
 
 def commit_configure():
+    """
+    Performs a commit of changes performed during configuration of an install
+    with an appropriate logfile message.
+    """
     message = "Autoinstall configuration of %s locker.\n\n%s" % (util.get_dir_owner(), util.get_git_footer())
     util.set_git_env()
     try:
index 55027e016c098637209ef50b119cb76347d9c0ac..80938398b8fe1d8b63a67f242bbcedf2ba2ac6b4 100644 (file)
@@ -1,10 +1,14 @@
 """
-Interface compatible with :class:`dialog.Dialog` for doing
+Interface compatible with :class:`PromptInterface` for doing
 non-ncurses interaction.
 
 By convention, the last line of a text parameter should be
 a short value with a trailing colon so that we can prompt a user
 for a value immediately after it.
+
+.. testsetup:: *
+
+    from wizard.prompt import *
 """
 
 import sys
@@ -23,9 +27,17 @@ except ImportError:
     has_dialog = False
 
 def fill(text, width=60, **kwargs):
+    """
+    Convenience wrapper for :func:`textwrap.fill` that preserves
+    paragraphs.
+    """
     return "\n\n".join(textwrap.fill(p, width=width, **kwargs) for p in text.split("\n\n"))
 
 def guess_dimensions(text, width=60):
+    """
+    Guesses the dimensions that any given piece of text will
+    need to display on terminal, given some width.
+    """
     # +1 for the fact that there's no trailing newline from fill
     # +2 for the borders
     # +1 as a buffer in case we underestimate
@@ -33,6 +45,10 @@ def guess_dimensions(text, width=60):
     return width, fill(text, width-2).count("\n") + 1 + 2 + 1
 
 def make(prompt, non_interactive):
+    """
+    Makes a :class:`dialog.Dialog` compatible class based on
+    configuration.
+    """
     if non_interactive:
         return FailPrompt()
     if prompt or os.getenv('TERM') == 'dumb' or not has_dialog:
@@ -43,14 +59,65 @@ def make(prompt, non_interactive):
         return Prompt()
 
 def join_or(items):
+    """
+    Joins a list of disjunctions into a human readable sentence.
+
+    >>> join_or(['foo'])
+    'foo'
+    >>> join_or(['foo', 'bar', 'baz'])
+    'foo, bar or baz'
+    """
     if len(items) == 0:
         raise ValueError
     elif len(items) == 1:
         return items[0]
     return ', '.join(items[:-1]) + ' or ' + items[-1]
 
+class PromptInterface(object):
+    def inputbox(self, text, init='', **kwargs):
+        """
+        Request a free-form, single line of text from the user.
+        Prompt the user using ``text``; and ``init`` is the
+        initial value filling the field; not all implementations
+        support editing ``init``.  Returns the typed string.
+        """
+        raise NotImplementedError
+    def menu(self, text, choices=[], **kwargs):
+        """
+        Request a selection from a number of choices from the user.
+        Prompt the user using ``text``; ``choices`` is a list
+        of tuples of form ``(value to return, description)``, where
+        ``value to return`` is the value that this function will
+        return.
+        """
+        raise NotImplementedError
+    def passwordbox(self, text, **kwargs):
+        """
+        Securely requests a password from the user.  Prompts the user
+        using ``text``; return value is the password.
+        """
+        raise NotImplementedError
+    def msgbox(self, text, **kwargs):
+        """
+        Gives the user a message that they must dismiss before proceeding.
+        """
+        raise NotImplementedError
+    def infobox(self, text, **kwargs):
+        """
+        Gives the user a non-blocking message; useful if you are about
+        to do an operation that will take some time.
+        """
+        raise NotImplementedError
+
 @decorator.decorator
 def dialog_wrap(f, self, text, *args, **kwargs):
+    """
+    Convenience decorator that automatically:
+
+        1. Removes already handled keyword arguments,
+        2. Configures the dimensions of the dialog box, and
+        3. Handles the different ext possibilities of dialog.
+    """
     if 'cmdopt' in kwargs: del kwargs['cmdopt']
     if 'width' not in kwargs and 'height' not in kwargs:
         kwargs["width"], kwargs["height"] = guess_dimensions(text)
@@ -63,13 +130,13 @@ def dialog_wrap(f, self, text, *args, **kwargs):
     else:
         exit, value = result
     if exit == self.dialog.DIALOG_CANCEL or exit == self.dialog.DIALOG_ESC:
-        raise UserCancel
+        raise UserCancl
     elif exit != self.dialog.DIALOG_OK:
         # XXX: We don't support stuff like DIALOG_EXTRA or DIALOG_HELP
         raise DialogError(exit)
     return value
 
-class Dialog(object):
+class Dialog(PromptInterface):
     """Ncurses interface using dialog."""
     interactive = True
     def __init__(self):
@@ -112,12 +179,14 @@ class Dialog(object):
 
 @decorator.decorator
 def prompt_wrap(f, self, *args, **kwargs):
+    """Convenience decorator that handles end-of-document and interrupts."""
     try:
         return f(self, *args, **kwargs)
     except (EOFError, KeyboardInterrupt):
         raise UserCancel
 
-class Prompt(object):
+class Prompt(PromptInterface):
+    """Simple stdin/stdout prompt object."""
     interactive = True
     @prompt_wrap
     def inputbox(self, text, init='', **kwargs):
@@ -150,7 +219,7 @@ class Prompt(object):
         print ""
         print fill(text.strip())
 
-class FailPrompt(object):
+class FailPrompt(PromptInterface):
     """
     Prompt that doesn't actually ask the user; just fails with
     an error message.
@@ -173,11 +242,13 @@ class FailPrompt(object):
         print fill(text.strip(), break_long_words=False)
 
 class Error(wizard.Error):
+    """Base error class."""
     pass
 
 class MissingRequiredParam(Error):
     """Non-interactive, but we needed more info."""
     def __init__(self, cmdopt):
+        """``cmdopt`` is the command line option that should be specified."""
         self.cmdopt = cmdopt
     def __str__(self):
         return """
@@ -192,6 +263,7 @@ class UserCancel(Error):
 class DialogError(Error):
     """Dialog returned a mysterious error."""
     def __init__(self, exit):
+        """``exit`` is the mysterious exit code."""
         self.exitcode = exit
     def __str__(self):
         return """
index fd9d12d59be75b3d6f56ecd5c184364f5732fc01..4460cc6d8ce57ccb9efa44035b33677b6f6c876e 100644 (file)
@@ -12,10 +12,10 @@ for resolving conflicts in configuration files.
 The conflict resolution DSL is described here:
 
 Resolutions are specified as input-output pairs.  An input
-is a string with the conflict resolution markers ("<" * 7,
-"=" * 7 and ">" * 7), with the HEAD content above the equals
+is a string with the conflict resolution markers ``("<" * 7,
+"=" * 7 and ">" * 7)``, with the HEAD content above the equals
 divider, and the upstream content below the equals divider.
-Lines can also be marked as "***N***" where N is a natural
+Lines can also be marked as ``***N***`` where N is a natural
 number greater than 0 (i.e. 1 or more), which means that
 an arbitrary number of lines may be matched and available for output.
 
@@ -97,6 +97,10 @@ def spec_to_regex(spec):
     return ("<<<<<<<[^\n]*\\\n" + ours_regex + "\|\|\|\|\|\|\|\\\n" + common_regex + "=======\\\n" + theirs_regex + ">>>>>>>[^\n]*(\\\n|$)", ours_mappings)
 
 def result_to_repl(result, mappings):
+    """
+    Converts a list of replacement strings and or references
+    into a replacement string appropriate for a regular expression.
+    """
     def ritem_to_string(r):
         if type(r) is int:
             return "\\%d" % mappings[r]
@@ -105,6 +109,10 @@ def result_to_repl(result, mappings):
     return "".join(map(ritem_to_string, result))
 
 def resolve(contents, spec, result):
+    """
+    Given a conflicted file, whose contents are ``contents``, attempt
+    to resolve all conflicts that match ``spec`` with ``result``.
+    """
     rstring, mappings = spec_to_regex(spec)
     regex = re.compile(rstring, re.DOTALL)
     repl = result_to_repl(result, mappings)
@@ -131,23 +139,9 @@ def resolve(contents, spec, result):
     return ret
 
 def is_conflict(contents):
+    """
+    Given ``contents``, return ``True`` if there are any conflicts in it.
+    """
     # Really really simple heuristic
     return "<<<<<<<" in contents
 
-def fix_newlines(file, log=True):
-    """
-    Normalizes newlines in a file into UNIX file endings.  If
-    ``log`` is ``True`` an info log mesage is printed if
-    any normalization occurs.  Return value is ``True`` if
-    normalization occurred.
-    """
-    old_contents = open(file, "r").read()
-    contents = old_contents
-    while "\r\n" in contents:
-        contents = contents.replace("\r\n", "\n")
-    contents = contents.replace("\r", "\n")
-    if contents != old_contents:
-        logging.info("Converted %s to UNIX file endings" % file)
-        open(file, "w").write(contents)
-        return True
-    return False
index 9deb4f1512820e88d7c88da6eb68b92c61141f7e..40ba4545a6e6b5b297ab14e5cadf098925e17a14 100644 (file)
@@ -1,3 +1,7 @@
+"""
+This is ostensibly the place where Scripts specific code should live.
+"""
+
 import os
 import shlex
 import errno
@@ -10,6 +14,10 @@ import wizard
 from wizard import shell, util
 
 def fill_url(dir, url=None):
+    """
+    Attempts to determine the URL a directory would be web-accessible at.
+    If ``url`` is specified, automatically use it.
+    """
     if url:
         return url
 
@@ -116,7 +124,9 @@ def get_disk_usage(dir=None, excluded_dir=".git"):
                     else:
                         raise
     return sum_sizes
+
 class QuotaParseError(wizard.Error):
+    """Could not parse quota information."""
     def __init__(self, msg):
         self.msg = msg
     def __str__(self):
index 223b32c4de6380847c85f8363fc7be19e8ca5af4..98509f4989277ff35acca7349a1f1e05abff720e 100644 (file)
@@ -1,5 +1,8 @@
 import os.path
 
 def getTestFile(file):
+    """
+    Returns the path to a testfile in this test directory.
+    """
     return os.path.join(os.path.dirname(os.path.abspath(__file__)), file)