Hello community,

here is the log from the commit of package python-Fabric for openSUSE:Factory 
checked in at 2016-03-02 14:21:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Fabric (Old)
 and      /work/SRC/openSUSE:Factory/.python-Fabric.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Fabric"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Fabric/python-Fabric.changes      
2015-05-07 09:22:36.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-Fabric.new/python-Fabric.changes 
2016-03-02 14:21:30.000000000 +0100
@@ -1,0 +2,18 @@
+Thu Feb 18 15:32:02 UTC 2016 - [email protected]
+
+- update to version 1.10.2:
+ * Fix issue with ssh/config not having a cross-platform default path.
+ * Recursively unwrap decorators instead of only unwrapping a single 
+   decorator level, when obtaining task docstrings.
+ * Fix “NameError: free variable referenced before assignment in 
+   enclosing scope”.
+ * Redirect output of cd to /dev/null so users enabling bash’s 
+   CDPATH (or similar features in other shells) don’t have polluted 
+   output captures.
+ * Fix a couple minor issues with the operation of & demo code for 
+   the JobQueue class. 
+ * Update functionality added in #1213 so abort error messages don’t 
+   get printed twice (once by us, once by sys.exit) but the annotated 
+   exception error message is retained. 
+
+-------------------------------------------------------------------

Old:
----
  Fabric-1.10.1.tar.gz

New:
----
  Fabric-1.10.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-Fabric.spec ++++++
--- /var/tmp/diff_new_pack.oHf39d/_old  2016-03-02 14:21:31.000000000 +0100
+++ /var/tmp/diff_new_pack.oHf39d/_new  2016-03-02 14:21:31.000000000 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-Fabric
 #
-# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,31 +16,31 @@
 #
 
 
+%if 0%{?suse_version} && 0%{?suse_version} <= 1110
+%{!?python_sitelib: %global python_sitelib %(python -c "from 
distutils.sysconfig import get_python_lib; print get_python_lib()")}
+%else
+BuildArch:      noarch
+%endif
 Name:           python-Fabric
-Version:        1.10.1
+Version:        1.10.2
 Release:        0
 Summary:        Fabric is a simple, Pythonic tool for remote execution and 
deployment
 License:        BSD-2-Clause
 Group:          Development/Languages/Python
 Url:            http://fabfile.org
 Source:         
https://pypi.python.org/packages/source/F/Fabric/Fabric-%{version}.tar.gz
-BuildRequires:  python-devel
-BuildRequires:  python-setuptools
 # Test requirements:
 #TODO: Disabled due to errors / fudge requirement
 #BuildRequires:  python-fudge
 #BuildRequires:  python-nose
 # Documentation requirements:
 BuildRequires:  python-Sphinx
+BuildRequires:  python-devel
 BuildRequires:  python-paramiko >= 1.10
+BuildRequires:  python-setuptools
 Requires:       python-paramiko >= 1.10
 Requires:       python-setuptools
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-%if 0%{?suse_version} && 0%{?suse_version} <= 1110
-%{!?python_sitelib: %global python_sitelib %(python -c "from 
distutils.sysconfig import get_python_lib; print get_python_lib()")}
-%else
-BuildArch:      noarch
-%endif
 
 %description
 Fabric is a Python (2.5 or higher) library and command-line tool for

++++++ Fabric-1.10.1.tar.gz -> Fabric-1.10.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/Fabric.egg-info/PKG-INFO 
new/Fabric-1.10.2/Fabric.egg-info/PKG-INFO
--- old/Fabric-1.10.1/Fabric.egg-info/PKG-INFO  2014-12-20 00:19:18.000000000 
+0100
+++ new/Fabric-1.10.2/Fabric.egg-info/PKG-INFO  2015-06-19 20:18:45.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: Fabric
-Version: 1.10.1
+Version: 1.10.2
 Summary: Fabric is a simple, Pythonic tool for remote execution and deployment.
 Home-page: http://fabfile.org
 Author: Jeff Forcier
@@ -24,27 +24,29 @@
         commands (normally or via ``sudo``) and uploading/downloading files, 
as well as
         auxiliary functionality such as prompting the running user for input, 
or
         aborting execution.
-        
+         
         Typical use involves creating a Python module containing one or more 
functions,
         then executing them via the ``fab`` command-line tool. Below is a 
small but
-        complete "fabfile" containing a single task::
+        complete "fabfile" containing a single task:
+        
+        .. code-block:: python
         
-        from fabric.api import run
+            from fabric.api import run
         
-        def host_type():
-        run('uname -s')
+            def host_type():
+                run('uname -s')
         
         Once a task is defined, it may be run on one or more servers, like so::
         
-        $ fab -H localhost,linuxbox host_type
-        [localhost] run: uname -s
-        [localhost] out: Darwin
-        [linuxbox] run: uname -s
-        [linuxbox] out: Linux
-        
-        Done.
-        Disconnecting from localhost... done.
-        Disconnecting from linuxbox... done.
+            $ fab -H localhost,linuxbox host_type
+            [localhost] run: uname -s
+            [localhost] out: Darwin
+            [linuxbox] run: uname -s
+            [linuxbox] out: Linux
+        
+            Done.
+            Disconnecting from localhost... done.
+            Disconnecting from linuxbox... done.
         
         In addition to use via the ``fab`` tool, Fabric's components may be 
imported
         into other Python code, providing a Pythonic interface to the SSH 
protocol
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/Fabric.egg-info/SOURCES.txt 
new/Fabric-1.10.2/Fabric.egg-info/SOURCES.txt
--- old/Fabric-1.10.1/Fabric.egg-info/SOURCES.txt       2014-12-20 
00:19:18.000000000 +0100
+++ new/Fabric-1.10.2/Fabric.egg-info/SOURCES.txt       2015-06-19 
20:18:45.000000000 +0200
@@ -12,8 +12,6 @@
 Fabric.egg-info/requires.txt
 Fabric.egg-info/top_level.txt
 fabfile/__init__.py
-fabfile/tag.py
-fabfile/utils.py
 fabric/__init__.py
 fabric/__main__.py
 fabric/api.py
@@ -44,6 +42,7 @@
 sites/_shared_static/logo.png
 sites/docs/conf.py
 sites/docs/index.rst
+sites/docs/running_tests.rst
 sites/docs/tutorial.rst
 sites/docs/api/contrib/console.rst
 sites/docs/api/contrib/django.rst
@@ -67,6 +66,7 @@
 sites/docs/usage/parallel.rst
 sites/docs/usage/ssh.rst
 sites/docs/usage/tasks.rst
+sites/www/.changelog.rst.swp
 sites/www/changelog.rst
 sites/www/conf.py
 sites/www/contact.rst
@@ -99,6 +99,7 @@
 tests/test_version.py
 tests/utils.py
 tests/support/__init__.py
+tests/support/aborts.py
 tests/support/classbased_task_fabfile.py
 tests/support/decorated_fabfile.py
 tests/support/decorated_fabfile_with_classbased_task.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/Fabric.egg-info/requires.txt 
new/Fabric-1.10.2/Fabric.egg-info/requires.txt
--- old/Fabric-1.10.1/Fabric.egg-info/requires.txt      2014-12-20 
00:19:18.000000000 +0100
+++ new/Fabric-1.10.2/Fabric.egg-info/requires.txt      2015-06-19 
20:18:45.000000000 +0200
@@ -1 +1 @@
-paramiko>=1.10,<1.13
\ No newline at end of file
+paramiko>=1.10
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/LICENSE new/Fabric-1.10.2/LICENSE
--- old/Fabric-1.10.1/LICENSE   2014-09-19 05:11:49.000000000 +0200
+++ new/Fabric-1.10.2/LICENSE   2015-04-30 04:32:40.000000000 +0200
@@ -1,4 +1,4 @@
-Copyright (c) 2009-2014 Jeffrey E. Forcier
+Copyright (c) 2009-2015 Jeffrey E. Forcier
 Copyright (c) 2008-2009 Christian Vest Hansen
 All rights reserved.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/PKG-INFO new/Fabric-1.10.2/PKG-INFO
--- old/Fabric-1.10.1/PKG-INFO  2014-12-20 00:19:18.000000000 +0100
+++ new/Fabric-1.10.2/PKG-INFO  2015-06-19 20:18:45.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: Fabric
-Version: 1.10.1
+Version: 1.10.2
 Summary: Fabric is a simple, Pythonic tool for remote execution and deployment.
 Home-page: http://fabfile.org
 Author: Jeff Forcier
@@ -24,27 +24,29 @@
         commands (normally or via ``sudo``) and uploading/downloading files, 
as well as
         auxiliary functionality such as prompting the running user for input, 
or
         aborting execution.
-        
+         
         Typical use involves creating a Python module containing one or more 
functions,
         then executing them via the ``fab`` command-line tool. Below is a 
small but
-        complete "fabfile" containing a single task::
+        complete "fabfile" containing a single task:
+        
+        .. code-block:: python
         
-        from fabric.api import run
+            from fabric.api import run
         
-        def host_type():
-        run('uname -s')
+            def host_type():
+                run('uname -s')
         
         Once a task is defined, it may be run on one or more servers, like so::
         
-        $ fab -H localhost,linuxbox host_type
-        [localhost] run: uname -s
-        [localhost] out: Darwin
-        [linuxbox] run: uname -s
-        [linuxbox] out: Linux
-        
-        Done.
-        Disconnecting from localhost... done.
-        Disconnecting from linuxbox... done.
+            $ fab -H localhost,linuxbox host_type
+            [localhost] run: uname -s
+            [localhost] out: Darwin
+            [linuxbox] run: uname -s
+            [linuxbox] out: Linux
+        
+            Done.
+            Disconnecting from localhost... done.
+            Disconnecting from linuxbox... done.
         
         In addition to use via the ``fab`` tool, Fabric's components may be 
imported
         into other Python code, providing a Pythonic interface to the SSH 
protocol
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/README.rst new/Fabric-1.10.2/README.rst
--- old/Fabric-1.10.1/README.rst        2014-09-19 04:01:17.000000000 +0200
+++ new/Fabric-1.10.2/README.rst        2015-04-30 04:32:40.000000000 +0200
@@ -9,7 +9,9 @@
  
 Typical use involves creating a Python module containing one or more functions,
 then executing them via the ``fab`` command-line tool. Below is a small but
-complete "fabfile" containing a single task::
+complete "fabfile" containing a single task:
+
+.. code-block:: python
 
     from fabric.api import run
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabfile/__init__.py 
new/Fabric-1.10.2/fabfile/__init__.py
--- old/Fabric-1.10.1/fabfile/__init__.py       2014-09-19 04:01:17.000000000 
+0200
+++ new/Fabric-1.10.2/fabfile/__init__.py       2015-05-04 03:23:07.000000000 
+0200
@@ -8,9 +8,6 @@
 
 from fabric.api import abort, local, task
 
-import tag
-from utils import msg
-
 
 @task(default=True)
 def test(args=None):
@@ -25,21 +22,3 @@
     default_args = "-sv --with-doctest --nologcapture --with-color %s" % tests
     default_args += (" " + args) if args else ""
     nose.core.run_exit(argv=[''] + default_args.split())
-
-
-@task
-def upload():
-    """
-    Build, register and upload to PyPI
-    """
-    with msg("Uploading to PyPI"):
-        local('python setup.py sdist register upload')
-
-
-@task
-def release(force='no'):
-    """
-    Tag, push tag to Github, & upload new version to PyPI.
-    """
-    tag.tag(force=force, push='yes')
-    upload()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabfile/tag.py 
new/Fabric-1.10.2/fabfile/tag.py
--- old/Fabric-1.10.1/fabfile/tag.py    2014-08-14 22:54:23.000000000 +0200
+++ new/Fabric-1.10.2/fabfile/tag.py    1970-01-01 01:00:00.000000000 +0100
@@ -1,119 +0,0 @@
-from __future__ import with_statement
-
-from contextlib import nested
-
-from fabric.api import abort, hide, local, settings, task
-
-# Need to import this as fabric.version for reload() purposes
-import fabric.version
-# But nothing is stopping us from making a convenient binding!
-_version = fabric.version.get_version
-
-from utils import msg
-
-
-def _seek_version(cmd, txt):
-    with nested(hide('running'), msg(txt)):
-        cmd = cmd % _version('short')
-        return local(cmd, capture=True)
-
-
-def current_version_is_tagged():
-    return _seek_version(
-        'git tag | egrep "^%s$"',
-        "Searching for existing tag"
-    )
-
-
-def current_version_is_changelogged(filename):
-    return _seek_version(
-        'egrep "^\* :release:\`%%s " %s' % filename,
-        "Looking for changelog entry"
-    )
-
-
-def update_code(filename, force):
-    """
-    Update version data structure in-code and commit that change to git.
-
-    Normally, if the version file has not been modified, we abort assuming the
-    user quit without saving. Specify ``force=yes`` to override this.
-    """
-    raw_input("Version update in %r required! Press Enter to load $EDITOR." % 
filename)
-    with hide('running'):
-        local("$EDITOR %s" % filename)
-    # Try to detect whether user bailed out of the edit
-    with hide('running'):
-        has_diff = local("git diff -- %s" % filename, capture=True)
-    if not has_diff and not force:
-        abort("You seem to have aborted the file edit, so I'm aborting too.")
-    return filename
-
-
-def commits_since_last_tag():
-    """
-    Has any work been done since the last tag?
-    """
-    with hide('running'):
-        return local("git log %s.." % _version('short'), capture=True)
-
-
-@task(default=True)
-def tag(force='no', push='no'):
-    """
-    Tag a new release.
-
-    Normally, if a Git tag exists matching the current version, and no Git
-    commits appear after that tag, we abort assuming the user is making a
-    mistake or forgot to commit their work.
-
-    To override this -- i.e. to re-tag and re-upload -- specify ``force=yes``.
-    We assume you know what you're doing if you use this.
-
-    By default we do not push the tag remotely; specify ``push=yes`` to force a
-    ``git push origin <tag>``.
-    """
-    force = force.lower() in ['y', 'yes']
-    with settings(warn_only=True):
-        changed = []
-        # Does the current in-code version exist as a Git tag already?
-        # If so, this means we haven't updated the in-code version specifier
-        # yet, and need to do so.
-        if current_version_is_tagged():
-            # That is, if any work has been done since. Sanity check!
-            if not commits_since_last_tag() and not force:
-                abort("No work done since last tag!")
-            # Open editor, update version
-            version_file = "fabric/version.py"
-            changed.append(update_code(version_file, force))
-        # If the tag doesn't exist, the user has already updated version info
-        # and we can just move on.
-        else:
-            print("Version has already been updated, no need to edit...")
-        # Similar process but for the changelog.
-        changelog = "docs/changelog.rst"
-        if not current_version_is_changelogged(changelog):
-            changed.append(update_code(changelog, force))
-        else:
-            print("Changelog already updated, no need to edit...")
-        # Commit any changes
-        if changed:
-            with msg("Committing updated version and/or changelog"):
-                reload(fabric.version)
-                local("git add %s" % " ".join(changed))
-                local("git commit -m \"Cut %s\"" % _version('verbose'))
-                local("git push")
-
-        # At this point, we've incremented the in-code version and just need to
-        # tag it in Git.
-        f = 'f' if force else ''
-        with msg("Tagging"):
-            local("git tag -%sam \"Fabric %s\" %s" % (
-                f,
-                _version('normal'),
-                _version('short')
-            ))
-        # And push to the central server, if we were told to
-        if push.lower() in ['y', 'yes']:
-            with msg("Pushing"):
-                local("git push origin %s" % _version('short'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabfile/utils.py 
new/Fabric-1.10.2/fabfile/utils.py
--- old/Fabric-1.10.1/fabfile/utils.py  2014-08-14 22:54:23.000000000 +0200
+++ new/Fabric-1.10.2/fabfile/utils.py  1970-01-01 01:00:00.000000000 +0100
@@ -1,13 +0,0 @@
-from __future__ import with_statement
-
-from contextlib import contextmanager
-
-from fabric.api import hide, puts
-
-
-@contextmanager
-def msg(txt):
-    puts(txt + "...", end='', flush=True)
-    with hide('everything'):
-        yield
-    puts("done.", show_prefix=False, flush=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/context_managers.py 
new/Fabric-1.10.2/fabric/context_managers.py
--- old/Fabric-1.10.1/fabric/context_managers.py        2014-12-19 
23:04:26.000000000 +0100
+++ new/Fabric-1.10.2/fabric/context_managers.py        2015-04-30 
04:32:40.000000000 +0200
@@ -34,7 +34,6 @@
 """
 
 from contextlib import contextmanager, nested
-import sys
 import socket
 import select
 
@@ -52,9 +51,9 @@
     """
     Refactored subroutine used by ``hide`` and ``show``.
     """
+    previous = {}
     try:
         # Preserve original values, pull in new given value to use
-        previous = {}
         for group in output.expand_aliases(groups):
             previous[group] = output[group]
             output[group] = which
@@ -542,7 +541,7 @@
             sock.connect((local_host, local_port))
         except Exception, e:
             print "[%s] rtunnel: cannot connect to %s:%d (from local)" % 
(env.host_string, local_host, local_port)
-            chan.close()
+            channel.close()
             return
 
         print "[%s] rtunnel: opened reverse tunnel: %r -> %r -> %r"\
@@ -566,7 +565,6 @@
         transport.cancel_port_forward(remote_bind_address, remote_port)
 
 
-
 quiet = lambda: settings(hide('everything'), warn_only=True)
 quiet.__doc__ = """
     Alias to ``settings(hide('everything'), warn_only=True)``.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/contrib/project.py 
new/Fabric-1.10.2/fabric/contrib/project.py
--- old/Fabric-1.10.1/fabric/contrib/project.py 2014-09-19 05:11:49.000000000 
+0200
+++ new/Fabric-1.10.2/fabric/contrib/project.py 2015-05-04 02:23:37.000000000 
+0200
@@ -52,7 +52,7 @@
 
         * If ``local_dir`` ends with a trailing slash, the files will be
           dropped inside of ``remote_dir``. E.g.
-          ``rsync_project("/home/username/project", "foldername/")`` will drop
+          ``rsync_project("/home/username/project/", "foldername/")`` will drop
           the contents of ``foldername`` inside of ``/home/username/project``.
         * If ``local_dir`` does **not** end with a trailing slash (and this
           includes the default scenario, when ``local_dir`` is not specified),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/job_queue.py 
new/Fabric-1.10.2/fabric/job_queue.py
--- old/Fabric-1.10.1/fabric/job_queue.py       2014-08-14 22:54:23.000000000 
+0200
+++ new/Fabric-1.10.2/fabric/job_queue.py       2015-05-04 02:23:37.000000000 
+0200
@@ -8,6 +8,7 @@
 from __future__ import with_statement
 import time
 import Queue
+from multiprocessing import Process
 
 from fabric.state import env
 from fabric.network import ssh
@@ -175,7 +176,8 @@
 
         # Attach exit codes now that we're all done & have joined all jobs
         for job in self._completed:
-            results[job.name]['exit_code'] = job.exitcode
+            if isinstance(job, Process):
+                results[job.name]['exit_code'] = job.exitcode
 
         return results
 
@@ -213,7 +215,8 @@
         from threading import Thread as Bucket
 
     # Make a job_queue with a bubble of len 5, and have it print verbosely
-    jobs = JobQueue(5)
+    queue = Queue.Queue()
+    jobs = JobQueue(5, queue)
     jobs._debug = True
 
     # Add 20 procs onto the stack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/network.py 
new/Fabric-1.10.2/fabric/network.py
--- old/Fabric-1.10.1/fabric/network.py 2014-09-19 05:11:49.000000000 +0200
+++ new/Fabric-1.10.2/fabric/network.py 2015-05-04 02:23:37.000000000 +0200
@@ -532,6 +532,8 @@
             # Update env.password, env.passwords if empty
             set_password(user, host, port, password)
         # Ctrl-D / Ctrl-C for exit
+        # TODO: this may no longer actually serve its original purpose and may
+        # also hide TypeErrors from paramiko. Double check in v2.
         except (EOFError, TypeError):
             # Print a newline (in case user was sitting at prompt)
             print('')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/operations.py 
new/Fabric-1.10.2/fabric/operations.py
--- old/Fabric-1.10.1/fabric/operations.py      2014-12-20 00:19:16.000000000 
+0100
+++ new/Fabric-1.10.2/fabric/operations.py      2015-06-19 20:16:26.000000000 
+0200
@@ -295,7 +295,8 @@
     scripts). To do this, specify ``mirror_local_mode=True``.
 
     Alternately, you may use the ``mode`` kwarg to specify an exact mode, in
-    the same vein as ``os.chmod`` or the Unix ``chmod`` command.
+    the same vein as ``os.chmod``, such as an exact octal number (``0755``) or
+    a string representing one (``"0755"``).
 
     `~fabric.operations.put` will honor `~fabric.context_managers.cd`, so
     relative values in ``remote_path`` will be prepended by the current remote
@@ -663,8 +664,9 @@
     # Also place it at the front of the list, in case user is expecting another
     # prefixed command to be "in" the current working directory.
     cwd = env.cwd if which == 'remote' else env.lcwd
+    redirect = " >/dev/null" if not win32 else ''
     if cwd:
-        prefixes.insert(0, 'cd %s' % cwd)
+        prefixes.insert(0, 'cd %s%s' % (cwd, redirect))
     glue = " && "
     prefix = (glue.join(prefixes) + glue) if prefixes else ""
     return prefix + command
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/sftp.py 
new/Fabric-1.10.2/fabric/sftp.py
--- old/Fabric-1.10.1/fabric/sftp.py    2014-12-20 00:19:16.000000000 +0100
+++ new/Fabric-1.10.2/fabric/sftp.py    2015-05-04 02:23:37.000000000 +0200
@@ -12,6 +12,9 @@
 from fabric.context_managers import settings
 
 
+# TODO: use self.sftp.listdir_iter on Paramiko 1.15+
+
+
 def _format_local(local_path, local_is_path):
     """Format a path for log output"""
     if local_is_path:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/state.py 
new/Fabric-1.10.2/fabric/state.py
--- old/Fabric-1.10.1/fabric/state.py   2014-12-20 00:19:16.000000000 +0100
+++ new/Fabric-1.10.2/fabric/state.py   2015-05-04 02:23:37.000000000 +0200
@@ -68,7 +68,7 @@
     return expanded_rc_path
 
 default_port = '22'  # hurr durr
-default_ssh_config_path = '~/.ssh/config'
+default_ssh_config_path = os.path.join(os.path.expanduser('~'), '.ssh', 
'config')
 
 # Options/settings which exist both as environment keys and which can be set on
 # the command line, are defined here. When used via `fab` they will be added to
@@ -426,10 +426,11 @@
     'running': True,
     'stdout': True,
     'stderr': True,
+    'exceptions': False,
     'debug': False,
     'user': True
 }, aliases={
-    'everything': ['warnings', 'running', 'user', 'output'],
+    'everything': ['warnings', 'running', 'user', 'output', 'exceptions'],
     'output': ['stdout', 'stderr'],
     'commands': ['stdout', 'running']
 })
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/tasks.py 
new/Fabric-1.10.2/fabric/tasks.py
--- old/Fabric-1.10.1/fabric/tasks.py   2014-12-20 00:19:16.000000000 +0100
+++ new/Fabric-1.10.2/fabric/tasks.py   2015-05-04 02:23:37.000000000 +0200
@@ -177,7 +177,10 @@
         return getattr(self.wrapped, k)
 
     def __details__(self):
-        return get_task_details(self.wrapped)
+        orig = self
+        while 'wrapped' in orig.__dict__:
+            orig = orig.__dict__.get('wrapped')
+        return get_task_details(orig)
 
 
 def requires_parallel(task):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/utils.py 
new/Fabric-1.10.2/fabric/utils.py
--- old/Fabric-1.10.1/fabric/utils.py   2014-12-19 23:11:58.000000000 +0100
+++ new/Fabric-1.10.2/fabric/utils.py   2015-05-22 01:47:32.000000000 +0200
@@ -30,9 +30,12 @@
     """
     Abort execution, print ``msg`` to stderr and exit with error status (1.)
 
-    This function currently makes use of `sys.exit`_, which raises
-    `SystemExit`_. Therefore, it's possible to detect and recover from inner
-    calls to `abort` by using ``except SystemExit`` or similar.
+    This function currently makes use of `SystemExit`_ in a manner that is
+    similar to `sys.exit`_ (but which skips the automatic printing to stderr,
+    allowing us to more tightly control it via settings).
+
+    Therefore, it's possible to detect and recover from inner calls to `abort`
+    by using ``except SystemExit`` or similar.
 
     .. _sys.exit: http://docs.python.org/library/sys.html#sys.exit
     .. _SystemExit: 
http://docs.python.org/library/exceptions.html#exceptions.SystemExit
@@ -50,7 +53,13 @@
     if env.abort_exception:
         raise env.abort_exception(msg)
     else:
-        sys.exit(msg)
+        # See issue #1318 for details on the below; it lets us construct a
+        # valid, useful SystemExit while sidestepping the automatic stderr
+        # print (which would otherwise duplicate with the above in a
+        # non-controllable fashion).
+        e = SystemExit(1)
+        e.message = msg
+        raise e
 
 
 def warn(msg):
@@ -325,9 +334,11 @@
     import fabric.state
     if func is None:
         func = fabric.state.env.warn_only and warn or abort
-    # If debug printing is on, append a traceback to the message
-    if fabric.state.output.debug:
-        message += "\n\n" + format_exc()
+    # If exception printing is on, append a traceback to the message
+    if fabric.state.output.exceptions or fabric.state.output.debug:
+        exception_message = format_exc()
+        if exception_message:
+            message += "\n\n" + exception_message
     # Otherwise, if we were given an exception, append its contents.
     elif exception is not None:
         # Figure out how to get a string out of the exception; EnvironmentError
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/fabric/version.py 
new/Fabric-1.10.2/fabric/version.py
--- old/Fabric-1.10.1/fabric/version.py 2014-12-20 00:19:16.000000000 +0100
+++ new/Fabric-1.10.2/fabric/version.py 2015-05-04 02:24:14.000000000 +0200
@@ -9,7 +9,7 @@
 from os.path import abspath, dirname
 
 
-VERSION = (1, 10, 1, 'final', 0)
+VERSION = (1, 10, 2, 'final', 0)
 
 
 def git_sha():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/sites/docs/index.rst 
new/Fabric-1.10.2/sites/docs/index.rst
--- old/Fabric-1.10.1/sites/docs/index.rst      2014-09-19 04:01:17.000000000 
+0200
+++ new/Fabric-1.10.2/sites/docs/index.rst      2015-05-04 02:24:16.000000000 
+0200
@@ -76,3 +76,14 @@
     :glob:
 
     api/contrib/*
+
+
+Contributing & Running Tests
+----------------------------
+
+For advanced users & developers looking to help fix bugs or add new features.
+
+.. toctree::
+    :hidden:
+
+    running_tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/sites/docs/running_tests.rst 
new/Fabric-1.10.2/sites/docs/running_tests.rst
--- old/Fabric-1.10.1/sites/docs/running_tests.rst      1970-01-01 
01:00:00.000000000 +0100
+++ new/Fabric-1.10.2/sites/docs/running_tests.rst      2015-05-04 
02:24:16.000000000 +0200
@@ -0,0 +1,48 @@
+======================
+Running Fabric's Tests
+======================
+
+Fabric is maintained with 100% passing tests. Where possible, patches should
+include tests covering the changes, making things far easier to verify & merge.
+
+When developing on Fabric, it works best to establish a `virtualenv`_ to 
install
+the dependencies in isolation for running tests.
+
+.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/
+
+.. _first-time-setup:
+
+First-time Setup
+================
+
+* Fork the `repository`_ on GitHub
+* Clone your new fork (e.g.
+  ``git clone [email protected]:<your_username>/fabric.git``)
+* ``cd fabric``
+* ``virtualenv env``
+* ``. env/bin/activate``
+* ``pip install -r requirements.txt``
+* ``python setup.py develop``
+
+.. _`repository`: https://github.com/fabric/fabric
+
+.. _running-tests:
+
+Running Tests
+=============
+
+Once your virtualenv is activated (``. env/bin/activate``) & you have the 
latest
+requirements, running tests is just::
+
+    nosetests tests/
+
+You should **always** run tests on ``master`` (or the release branch you're
+working with) to ensure they're passing before working on your own
+changes/tests.
+
+Alternatively, if you've run ``python setup.py develop`` on your Fabric clone,
+you can also run::
+
+    fab test
+
+This adds additional flags which enable running doctests & adds nice 
coloration.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/sites/docs/usage/env.rst 
new/Fabric-1.10.2/sites/docs/usage/env.rst
--- old/Fabric-1.10.1/sites/docs/usage/env.rst  2014-12-20 00:19:16.000000000 
+0100
+++ new/Fabric-1.10.2/sites/docs/usage/env.rst  2015-05-04 02:23:37.000000000 
+0200
@@ -406,7 +406,7 @@
 **Default:** ``0`` (i.e. no keepalive)
 
 An integer specifying an SSH keepalive interval to use; basically maps to the
-SSH config option ``ClientAliveInterval``. Useful if you find connections are
+SSH config option ``ServerAliveInterval``. Useful if you find connections are
 timing out due to meddlesome network hardware or what have you.
 
 .. seealso:: :option:`--keepalive`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/sites/docs/usage/output_controls.rst 
new/Fabric-1.10.2/sites/docs/usage/output_controls.rst
--- old/Fabric-1.10.1/sites/docs/usage/output_controls.rst      2014-09-19 
04:01:17.000000000 +0200
+++ new/Fabric-1.10.2/sites/docs/usage/output_controls.rst      2015-05-04 
02:23:37.000000000 +0200
@@ -19,7 +19,7 @@
 
 .. note::
 
-    All levels, save for ``debug``, are on by default.
+    All levels, save for ``debug`` and ``exceptions``, are on by default.
 
 Standard output levels
 ----------------------
@@ -52,7 +52,7 @@
 
 * **user**: User-generated output, i.e. local output printed by fabfile code
   via use of the `~fabric.utils.fastprint` or `~fabric.utils.puts` functions.
-
+  
 .. versionchanged:: 0.9.2
     Added "Executing task" lines to the ``running`` output level.
 
@@ -62,8 +62,10 @@
 Debug output
 ------------
 
-There is a final atomic output level, ``debug``, which behaves slightly
-differently from the rest:
+There are two more atomic output levels for use when troubleshooting:
+``debug``, which behaves slightly differently from the rest, and
+``exceptions``, whose behavior is included in ``debug`` but may be enabled
+separately.
 
 * **debug**: Turn on debugging (which is off by default.) Currently, this is
   largely used to view the "full" commands being run; take for example this
@@ -82,7 +84,7 @@
       [hostname] run: /bin/bash -l -c "ls \"/home/username/Folder Name With 
Spaces\""
 
   Enabling ``debug`` output will also display full Python tracebacks during
-  aborts.
+  aborts (as if ``exceptions`` output was enabled).
   
   .. note::
   
@@ -92,9 +94,16 @@
       ``running`` is False but ``debug`` is True, you will still be shown the
       'running' line in its debugging form.
 
+* **exceptions**: Enables display of tracebacks when exceptions occur; intended
+  for use when ``debug`` is set to ``False`` but one is still interested in
+  detailed error info.
+
 .. versionchanged:: 1.0
     Debug output now includes full Python tracebacks during aborts.
 
+.. versionchanged:: 1.11
+    Added the ``exceptions`` output level.
+
 .. _output-aliases:
 
 Output level aliases
Files old/Fabric-1.10.1/sites/www/.changelog.rst.swp and 
new/Fabric-1.10.2/sites/www/.changelog.rst.swp differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/sites/www/changelog.rst 
new/Fabric-1.10.2/sites/www/changelog.rst
--- old/Fabric-1.10.1/sites/www/changelog.rst   2014-12-20 00:19:16.000000000 
+0100
+++ new/Fabric-1.10.2/sites/www/changelog.rst   2015-06-19 20:18:15.000000000 
+0200
@@ -2,6 +2,33 @@
 Changelog
 =========
 
+* :release:`1.10.2 <2015-06-19>`
+* :support:`1325` Clarify `~fabric.operations.put` docs re: the ``mode``
+  argument. Thanks to ``@mjmare`` for the catch.
+* :bug:`1318` Update functionality added in :issue:`1213` so abort error
+  messages don't get printed twice (once by us, once by ``sys.exit``) but the
+  annotated exception error message is retained. Thanks to Felix Almeida for
+  the report.
+* :bug:`1305` (also :issue:`1313`) Fix a couple minor issues with the operation
+  of & demo code for the ``JobQueue`` class. Thanks to ``@dioh`` and Horst
+  Gutmann for the report & Cameron Lane for the patch.
+* :bug:`980` (also :issue:`1312`) Redirect output of ``cd`` to ``/dev/null`` so
+  users enabling bash's ``CDPATH`` (or similar features in other shells) don't
+  have polluted output captures. Thanks to Alex North-Keys for the original
+  report & Steve Ivy for the fix.
+* :bug:`1289` Fix "NameError: free variable referenced before assignment in
+  enclosing scope". Thanks to ``@SamuelMarks`` for catch & patch.
+* :bug:`1286` (also :issue:`971`, :issue:`1032`) Recursively unwrap decorators
+  instead of only unwrapping a single decorator level, when obtaining task
+  docstrings. Thanks to Avishai Ish-Shalom for the original report & Max Kovgan
+  for the patch.
+* :bug:`1273` Fix issue with ssh/config not having a cross-platform default
+  path. Thanks to ``@SamuelMarks`` for catch & patch.
+* :feature:`1200` Introduced ``exceptions`` output level, so users don't have 
to
+  deal with the debug output just to see tracebacks.
+* :support:`1239` Update README to work better under raw docutils so the
+  example code block is highlighted as Python on PyPI (and not just on our
+  Sphinx-driven website). Thanks to Marc Abramowitz.
 * :release:`1.10.1 <2014-12-19>`
 * :release:`1.9.2 <2014-12-19>`
 * :bug:`1201` Don't naively glob all `~fabric.operations.get` targets - only
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/sites/www/installing.rst 
new/Fabric-1.10.2/sites/www/installing.rst
--- old/Fabric-1.10.1/sites/www/installing.rst  2014-09-19 05:11:49.000000000 
+0200
+++ new/Fabric-1.10.2/sites/www/installing.rst  2015-05-04 02:23:37.000000000 
+0200
@@ -56,7 +56,7 @@
 Python
 ------
 
-Fabric requires `Python <http://python.org>`_ version 2.5 or 2.6. Some caveats
+Fabric requires `Python <http://python.org>`_ version 2.5 - 2.7. Some caveats
 and notes about other Python versions:
 
 * We are not planning on supporting **Python 2.4** given its age and the number
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/sites/www/roadmap.rst 
new/Fabric-1.10.2/sites/www/roadmap.rst
--- old/Fabric-1.10.1/sites/www/roadmap.rst     2014-12-20 00:19:16.000000000 
+0100
+++ new/Fabric-1.10.2/sites/www/roadmap.rst     2015-06-19 20:18:33.000000000 
+0200
@@ -13,8 +13,8 @@
 Fabric 1.x
 ==========
 
-Fabric 1.x, while not end-of-life'd, has reached a tipping point regarding
-internal tech debt & ability to make significant improvements without harming
+Fabric 1.x, while not quite yet end-of-life'd, has reached a tipping point
+regarding internal tech debt & ability to make improvements without harming
 backwards compatibility.
 
 As such, future 1.x releases (**1.6** onwards) will emphasize small-to-medium
@@ -31,25 +31,27 @@
   <https://github.com/pyinvoke/invoke>`_ (see also :issue:`565`), which is a
   revamped and standalone version of Fabric's task running components. 
 
-    * As of late 2013, Invoke is approaching maturity and already has a 
handful of
+    * As of early 2015, Invoke is already reasonably mature and has a handful 
of
       features lacking in Fabric itself, including but not limited to:
       
         * a more explicit and powerful namespacing implementation
-        * "regular" style CLI flags,
+        * "regular" style CLI flags, including powerful tab completion
         * before/after hooks
-        * explicit context management
+        * explicit context management (no shared state)
+        * significantly more powerful configuration mechanisms
 
     * Invoke is already Python 3 compatible, due to being a new codebase with
       few dependencies.
-    * As Fabric 2 is developed, Invoke will continue to grow & change to suit
-      Fabric's needs while remaining a high quality standalone task runner.
+    * As Fabric 2 is developed, Invoke will approach a 1.0 release, and will
+      continue to grow & change to suit Fabric's needs while remaining a high
+      quality standalone task runner.
 
-* Start putting together Fabric 2.0, a mostly-rewritten Fabric core:
+* Release Fabric 2.0, a mostly-rewritten Fabric core:
 
     * Leverage Invoke for task running, leaving Fabric itself much more library
       oriented.
     * Implement object-oriented hosts/host lists and all the fun stuff that
-      provides (e.g. no more hacky host string and unintuitive env var
+      provides (no more hacky host string and unintuitive env var
       manipulation.)
     * No more shared state by default (thanks to Invoke's context design.)
     * Any other core overhauls difficult to do in a backwards compatible
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/tests/Python26SocketServer.py 
new/Fabric-1.10.2/tests/Python26SocketServer.py
--- old/Fabric-1.10.1/tests/Python26SocketServer.py     2014-08-14 
22:54:23.000000000 +0200
+++ new/Fabric-1.10.2/tests/Python26SocketServer.py     2015-05-04 
02:23:37.000000000 +0200
@@ -118,6 +118,7 @@
   entry is processed by a RequestHandlerClass.
 
 """
+# This file copyright (c) 2001-2015 Python Software Foundation; All Rights 
Reserved
 
 # Author of the BaseServer patch: Luke Kenneth Casson Leighton
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/tests/support/aborts.py 
new/Fabric-1.10.2/tests/support/aborts.py
--- old/Fabric-1.10.1/tests/support/aborts.py   1970-01-01 01:00:00.000000000 
+0100
+++ new/Fabric-1.10.2/tests/support/aborts.py   2015-05-04 03:23:07.000000000 
+0200
@@ -0,0 +1,5 @@
+from fabric.api import task, abort
+
+@task
+def kaboom():
+    abort("It burns!")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/tests/test_context_managers.py 
new/Fabric-1.10.2/tests/test_context_managers.py
--- old/Fabric-1.10.1/tests/test_context_managers.py    2014-09-19 
04:09:42.000000000 +0200
+++ new/Fabric-1.10.2/tests/test_context_managers.py    2015-05-04 
02:23:37.000000000 +0200
@@ -9,7 +9,7 @@
 from fabric.state import env, output
 from fabric.context_managers import (cd, settings, lcd, hide, shell_env, quiet,
     warn_only, prefix, path)
-from fabric.operations import run, local
+from fabric.operations import run, local, _prefix_commands
 from utils import mock_streams, FabricTest
 from server import server
 
@@ -110,6 +110,35 @@
         with cm2:
             eq_(env.command_prefixes, ['1', '2'])
 
+#
+# cd prefix with dev/null
+#
+
+def test_cd_prefix():
+    """
+    cd prefix should direct output to /dev/null in case of CDPATH
+    """
+    some_path = "~/somepath"
+
+    with cd(some_path):
+        command_out = _prefix_commands('foo', "remote")
+        eq_(command_out, 'cd %s >/dev/null && foo' % some_path)
+
+
+# def test_cd_prefix_on_win32():
+#     """
+#     cd prefix should NOT direct output to /dev/null on win32
+#     """
+#     some_path = "~/somepath"
+
+#     import fabric
+#     try:
+#         fabric.state.win32 = True
+#         with cd(some_path):
+#             command_out = _prefix_commands('foo', "remote")
+#             eq_(command_out, 'cd %s && foo' % some_path)
+#     finally:
+#         fabric.state.win32 = False
 
 #
 # hide/show
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/tests/test_network.py 
new/Fabric-1.10.2/tests/test_network.py
--- old/Fabric-1.10.1/tests/test_network.py     2014-09-19 05:11:49.000000000 
+0200
+++ new/Fabric-1.10.2/tests/test_network.py     2015-04-30 04:32:40.000000000 
+0200
@@ -16,7 +16,6 @@
 import fabric.network  # So I can call patch_object correctly. Sigh.
 from fabric.state import env, output, _get_system_username
 from fabric.operations import run, sudo, prompt
-from fabric.exceptions import NetworkError
 from fabric.tasks import execute
 from fabric.api import parallel
 from fabric import utils # for patching
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/tests/test_tasks.py 
new/Fabric-1.10.2/tests/test_tasks.py
--- old/Fabric-1.10.1/tests/test_tasks.py       2014-12-20 00:19:16.000000000 
+0100
+++ new/Fabric-1.10.2/tests/test_tasks.py       2015-05-04 02:23:37.000000000 
+0200
@@ -10,7 +10,7 @@
 import fabric
 from fabric.tasks import WrappedCallableTask, execute, Task, get_task_details
 from fabric.main import display_command
-from fabric.api import run, env, settings, hosts, roles, hide, parallel, task
+from fabric.api import run, env, settings, hosts, roles, hide, parallel, task, 
runs_once, serial
 from fabric.network import from_dict
 from fabric.exceptions import NetworkError
 
@@ -466,6 +466,9 @@
 
 class TestTaskDetails(unittest.TestCase):
     def test_old_style_task_with_default_args(self):
+        """
+        __details__() should print docstr for old style task methods with 
default args
+        """
         def task_old_style(arg1, arg2, arg3=None, arg4='yes'):
             '''Docstring'''
         details = get_task_details(task_old_style)
@@ -474,6 +477,10 @@
             details)
 
     def test_old_style_task_without_default_args(self):
+        """
+        __details__() should print docstr for old style task methods without 
default args
+        """
+
         def task_old_style(arg1, arg2):
             '''Docstring'''
         details = get_task_details(task_old_style)
@@ -482,6 +489,10 @@
             details)
 
     def test_old_style_task_without_args(self):
+        """
+        __details__() should print docstr for old style task methods without 
args
+        """
+
         def task_old_style():
             '''Docstring'''
         details = get_task_details(task_old_style)
@@ -490,14 +501,43 @@
             details)
 
     def test_decorated_task(self):
+        """
+        __details__() should print docstr for method with any number and order 
of decorations
+        """
+        expected = "\n".join([
+            "Docstring",
+            "Arguments: arg1",
+            ])
+
         @task
         def decorated_task(arg1):
             '''Docstring'''
-        eq_("Docstring\n"
-            "Arguments: arg1",
-            decorated_task.__details__())
+
+        actual = decorated_task.__details__()
+        eq_(expected, actual)
+
+        @runs_once
+        @task
+        def decorated_task1(arg1):
+            '''Docstring'''
+
+        actual = decorated_task1.__details__()
+        eq_(expected, actual)
+
+        @runs_once
+        @serial
+        @task
+        def decorated_task2(arg1):
+            '''Docstring'''
+
+        actual = decorated_task2.__details__()
+        eq_(expected, actual)
 
     def test_subclassed_task(self):
+        """
+        __details__() should print docstr for subclassed task methods with args
+        """
+
         class SpecificTask(Task):
             def run(self, arg1, arg2, arg3):
                 '''Docstring'''
@@ -507,6 +547,10 @@
 
     @mock_streams('stdout')
     def test_multiline_docstring_indented_correctly(self):
+        """
+        display_command() should properly indent docstr for old style task 
methods
+        """
+
         def mytask(arg1):
             """
             This is a multi line docstring.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Fabric-1.10.1/tests/test_utils.py 
new/Fabric-1.10.2/tests/test_utils.py
--- old/Fabric-1.10.1/tests/test_utils.py       2014-12-19 19:39:38.000000000 
+0100
+++ new/Fabric-1.10.2/tests/test_utils.py       2015-05-04 03:23:07.000000000 
+0200
@@ -1,6 +1,7 @@
 from __future__ import with_statement
 
 import sys
+import traceback
 from unittest import TestCase
 
 from fudge import Fake, patched_context, with_fakes
@@ -10,9 +11,11 @@
 from fabric.state import output, env
 from fabric.utils import warn, indent, abort, puts, fastprint, error, 
RingBuffer
 from fabric import utils  # For patching
+from fabric.api import local, quiet
 from fabric.context_managers import settings, hide
 from fabric.colors import magenta, red
-from utils import mock_streams, aborts, FabricTest, assert_contains
+from utils import mock_streams, aborts, FabricTest, assert_contains, \
+    assert_not_contains
 
 
 @mock_streams('stderr')
@@ -70,7 +73,6 @@
     with settings(abort_exception=TestException):
         abort("Test")
 
-
 @mock_streams('stderr')
 @with_patched_object(output, 'aborts', True)
 def test_abort_message():
@@ -84,6 +86,31 @@
     result = sys.stderr.getvalue()
     eq_("\nFatal error: Test\n\nAborting.\n", result)
 
+def test_abort_message_only_printed_once():
+    """
+    abort()'s SystemExit should not cause a reprint of the error message
+    """
+    # No good way to test the implicit stderr print which sys.exit/SystemExit
+    # perform when they are allowed to bubble all the way to the top. So, we
+    # invoke a subprocess and look at its stderr instead.
+    with quiet():
+        result = local("fab -f tests/support/aborts.py kaboom", capture=True)
+    # When error in #1318 is present, this has an extra "It burns!" at end of
+    # stderr string.
+    eq_(result.stderr, "Fatal error: It burns!\n\nAborting.")
+
+@mock_streams('stderr')
+@with_patched_object(output, 'aborts', True)
+def test_abort_exception_contains_separate_message_and_code():
+    """
+    abort()'s SystemExit contains distinct .code/.message attributes.
+    """
+    # Re #1318 / #1213
+    try:
+        abort("Test")
+    except SystemExit as e:
+        eq_(e.message, "Test")
+        eq_(e.code, 1)
 
 @mock_streams('stdout')
 def test_puts_with_user_output_on():
@@ -163,6 +190,8 @@
 
 
 class TestErrorHandling(FabricTest):
+    dummy_string = 'test1234!'
+
     @with_patched_object(utils, 'warn', Fake('warn', callable=True,
         expect_call=True))
     def test_error_warns_if_warn_only_True_and_func_None(self):
@@ -200,6 +229,45 @@
             error("error message", func=utils.abort, stdout=stdout)
         assert_contains(stdout, sys.stdout.getvalue())
 
+    @mock_streams('stdout')
+    @with_patched_object(utils, 'abort', Fake('abort', callable=True,
+        expect_call=True).calls(lambda x: sys.stdout.write(x + "\n")))
+    @with_patched_object(output, 'exceptions', True)
+    @with_patched_object(utils, 'format_exc', Fake('format_exc', callable=True,
+        expect_call=True).returns(dummy_string))
+    def test_includes_traceback_if_exceptions_logging_is_on(self):
+        """
+        error() includes traceback in message if exceptions logging is on
+        """
+        error("error message", func=utils.abort, stdout=error)
+        assert_contains(self.dummy_string, sys.stdout.getvalue())
+
+    @mock_streams('stdout')
+    @with_patched_object(utils, 'abort', Fake('abort', callable=True,
+        expect_call=True).calls(lambda x: sys.stdout.write(x + "\n")))
+    @with_patched_object(output, 'debug', True)
+    @with_patched_object(utils, 'format_exc', Fake('format_exc', callable=True,
+        expect_call=True).returns(dummy_string))
+    def test_includes_traceback_if_debug_logging_is_on(self):
+        """
+        error() includes traceback in message if debug logging is on 
(backwardis compatibility)
+        """
+        error("error message", func=utils.abort, stdout=error)
+        assert_contains(self.dummy_string, sys.stdout.getvalue())
+
+    @mock_streams('stdout')
+    @with_patched_object(utils, 'abort', Fake('abort', callable=True,
+        expect_call=True).calls(lambda x: sys.stdout.write(x + "\n")))
+    @with_patched_object(output, 'exceptions', True)
+    @with_patched_object(utils, 'format_exc', Fake('format_exc', callable=True,
+        expect_call=True).returns(None))
+    def test_doesnt_print_None_when_no_traceback_present(self):
+        """
+        error() doesn't include None in message if there is no traceback
+        """
+        error("error message", func=utils.abort, stdout=error)
+        assert_not_contains('None', sys.stdout.getvalue())
+
     @mock_streams('stderr')
     @with_patched_object(utils, 'abort', Fake('abort', callable=True,
         expect_call=True).calls(lambda x: sys.stderr.write(x + "\n")))


Reply via email to