Add docstring inheritance decorator and drop duplicated docstrings.

R=qsr@chromium.org

Review URL: https://codereview.chromium.org/1259773004 .

Cr-Mirrored-From: https://github.com/domokit/mojo
Cr-Mirrored-Commit: 703c7a5ae9f42a61e8306c39dcb1ed3730dac590
diff --git a/devtoolslib/android_shell.py b/devtoolslib/android_shell.py
index 2d87f4e..a00ede9 100644
--- a/devtoolslib/android_shell.py
+++ b/devtoolslib/android_shell.py
@@ -18,6 +18,7 @@
 
 from devtoolslib.http_server import start_http_server
 from devtoolslib.shell import Shell
+from devtoolslib.utils import overrides
 
 
 # Tags used by mojo shell Java logging.
@@ -370,20 +371,8 @@
     logcat_watch_thread = threading.Thread(target=_ForwardObservatoriesAsNeeded)
     logcat_watch_thread.start()
 
+  @overrides(Shell)
   def ServeLocalDirectory(self, local_dir_path, port=0):
-    """Serves the content of the local (host) directory, making it available to
-    the shell under the url returned by the function.
-
-    The server will run on a separate thread until the program terminates. The
-    call returns immediately.
-
-    Args:
-      local_dir_path: path to the directory to be served
-      port: port at which the server will be available to the shell
-
-    Returns:
-      The url that the shell can use to access the content of |local_dir_path|.
-    """
     assert local_dir_path
     mappings = [('', local_dir_path)]
     server_address = start_http_server(mappings, host_port=port)
@@ -391,45 +380,20 @@
     return 'http://127.0.0.1:%d/' % self._ForwardDevicePortToHost(
         port, server_address[1])
 
+  @overrides(Shell)
   def ServeLocalDirectories(self, mappings, port=0):
-    """Serves the content of the local (host) directories, making it available
-    to the shell under the url returned by the function.
-
-    The server will run on a separate thread until the program terminates. The
-    call returns immediately.
-
-    Args:
-      mappings: List of tuples (prefix, local_base_path) mapping URLs that start
-          with |prefix| to local directory at |local_base_path|. The prefixes
-          should skip the leading slash. The first matching prefix will be used
-          each time.
-      port: port at which the server will be available to the shell
-
-    Returns:
-      The url that the shell can use to access the content of |local_dir_path|.
-    """
     assert mappings
     server_address = start_http_server(mappings, host_port=port)
 
     return 'http://127.0.0.1:%d/' % self._ForwardDevicePortToHost(
         port, server_address[1])
 
+  @overrides(Shell)
   def ForwardHostPortToShell(self, host_port):
-    """Forwards a port on the host machine to the same port wherever the shell
-    is running.
-
-    This is a no-op if the shell is running locally.
-    """
     self._ForwardHostPortToDevice(host_port, host_port)
 
+  @overrides(Shell)
   def Run(self, arguments):
-    """Runs the shell with given arguments until shell exits, passing the stdout
-    mingled with stderr produced by the shell onto the stdout.
-
-    Returns:
-      Exit code retured by the shell or None if the exit code cannot be
-      retrieved.
-    """
     self.CleanLogs()
     self.ForwardObservatoryPorts()
 
@@ -440,22 +404,8 @@
     p.wait()
     return None
 
+  @overrides(Shell)
   def RunAndGetOutput(self, arguments, timeout=None):
-    """Runs the shell with given arguments until shell exits and returns the
-    output.
-
-    Args:
-      arguments: list of arguments for the shell
-      timeout: maximum running time in seconds, after which the shell will be
-          terminated
-
-    Returns:
-      A tuple of (return_code, output, did_time_out). |return_code| is the exit
-      code returned by the shell or None if the exit code cannot be retrieved.
-      |output| is the stdout mingled with the stderr produced by the shell.
-      |did_time_out| is True iff the shell was terminated because it exceeded
-      the |timeout| and False otherwise.
-    """
     class Results:
       """Workaround for Python scoping rules that prevent assigning to variables
       from the outer scope.
diff --git a/devtoolslib/linux_shell.py b/devtoolslib/linux_shell.py
index fff21a7..d37c46f 100644
--- a/devtoolslib/linux_shell.py
+++ b/devtoolslib/linux_shell.py
@@ -5,8 +5,9 @@
 import subprocess
 import threading
 
-from devtoolslib.shell import Shell
 from devtoolslib import http_server
+from devtoolslib.shell import Shell
+from devtoolslib.utils import overrides
 
 
 class LinuxShell(Shell):
@@ -22,77 +23,26 @@
     self.executable_path = executable_path
     self.command_prefix = command_prefix if command_prefix else []
 
+  @overrides(Shell)
   def ServeLocalDirectory(self, local_dir_path, port=0):
-    """Serves the content of the local (host) directory, making it available to
-    the shell under the url returned by the function.
-
-    The server will run on a separate thread until the program terminates. The
-    call returns immediately.
-
-    Args:
-      local_dir_path: path to the directory to be served
-      port: port at which the server will be available to the shell
-
-    Returns:
-      The url that the shell can use to access the content of |local_dir_path|.
-    """
     mappings = [('', local_dir_path)]
     return 'http://%s:%d/' % http_server.start_http_server(mappings, port)
 
+  @overrides(Shell)
   def ServeLocalDirectories(self, mappings, port=0):
-    """Serves the content of the local (host) directories, making it available
-    to the shell under the url returned by the function.
-
-    The server will run on a separate thread until the program terminates. The
-    call returns immediately.
-
-    Args:
-      mappings: List of tuples (prefix, local_base_path) mapping URLs that start
-          with |prefix| to local directory at |local_base_path|. The prefixes
-          should skip the leading slash. The first matching prefix will be used
-          each time.
-      port: port at which the server will be available to the shell
-
-    Returns:
-      The url that the shell can use to access the content of |local_dir_path|.
-    """
     return 'http://%s:%d/' % http_server.start_http_server(mappings, port)
 
+  @overrides(Shell)
   def ForwardHostPortToShell(self, host_port):
-    """Forwards a port on the host machine to the same port wherever the shell
-    is running.
-
-    This is a no-op if the shell is running locally.
-    """
     pass
 
+  @overrides(Shell)
   def Run(self, arguments):
-    """Runs the shell with given arguments until shell exits, passing the stdout
-    mingled with stderr produced by the shell onto the stdout.
-
-    Returns:
-      Exit code retured by the shell or None if the exit code cannot be
-      retrieved.
-    """
     command = self.command_prefix + [self.executable_path] + arguments
     return subprocess.call(command, stderr=subprocess.STDOUT)
 
+  @overrides(Shell)
   def RunAndGetOutput(self, arguments, timeout=None):
-    """Runs the shell with given arguments until shell exits and returns the
-    output.
-
-    Args:
-      arguments: list of arguments for the shell
-      timeout: maximum running time in seconds, after which the shell will be
-          terminated
-
-    Returns:
-      A tuple of (return_code, output, did_time_out). |return_code| is the exit
-      code returned by the shell or None if the exit code cannot be retrieved.
-      |output| is the stdout mingled with the stderr produced by the shell.
-      |did_time_out| is True iff the shell was terminated because it exceeded
-      the |timeout| and False otherwise.
-    """
     command = self.command_prefix + [self.executable_path] + arguments
     p = subprocess.Popen(command, stdout=subprocess.PIPE,
                          stderr=subprocess.STDOUT)
diff --git a/devtoolslib/utils.py b/devtoolslib/utils.py
new file mode 100644
index 0000000..7bf2e1c
--- /dev/null
+++ b/devtoolslib/utils.py
@@ -0,0 +1,16 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Python utils."""
+
+
+def overrides(parent_class):
+  """Inherits the docstring from the method of the same name in the indicated
+  parent class.
+  """
+  def overriding(method):
+    assert(method.__name__ in dir(parent_class))
+    method.__doc__ = getattr(parent_class, method.__name__).__doc__
+    return method
+  return overriding