Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-Fabric for openSUSE:Factory checked in at 2023-07-03 17:43:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-Fabric (Old) and /work/SRC/openSUSE:Factory/.python-Fabric.new.13546 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Fabric" Mon Jul 3 17:43:01 2023 rev:43 rq:1096411 version:3.0.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-Fabric/python-Fabric.changes 2023-07-01 23:18:19.398358153 +0200 +++ /work/SRC/openSUSE:Factory/.python-Fabric.new.13546/python-Fabric.changes 2023-07-03 17:43:03.808816802 +0200 @@ -1,0 +2,28 @@ +Sun Jul 2 08:57:33 UTC 2023 - ecsos <[email protected]> + +- Update to 3.0.1 + * [Bug] #2241: A typo prevented Fabricâs command runner from properly + calling its superclass stop() method, which in tandem with a related + Invoke bug meant messy or long shutdowns in many scenarios. +- Changes from 3.0.0 + * [Feature]: Change the default configuration value for inline_ssh_env + from False to True, to better align with the practicalities of common + SSH server configurations. + - Warning + This change is backwards incompatible if you were using + environment-variable-setting kwargs or config settings, + such as Connection.run(command, env={'SOME': 'ENV VARS'}), + and were not already explicitly specifying the value of inline_ssh_env. + * [Bug] #1981: (fixed in #2195) Automatically close any open SFTP session + during fabric.connection.Connection.close; this avoids issues encountered + upon re-opening a previously-closed connection object. + * [Support]: Drop support for Python <3.6, including Python 2. + - Warning + This is a backwards incompatible change if you are not yet on + Python 3.6 or above; however, pip shouldnât offer you this + version of Fabric as long as your pip version understands + python_requires metadata. +- Drop remove-mock.patch because now in upstream. +- Drop remove-pathlib2.patch because now in upstream. + +------------------------------------------------------------------- Old: ---- fabric-2.7.1.tar.gz remove-mock.patch remove-pathlib2.patch New: ---- fabric-3.0.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-Fabric.spec ++++++ --- /var/tmp/diff_new_pack.MtlOSC/_old 2023-07-03 17:43:04.428820453 +0200 +++ /var/tmp/diff_new_pack.MtlOSC/_new 2023-07-03 17:43:04.432820476 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-Fabric # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-Fabric -Version: 2.7.1 +Version: 3.0.1 Release: 0 Summary: A Pythonic tool for remote execution and deployment License: BSD-2-Clause @@ -26,25 +26,16 @@ Source: https://files.pythonhosted.org/packages/source/f/fabric/fabric-%{version}.tar.gz # PATCH-FIX-UPSTREAM gh#fabric/fabric#2209 Patch0: fix-executable.patch -# PATCH-FIX-UPSTREAM gh#fabric/fabric#2210 -Patch1: remove-mock.patch -# PATCH-FIX-OPENSUSE remove pathlib2 requirement gh#fabric/fabric#2180 -Patch2: remove-pathlib2.patch -BuildRequires: %{python_module cryptography >= 1.1} BuildRequires: %{python_module decorator} -BuildRequires: %{python_module invoke >= 1.3} +BuildRequires: %{python_module invoke >= 2.0} BuildRequires: %{python_module paramiko >= 2.4} BuildRequires: %{python_module pytest-relaxed} BuildRequires: %{python_module setuptools} -BuildRequires: %{python_module six} BuildRequires: fdupes BuildRequires: python-rpm-macros -Requires: python-cryptography >= 1.1 Requires: python-decorator -Requires: python-invoke >= 1.3 +Requires: python-invoke >= 2.0 Requires: python-paramiko >= 2.4 -Requires: python-setuptools -Requires: python-six Requires(post): update-alternatives Requires(postun):update-alternatives Conflicts: python-Fabric3 ++++++ fabric-2.7.1.tar.gz -> fabric-3.0.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/PKG-INFO new/fabric-3.0.1/PKG-INFO --- old/fabric-2.7.1/PKG-INFO 2022-07-15 00:39:03.000000000 +0200 +++ new/fabric-3.0.1/PKG-INFO 2023-04-29 20:59:33.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: fabric -Version: 2.7.1 +Version: 3.0.1 Summary: High level SSH command execution Home-page: https://fabfile.org Author: Jeff Forcier @@ -57,13 +57,14 @@ Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: Microsoft :: Windows Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Build Tools Classifier: Topic :: Software Development :: Libraries diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/dev-requirements.txt new/fabric-3.0.1/dev-requirements.txt --- old/fabric-2.7.1/dev-requirements.txt 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/dev-requirements.txt 2023-04-28 17:33:01.000000000 +0200 @@ -1,24 +1,19 @@ # Us, of course -e . +paramiko>=3.0 +invoke>=2.0 # Invocations for common project tasks -invocations==2.6.0 +invocations>=3.0.1 # pytest-relaxed for test organization, display etc tweaks -pytest-relaxed>=1.0.1,<1.1 -pytest==3.2.5 +pytest-relaxed>=2 # pytest-cov for coverage -pytest-cov==2.5.1 -six==1.10.0 -# Mock for test mocking -mock==2.0.0 -# Formatting! -flake8==3.6.0 -black==18.6b4 +pytest-cov>=4 +# Formatting +# Flake8 5.x seems to have an odd importlib-metadata incompatibility? +flake8>=4,<5 +black>=22.8,<22.9 # Coverage! -coverage==5.3.1 -codecov==2.1.11 +coverage>=6.2,<7 # Documentation tools -sphinx>=1.4,<1.7 -alabaster==0.7.12 -releases>=1.5,<2.0 -# Release tools -semantic_version>=2.4,<2.5 +releases>=2 +alabaster==0.7.13 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/_version.py new/fabric-3.0.1/fabric/_version.py --- old/fabric-2.7.1/fabric/_version.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/fabric/_version.py 2023-04-29 20:58:51.000000000 +0200 @@ -1,2 +1,2 @@ -__version_info__ = (2, 7, 1) +__version_info__ = (3, 0, 1) __version__ = ".".join(map(str, __version_info__)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/config.py new/fabric-3.0.1/fabric/config.py --- old/fabric-2.7.1/fabric/config.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/fabric/config.py 2023-04-29 19:40:23.000000000 +0200 @@ -156,7 +156,7 @@ # Now that our own attributes have been prepared & kwargs yanked, we # can fall up into parent __init__() - super(Config, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # And finally perform convenience non-lazy bits if needed if not lazy: @@ -202,7 +202,7 @@ # .base_ssh_config ourselves. Similarly, there's no need to worry about # how the SSH config paths may be inaccurate until below; nothing will # be referencing them. - new = super(Config, self).clone(*args, **kwargs) + new = super().clone(*args, **kwargs) # Copy over our custom attributes, so that the clone still resembles us # re: recording where the data originally came from (in case anything # re-runs ._load_ssh_files(), for example). @@ -220,7 +220,7 @@ def _clone_init_kwargs(self, *args, **kw): # Parent kwargs - kwargs = super(Config, self)._clone_init_kwargs(*args, **kw) + kwargs = super()._clone_init_kwargs(*args, **kw) # Transmit our internal SSHConfig via explicit-obj kwarg, thus # bypassing any file loading. (Our extension of clone() above copies # over other attributes as well so that the end result looks consistent @@ -247,8 +247,9 @@ path = self._runtime_ssh_path # Manually blow up like open() (_load_ssh_file normally doesn't) if not os.path.exists(path): - msg = "No such file or directory: {!r}".format(path) - raise IOError(errno.ENOENT, msg) + raise FileNotFoundError( + errno.ENOENT, "No such file or directory", path + ) self._load_ssh_file(os.path.expanduser(path)) elif self.load_ssh_configs: for path in (self._user_ssh_path, self._system_ssh_path): @@ -304,8 +305,7 @@ "connect_kwargs": {}, "forward_agent": False, "gateway": None, - # TODO 3.0: change to True and update all docs accordingly. - "inline_ssh_env": False, + "inline_ssh_env": True, "load_ssh_configs": True, "port": 22, "runners": {"remote": Remote, "remote_shell": RemoteShell}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/connection.py new/fabric-3.0.1/fabric/connection.py --- old/fabric-2.7.1/fabric/connection.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/fabric/connection.py 2023-04-29 19:40:23.000000000 +0200 @@ -1,15 +1,12 @@ from contextlib import contextmanager +from io import StringIO from threading import Event +import socket try: - from invoke.vendor.six import StringIO from invoke.vendor.decorator import decorator - from invoke.vendor.six import string_types except ImportError: - from six import StringIO from decorator import decorator - from six import string_types -import socket from invoke import Context from invoke.exceptions import ThreadException @@ -327,15 +324,19 @@ :param bool inline_ssh_env: Whether to send environment variables "inline" as prefixes in front - of command strings (``export VARNAME=value && mycommand here``), - instead of trying to submit them through the SSH protocol itself - (which is the default behavior). This is necessary if the remote - server has a restricted ``AcceptEnv`` setting (which is the common - default). - - The default value is the value of the ``inline_ssh_env`` - :ref:`configuration value <default-values>` (which itself defaults - to ``False``). + of command strings (``export VARNAME=value && mycommand here``; + this is the default behavior), or submit them through the SSH + protocol itself. + + In Fabric 2.x this defaulted to ``False`` (try using the protocol + behavior), but in 3.x it changed to ``True`` due to the simple fact + that most remote servers are deployed with a restricted + ``AcceptEnv`` setting, making use of the protocol approach + non-viable. + + The actual default value is the value of the ``inline_ssh_env`` + :ref:`configuration value <default-values>` (which, as above, + currently defaults to ``True``). .. warning:: This functionality does **not** currently perform any shell @@ -366,11 +367,16 @@ .. versionchanged:: 2.3 Added the ``inline_ssh_env`` parameter. + + .. versionchanged:: 3.0 + ``inline_ssh_env`` still defaults to the config value, but said + config value has now changed and defaults to ``True``, not + ``False``. """ # NOTE: parent __init__ sets self._config; for now we simply overwrite # that below. If it's somehow problematic we would want to break parent # __init__ up in a manner that is more cleanly overrideable. - super(Connection, self).__init__(config=config) + super().__init__(config=config) #: The .Config object referenced when handling default values (for e.g. #: user or port, when not explicitly given) or deciding how to behave. @@ -486,7 +492,7 @@ # Make sure all are normalized to list as well! final_keys = [] for value in (config_keys, constructor_keys, ssh_config_keys): - if isinstance(value, string_types): + if isinstance(value, str): value = [value] final_keys.extend(value) # Only populate if non-empty. @@ -543,7 +549,7 @@ if self.gateway: # Displaying type because gw params would probs be too verbose val = "proxyjump" - if isinstance(self.gateway, string_types): + if isinstance(self.gateway, str): val = "proxycommand" bits.append(("gw", val)) return "<Connection {}>".format( @@ -648,7 +654,7 @@ .. versionadded:: 2.0 """ # ProxyCommand is faster to set up, so do it first. - if isinstance(self.gateway, string_types): + if isinstance(self.gateway, str): # Leverage a dummy SSHConfig to ensure %h/%p/etc are parsed. # TODO: use real SSH config once loading one properly is # implemented. @@ -680,10 +686,18 @@ """ Terminate the network connection to the remote end, if open. - If no connection is open, this method does nothing. + If any SFTP sessions are open, they will also be closed. + + If no connection or SFTP session is open, this method does nothing. .. versionadded:: 2.0 + .. versionchanged:: 3.0 + Now closes SFTP sessions too (2.x required manually doing so). """ + if self._sftp is not None: + self._sftp.close() + self._sftp = None + if self.is_connected: self.client.close() if self.forward_agent and self._agent_handler is not None: @@ -829,7 +843,7 @@ """ # Superclass run() uses runners.local, so we can literally just call it # straight. - return super(Connection, self).run(*args, **kwargs) + return super().run(*args, **kwargs) @opens def sftp(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/group.py new/fabric-3.0.1/fabric/group.py --- old/fabric-2.7.1/fabric/group.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/fabric/group.py 2023-01-21 00:13:54.000000000 +0100 @@ -1,7 +1,4 @@ -try: - from invoke.vendor.six.moves.queue import Queue -except ImportError: - from six.moves.queue import Queue +from queue import Queue from invoke.util import ExceptionHandlingThread @@ -180,9 +177,8 @@ .. versionadded:: 2.6 """ - # TODO: consider a backwards incompat change after we drop Py2 that - # just makes a lot of these kwarg-only methods? then below could become - # kwargs.setdefault() if desired. + # TODO 4.0: consider making many of these into kwarg-only methods? then + # below could become kwargs.setdefault() if desired. # TODO: do we care enough to handle explicitly given, yet falsey, # values? it's a lot more complexity for a corner case. if len(args) < 2 and "local" not in kwargs: @@ -309,7 +305,7 @@ """ def __init__(self, *args, **kwargs): - super(dict, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._successes = {} self._failures = {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/main.py new/fabric-3.0.1/fabric/main.py --- old/fabric-2.7.1/fabric/main.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/fabric/main.py 2023-04-29 19:40:23.000000000 +0200 @@ -16,12 +16,12 @@ class Fab(Program): def print_version(self): - super(Fab, self).print_version() + super().print_version() print("Paramiko {}".format(paramiko)) print("Invoke {}".format(invoke)) def core_args(self): - core_args = super(Fab, self).core_args() + core_args = super().core_args() my_args = [ Argument( names=("H", "hosts"), @@ -84,13 +84,13 @@ # honor the real "lives by task coll"? self.collection = Collection() else: - super(Fab, self).load_collection() + super().load_collection() def no_tasks_given(self): # As above, neuter the usual "hey you didn't give me any tasks, let me # print help for you" behavior, if necessary. if not self._remainder_only: - super(Fab, self).no_tasks_given() + super().no_tasks_given() def create_config(self): # Create config, as parent does, but with lazy=True to avoid our own @@ -112,7 +112,7 @@ # Note runtime SSH path, if given, and load SSH configurations. # NOTE: must do parent before our work, in case users want to disable # SSH config loading within a runtime-level conf file/flag. - super(Fab, self).update_config(merge=False) + super().update_config(merge=False) self.config.set_runtime_ssh_path(self.args["ssh-config"].value) self.config.load_ssh_config() # Load -i identity file, if given, into connect_kwargs, at overrides diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/runners.py new/fabric-3.0.1/fabric/runners.py --- old/fabric-2.7.1/fabric/runners.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/fabric/runners.py 2023-04-29 19:52:38.000000000 +0200 @@ -26,13 +26,16 @@ :param bool inline_env: Whether to 'inline' shell env vars as prefixed parameters, instead of trying to submit them via `.Channel.update_environment`. - Default:: ``False``. + Default: ``True``. .. versionchanged:: 2.3 Added the ``inline_env`` parameter. + .. versionchanged:: 3.0 + Changed the default value of ``inline_env`` from ``False`` to + ``True``. """ self.inline_env = kwargs.pop("inline_env", None) - super(Remote, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def start(self, command, shell, env, timeout=None): self.channel = self.context.create_session() @@ -69,7 +72,7 @@ def run(self, command, **kwargs): kwargs.setdefault("replace_env", True) - return super(Remote, self).run(command, **kwargs) + return super().run(command, **kwargs) def read_proc_stdout(self, num_bytes): return self.channel.recv(num_bytes) @@ -99,7 +102,7 @@ # Submit hex ASCII character 3, aka ETX, which most Unix PTYs # interpret as a foreground SIGINT. # TODO: is there anything else we can do here to be more portable? - self.channel.send(u"\x03") + self.channel.send("\x03") else: raise interrupt @@ -111,6 +114,7 @@ return Result(**kwargs) def stop(self): + super().stop() if hasattr(self, "channel"): self.channel.close() @@ -168,7 +172,7 @@ def __init__(self, **kwargs): connection = kwargs.pop("connection") - super(Result, self).__init__(**kwargs) + super().__init__(**kwargs) self.connection = connection # TODO: have useful str/repr differentiation from invoke.Result, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/tasks.py new/fabric-3.0.1/fabric/tasks.py --- old/fabric-2.7.1/fabric/tasks.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/fabric/tasks.py 2023-01-21 00:13:54.000000000 +0100 @@ -18,7 +18,7 @@ # Pull out our own kwargs before hitting super, which will TypeError on # anything it doesn't know about. self.hosts = kwargs.pop("hosts", None) - super(Task, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def task(*args, **kwargs): @@ -88,7 +88,7 @@ wrapped task is executed. Default: ``None``. """ init_kwargs = kwargs.pop("init_kwargs") # , None) - super(ConnectionCall, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.init_kwargs = init_kwargs def clone_kwargs(self): @@ -97,7 +97,7 @@ # without getting too crazy on the metaprogramming/over-engineering? # Maybe something attrs library can help with (re: declaring "These are # my bag-of-attributes attributes I want common stuff done to/with") - kwargs = super(ConnectionCall, self).clone_kwargs() + kwargs = super().clone_kwargs() kwargs["init_kwargs"] = self.init_kwargs return kwargs @@ -110,7 +110,7 @@ return Connection(**kwargs) def __repr__(self): - ret = super(ConnectionCall, self).__repr__() + ret = super().__repr__() if self.init_kwargs: ret = ret[:-1] + ", host='{}'>".format(self.init_kwargs["host"]) return ret diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/testing/base.py new/fabric-3.0.1/fabric/testing/base.py --- old/fabric-2.7.1/fabric/testing/base.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/fabric/testing/base.py 2023-01-21 00:13:54.000000000 +0100 @@ -2,9 +2,9 @@ This module contains helpers/fixtures to assist in testing Fabric-driven code. It is not intended for production use, and pulls in some test-oriented -dependencies such as `mock <https://pypi.org/project/mock/>`_. You can install -an 'extra' variant of Fabric to get these dependencies if you aren't already -using them for your own testing purposes: ``pip install fabric[testing]``. +dependencies as needed. You can install an 'extra' variant of Fabric to get +these dependencies if you aren't already using them for your own testing +purposes: ``pip install fabric[testing]``. .. note:: If you're using pytest for your test suite, you may be interested in @@ -19,20 +19,10 @@ from io import BytesIO import os -try: - from mock import Mock, PropertyMock, call, patch, ANY -except ImportError: - import warnings - - warning = ( - "You appear to be missing some optional test-related dependencies;" - "please 'pip install fabric[testing]'." - ) - warnings.warn(warning, ImportWarning) - raise +from unittest.mock import Mock, PropertyMock, call, patch, ANY -class Command(object): +class Command: """ Data record specifying params of a command execution to mock/expect. @@ -104,7 +94,7 @@ object.__setattr__(self, "__stderr", kwargs.pop("stderr")) # Stdin less private so it can be asserted about object.__setattr__(self, "_stdin", BytesIO()) - super(MockChannel, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _get_child_mock(self, **kwargs): # Don't return our own class on sub-mocks. @@ -120,7 +110,7 @@ return object.__getattribute__(self, "_stdin").write(data) -class Session(object): +class Session: """ A mock remote session of a single connection and 1 or more command execs. @@ -284,7 +274,7 @@ assert calls == session_opens -class MockRemote(object): +class MockRemote: """ Class representing mocked remote state. @@ -377,7 +367,7 @@ # TODO: unify with the stuff in paramiko itself (now in its tests/conftest.py), # they're quite distinct and really shouldn't be. -class MockSFTP(object): +class MockSFTP: """ Class managing mocked SFTP remote state. @@ -409,8 +399,8 @@ mock_os.path.abspath.side_effect = fake_abspath sftp.getcwd.return_value = "/remote" - # Ensure stat st_mode is a real number; Python 2 stat.S_IMODE doesn't - # appear to care if it's handed a MagicMock, but Python 3's does (?!) + # Ensure stat st_mode is a real number; Python 3's stat.S_IMODE doesn't + # like just being handed a MagicMock? fake_mode = 0o644 # arbitrary real-ish mode sftp.stat.return_value.st_mode = fake_mode mock_os.stat.return_value.st_mode = fake_mode diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/testing/fixtures.py new/fabric-3.0.1/fabric/testing/fixtures.py --- old/fabric-2.7.1/fabric/testing/fixtures.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/fabric/testing/fixtures.py 2023-01-21 00:13:54.000000000 +0100 @@ -15,9 +15,10 @@ .. versionadded:: 2.1 """ +from unittest.mock import patch, Mock + try: from pytest import fixture - from mock import patch, Mock except ImportError: import warnings @@ -31,10 +32,6 @@ from .. import Connection from ..transfer import Transfer -# TODO: if we find a lot of people somehow ending up _with_ pytest but -# _without_ mock and other deps from testing.base, consider doing the -# try/except here too. But, really? - from .base import MockRemote, MockSFTP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/transfer.py new/fabric-3.0.1/fabric/transfer.py --- old/fabric-2.7.1/fabric/transfer.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/fabric/transfer.py 2023-01-21 00:13:54.000000000 +0100 @@ -6,10 +6,7 @@ import posixpath import stat -try: - from pathlib import Path -except ImportError: - from pathlib2 import Path +from pathlib import Path from .util import debug # TODO: actual logging! LOL @@ -21,7 +18,7 @@ # course. -class Transfer(object): +class Transfer: """ `.Connection`-wrapping class responsible for managing file upload/download. @@ -326,7 +323,7 @@ ) -class Result(object): +class Result: """ A container for information about the result of a file transfer. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric/tunnels.py new/fabric-3.0.1/fabric/tunnels.py --- old/fabric-2.7.1/fabric/tunnels.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/fabric/tunnels.py 2023-01-21 00:13:54.000000000 +0100 @@ -5,7 +5,6 @@ see `.Connection`, e.g. `.Connection.forward_local`. """ -import errno import select import socket import time @@ -39,7 +38,7 @@ transport, finished, ): - super(TunnelManager, self).__init__() + super().__init__() self.local_address = (local_host, local_port) self.remote_address = (remote_host, remote_port) self.transport = transport @@ -68,12 +67,10 @@ tun_sock, local_addr = sock.accept() # Set TCP_NODELAY to match OpenSSH's forwarding socket behavior tun_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except socket.error as e: - if e.errno is errno.EAGAIN: - # TODO: make configurable - time.sleep(0.01) - continue - raise + except BlockingIOError: # ie errno.EAGAIN + # TODO: make configurable + time.sleep(0.01) + continue # Set up direct-tcpip channel on server end # TODO: refactor w/ what's used for gateways @@ -122,7 +119,7 @@ self.finished = finished self.socket_chunk_size = 1024 self.channel_chunk_size = 1024 - super(Tunnel, self).__init__() + super().__init__() def _run(self): try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric.egg-info/PKG-INFO new/fabric-3.0.1/fabric.egg-info/PKG-INFO --- old/fabric-2.7.1/fabric.egg-info/PKG-INFO 2022-07-15 00:39:03.000000000 +0200 +++ new/fabric-3.0.1/fabric.egg-info/PKG-INFO 2023-04-29 20:59:32.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: fabric -Version: 2.7.1 +Version: 3.0.1 Summary: High level SSH command execution Home-page: https://fabfile.org Author: Jeff Forcier @@ -57,13 +57,14 @@ Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: Microsoft :: Windows Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Build Tools Classifier: Topic :: Software Development :: Libraries diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric.egg-info/SOURCES.txt new/fabric-3.0.1/fabric.egg-info/SOURCES.txt --- old/fabric-2.7.1/fabric.egg-info/SOURCES.txt 2022-07-15 00:39:03.000000000 +0200 +++ new/fabric-3.0.1/fabric.egg-info/SOURCES.txt 2023-04-29 20:59:32.000000000 +0200 @@ -2,7 +2,6 @@ MANIFEST.in README.rst dev-requirements.txt -setup.cfg setup.py tasks.py fabric/__init__.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/fabric.egg-info/requires.txt new/fabric-3.0.1/fabric.egg-info/requires.txt --- old/fabric-2.7.1/fabric.egg-info/requires.txt 2022-07-15 00:39:03.000000000 +0200 +++ new/fabric-3.0.1/fabric.egg-info/requires.txt 2023-04-29 20:59:32.000000000 +0200 @@ -1,10 +1,7 @@ -invoke<2.0,>=1.3 +invoke>=2.0 paramiko>=2.4 -pathlib2 [pytest] -mock<3.0,>=2.0.0 -pytest<4.0,>=3.2.5 +pytest>=7 [testing] -mock<3.0,>=2.0.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/integration/concurrency.py new/fabric-3.0.1/integration/concurrency.py --- old/fabric-2.7.1/integration/concurrency.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/integration/concurrency.py 2023-01-21 00:13:54.000000000 +0100 @@ -1,7 +1,6 @@ import codecs - -from invoke.vendor.six.moves.queue import Queue -from invoke.vendor.six.moves import zip_longest +from itertools import zip_longest +from queue import Queue from invoke.util import ExceptionHandlingThread from pytest import skip @@ -85,7 +84,7 @@ while not queue.empty(): cxn, result, expected = queue.get(block=False) for resultword, expectedword in zip_longest(result, expected): - err = u"({2!r}, {3!r}->{4!r}) {0!r} != {1!r}".format( + err = "({2!r}, {3!r}->{4!r}) {0!r} != {1!r}".format( resultword, expectedword, cxn, expected[0], expected[-1] ) assert resultword == expectedword, err diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/integration/connection.py new/fabric-3.0.1/integration/connection.py --- old/fabric-2.7.1/integration/connection.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/integration/connection.py 2023-01-21 00:13:54.000000000 +0100 @@ -1,10 +1,7 @@ import os import time -try: - from invoke.vendor.six import StringIO -except ImportError: - from six import StringIO +from io import StringIO from invoke import pty_size, CommandTimedOut from invocations.environment import in_ci diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/setup.cfg new/fabric-3.0.1/setup.cfg --- old/fabric-2.7.1/setup.cfg 2022-07-15 00:39:03.000000000 +0200 +++ new/fabric-3.0.1/setup.cfg 2023-04-29 20:59:33.000000000 +0200 @@ -1,9 +1,3 @@ -[wheel] -universal = 1 - -[metadata] -license_file = LICENSE - [egg_info] tag_build = tag_date = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/setup.py new/fabric-3.0.1/setup.py --- old/fabric-2.7.1/setup.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/setup.py 2023-04-29 19:40:23.000000000 +0200 @@ -45,9 +45,6 @@ exec(fp.read(), None, _locals) version = _locals["__version__"] -testing_deps = ["mock>=2.0.0,<3.0"] -pytest_deps = ["pytest>=3.2.5,<4.0"] - setuptools.setup( name=package_name, version=version, @@ -65,10 +62,14 @@ "CI": "https://app.circleci.com/pipelines/github/fabric/fabric", "Twitter": "https://twitter.com/pyfabric", }, - install_requires=["invoke>=1.3,<2.0", "paramiko>=2.4", "pathlib2"], + python_requres=">=3.6", + install_requires=["invoke>=2.0", "paramiko>=2.4"], extras_require={ - "testing": testing_deps, - "pytest": testing_deps + pytest_deps, + # For folks who want to use fabric.testing package, eg + # MockRemote/MockSFTP + "testing": [], # no longer (for now?) needs anything special + # For folks who want to use fabric.testing.fixtures' pytest fixtures + "pytest": ["pytest>=7"], }, packages=packages, entry_points={ @@ -87,13 +88,14 @@ "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Topic :: Software Development", "Topic :: Software Development :: Build Tools", "Topic :: Software Development :: Libraries", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/sites/docs/concepts/configuration.rst new/fabric-3.0.1/sites/docs/concepts/configuration.rst --- old/fabric-2.7.1/sites/docs/concepts/configuration.rst 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/sites/docs/concepts/configuration.rst 2023-04-29 19:40:23.000000000 +0200 @@ -99,7 +99,7 @@ specified. Default: ``22``. - ``inline_ssh_env``: Boolean serving as global default for the value of `.Connection`'s ``inline_ssh_env`` parameter; see its docs for details. - Default: ``False``. + Default: ``True``. - ``ssh_config_path``: Runtime SSH config path; see :ref:`ssh-config`. Default: ``None``. - ``timeouts``: Various timeouts, specifically: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/sites/docs/conf.py new/fabric-3.0.1/sites/docs/conf.py --- old/fabric-2.7.1/sites/docs/conf.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/sites/docs/conf.py 2023-01-21 00:13:54.000000000 +0100 @@ -8,7 +8,16 @@ # Enable & configure autodoc extensions.append("sphinx.ext.autodoc") -autodoc_default_flags = ["members", "special-members"] +# Autodoc settings +autodoc_default_options = { + "members": True, + "special-members": True, +} +# TODO: consider documenting things like Remote.run usefully and +# re-enabling this? new as of sphinx 1.7 and NOT the old behavior, so very +# surprising in a bunch of spots right now, where it pulls in Invoke +# docstrings that then have bad refs and so on. +autodoc_inherit_docstrings = False # Default is 'local' building, but reference the public WWW site when building # under RTD. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/sites/docs/getting-started.rst new/fabric-3.0.1/sites/docs/getting-started.rst --- old/fabric-2.7.1/sites/docs/getting-started.rst 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/sites/docs/getting-started.rst 2023-01-21 00:13:54.000000000 +0100 @@ -191,8 +191,7 @@ .. testsetup:: sudo - from __future__ import print_function - from mock import patch + from unittest.mock import patch gp_patcher = patch('getpass.getpass', side_effect=lambda x: print(x)) gp_patcher.start() mock = MockRemote() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/sites/shared_conf.py new/fabric-3.0.1/sites/shared_conf.py --- old/fabric-2.7.1/sites/shared_conf.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/sites/shared_conf.py 2023-01-21 00:13:54.000000000 +0100 @@ -69,8 +69,7 @@ # Regular settings project = "Fabric" -year = datetime.now().year -copyright = "%d Jeff Forcier" % year +copyright = f"{datetime.now().year} Jeff Forcier" master_doc = "index" templates_path = ["_templates"] exclude_trees = ["_build"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/sites/www/changelog-v1.rst new/fabric-3.0.1/sites/www/changelog-v1.rst --- old/fabric-2.7.1/sites/www/changelog-v1.rst 2022-07-15 00:38:45.000000000 +0200 +++ new/fabric-3.0.1/sites/www/changelog-v1.rst 2023-01-21 00:13:54.000000000 +0100 @@ -6,6 +6,35 @@ This is the changelog for the legacy 1.x version of Fabric. For the current (2.0+) changelog, please see :doc:`the main changelog </changelog>`. +* :release:`1.15.0 <2022-04-07>` +* :support:`-` Merge the longstanding ``fabric3`` fork back into our v1 branch + so users who'd rather port Fabric 1.x code to Python 3 before upgrading to + Fabric 2.x, are able to do so in a "blessed" manner. + + This change includes making sure that the delta between the fork and our v1 + branch still functions correctly & passes tests on both interpreters. It also + includes a basic CircleCI configuration to test on 3.6, 3.7 and 3.8, not that + we expect to be hosting many future commits on this side... + + Major major thanks to Mathias Ertl for his work on the fork, all the + contributors on his side of the house during that time, and to Zachary Vance + for getting the reconciliation process rolling. + + The changes folded in as part of this work (mostly taken from Mathias' + changelog) are as follows: + + - Installation now requires Paramiko 1.17.0 or later. + - Fix ``UnicodeDecodeError`` when receiving remote data. + - Clean up imports in main code base and test suite. + - Add Python 2/3/3.5 classifiers in ``setup.py``. + - Replace ``fabric.utils.RingBuffer`` with ``collections.deque`` from stdlib. + - Under Python 3, Fabric implements its own version of ``contextlib.nested`` + based on ``contextlib.ExitStack``, since it's no longer available in + Python3. + + - Please note that it was removed with good reason, we do not encourage + you use it. + * :release:`1.14.1 <2018-11-27>` * :bug:`1341` (via :issue:`1586`) Attempt to ``rm -f`` the temporary file used by ``put``'s sudo mode, when exceptions are encountered; previously, the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/sites/www/changelog.rst new/fabric-3.0.1/sites/www/changelog.rst --- old/fabric-2.7.1/sites/www/changelog.rst 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/sites/www/changelog.rst 2023-04-29 20:58:49.000000000 +0200 @@ -13,6 +13,33 @@ Click those projects' names in this paragraph to visit their changelogs and see what you might get if you upgrade your dependencies. +- :release:`3.0.1 <2023-04-29>` +- :bug:`2241` A typo prevented Fabric's command runner from properly calling + its superclass ``stop()`` method, which in tandem with a related Invoke bug + meant messy or long shutdowns in many scenarios. Thanks to Orlando + RodrÃguez for report and initial patch. +- :release:`3.0.0 <2023-01-20>` +- :bug:`1981 major` (fixed in :issue:`2195`) Automatically close any open SFTP + session during `fabric.connection.Connection.close`; this avoids issues + encountered upon re-opening a previously-closed connection object. Thanks to + Alexander Bodnya for the report and David JM Emmett for the patch. +- :feature:`-` Change the default configuration value for ``inline_ssh_env`` + from ``False`` to ``True``, to better align with the practicalities of common + SSH server configurations. + + .. warning:: + This change is backwards incompatible if you were using + environment-variable-setting kwargs or config settings, such as + ``Connection.run(command, env={'SOME': 'ENV VARS'})``, and were not already + explicitly specifying the value of ``inline_ssh_env``. + +- :support:`-` Drop support for Python <3.6, including Python 2. + + .. warning:: + This is a backwards incompatible change if you are not yet on Python 3.6 or + above; however, pip shouldn't offer you this version of Fabric as long as + your pip version understands ``python_requires`` metadata. + - :release:`2.7.1 <2022-07-14>` - :bug:`1924` (also :issue:`2007`) Overhaul behavior and testing re: merging together different sources for the ``key_filename`` parameter in diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/sites/www/upgrading.rst new/fabric-3.0.1/sites/www/upgrading.rst --- old/fabric-2.7.1/sites/www/upgrading.rst 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/sites/www/upgrading.rst 2023-01-21 00:13:54.000000000 +0100 @@ -36,7 +36,6 @@ These are all listed in the rest of the doc too, so if you're already sold, just skip there. -- Python 3 compatibility (specifically, we now support 2.7 and 3.4+); - Thread-safe - no more requirement on multiprocessing for concurrency; - API reorganized around `fabric.connection.Connection` objects instead of global module state; @@ -195,7 +194,7 @@ instead, then supply it to the ``connect_kwargs`` parameter. For example:: - from io import StringIO # or 'from StringIO' on Python 2 + from io import StringIO from fabric.state import env from fabric2 import Connection from paramiko import RSAKey @@ -282,9 +281,6 @@ General / conceptual -------------------- -- Modern Fabric is fully Python 3 compatible; as a cost, Python 2.5 support (a - longstanding feature of Fabric 1) has been dropped - in fact, we've dropped - support for anything older than Python 2.7. - The CLI task-oriented workflow remains a primary design goal, but the library use case is no longer a second-class citizen; instead, the library functionality has been designed first, with the CLI/task features built on diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tasks.py new/fabric-3.0.1/tasks.py --- old/fabric-2.7.1/tasks.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/tasks.py 2023-01-21 00:13:54.000000000 +0100 @@ -1,4 +1,4 @@ -from os import environ, getcwd +from os import getcwd import sys from invocations import ci @@ -21,13 +21,6 @@ Assumes Fabric 2+ is already installed as 'fabric2'. """ - # This cannot, by definition, work under Python 3 as Fabric 1 is not Python - # 3 compatible. - # TODO: once the final Fabric 1 release is out w/ 3.x compat, fix this up - # and add to CI - PYTHON = environ.get("TRAVIS_PYTHON_VERSION", "") - if PYTHON.startswith("3") or PYTHON == "pypy3": - return c.run("pip install 'fabric<2'") # Make darn sure the two copies of fabric are coming from install root, not # local directory - which would result in 'fabric' always being v2! diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/config.py new/fabric-3.0.1/tests/config.py --- old/fabric-2.7.1/tests/config.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/tests/config.py 2023-01-21 00:13:54.000000000 +0100 @@ -8,7 +8,7 @@ from fabric import Config, Remote, RemoteShell from fabric.util import get_local_user -from mock import patch, call +from unittest.mock import patch, call from _util import support, faux_v1_env @@ -47,7 +47,7 @@ assert c.connect_kwargs == {} assert c.timeouts.connect is None assert c.ssh_config_path is None - assert c.inline_ssh_env is False + assert c.inline_ssh_env is True def overrides_some_Invoke_defaults(self): config = Config() @@ -235,11 +235,12 @@ def runtime_path_does_not_die_silently(self): try: Config(runtime_ssh_path="sure/thing/boss/whatever/you/say") - except IOError as e: + except FileNotFoundError as e: assert "No such file or directory" in str(e) assert e.errno == errno.ENOENT + assert e.filename == "sure/thing/boss/whatever/you/say" else: - assert False, "Bad runtime path didn't raise IOError!" + assert False, "Bad runtime path didn't raise error!" # TODO: skip on windows @patch.object(Config, "_load_ssh_file") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/conftest.py new/fabric-3.0.1/tests/conftest.py --- old/fabric-2.7.1/tests/conftest.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/tests/conftest.py 2023-01-21 00:13:54.000000000 +0100 @@ -5,7 +5,7 @@ from pytest import fixture -from mock import patch +from unittest.mock import patch # TODO: does this want to end up in the public fixtures module too? diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/connection.py new/fabric-3.0.1/tests/connection.py --- old/fabric-2.7.1/tests/connection.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/tests/connection.py 2023-04-29 19:40:23.000000000 +0200 @@ -1,16 +1,13 @@ from itertools import chain, repeat -try: - from invoke.vendor.six import b, StringIO -except ImportError: - from six import b, StringIO +from io import StringIO import errno from os.path import join import socket import time -from mock import patch, Mock, call, ANY +from unittest.mock import patch, Mock, call, ANY from paramiko.client import SSHClient, AutoAddPolicy from paramiko import SSHConfig import pytest # for mark, internal raises @@ -506,14 +503,16 @@ class inline_ssh_env: def defaults_to_config_value(self): - assert Connection("host").inline_ssh_env is False - config = Config({"inline_ssh_env": True}) - assert Connection("host", config=config).inline_ssh_env is True + assert Connection("host").inline_ssh_env is True + config = Config({"inline_ssh_env": False}) + assert ( + Connection("host", config=config).inline_ssh_env is False + ) def may_be_given(self): - assert Connection("host").inline_ssh_env is False - cxn = Connection("host", inline_ssh_env=True) - assert cxn.inline_ssh_env is True + assert Connection("host").inline_ssh_env is True + cxn = Connection("host", inline_ssh_env=False) + assert cxn.inline_ssh_env is False class from_v1: def setup(self): @@ -546,11 +545,11 @@ cxn = Connection.from_v1( self.env, connect_kwargs={"foo": "bar"}, - inline_ssh_env=True, + inline_ssh_env=False, connect_timeout=15, ) assert cxn.connect_kwargs["foo"] == "bar" - assert cxn.inline_ssh_env is True + assert cxn.inline_ssh_env is False assert cxn.connect_timeout == 15 def conflicting_kwargs_win_over_v1_env_values(self): @@ -962,6 +961,24 @@ c.close() client.close.assert_called_with() + def calls_SFTPClient_close(self, client): + "calls paramiko.SFTPClient.close()" + c = Connection("host") + c.open() + sftp_client = c.sftp() + assert c._sftp is not None + c.close() + assert c._sftp is None + sftp_client.close.assert_called_with() + + def calls_SFTPClient_close_not_called_if_not_open(self, client): + "calls paramiko.SFTPClient.close()" + c = Connection("host") + c.open() + assert c._sftp is None + c.close() + assert c._sftp is None + @patch("fabric.connection.AgentRequestHandler") def calls_agent_handler_close_if_enabled(self, Handler, client): c = Connection("host", forward_agent=True) @@ -1013,9 +1030,9 @@ @patch(remote_path) def passes_inline_env_to_Remote(self, Remote, client): Connection("host").run("command") - assert Remote.call_args[1]["inline_env"] is False - Connection("host", inline_ssh_env=True).run("command") assert Remote.call_args[1]["inline_env"] is True + Connection("host", inline_ssh_env=False).run("command") + assert Remote.call_args[1]["inline_env"] is False @patch(remote_path) def calls_Remote_run_with_command_and_kwargs_and_returns_its_result( @@ -1029,7 +1046,7 @@ # .assert_called_with()) stopped working, apparently triggered by # our code...somehow...after commit (roughly) 80906c7. # And yet, .call_args_list and its brethren work fine. Wha? - Remote.assert_any_call(context=c, inline_env=False) + Remote.assert_any_call(context=c, inline_env=True) remote.run.assert_has_calls( [call("command"), call("command", warn=True, hide="stderr")] ) @@ -1120,9 +1137,9 @@ @patch(remote_path) def passes_inline_env_to_Remote(self, Remote, client): Connection("host").sudo("command") - assert Remote.call_args[1]["inline_env"] is False - Connection("host", inline_ssh_env=True).sudo("command") assert Remote.call_args[1]["inline_env"] is True + Connection("host", inline_ssh_env=False).sudo("command") + assert Remote.call_args[1]["inline_env"] is False @patch(remote_path) def basic_invocation(self, Remote, client): @@ -1136,7 +1153,7 @@ # Remote.return_value is two different Mocks now, despite Remote's # own Mock having the same ID here and in code under test. WTF!!) expected = [ - call(context=cxn, inline_env=False), + call(context=cxn, inline_env=True), call().run(cmd, watchers=ANY), ] assert Remote.mock_calls == expected @@ -1213,7 +1230,7 @@ listener_sock = Mock(name="listener_sock") if listener_exception: listener_sock.bind.side_effect = listener_exception - data = b("Some data") + data = "Some data".encode() tunnel_sock = Mock(name="tunnel_sock", recv=lambda n: data) local_addr = Mock() transport = client.get_transport.return_value @@ -1224,6 +1241,7 @@ # fire once & raise EAGAIN after) listener_sock.accept.side_effect = chain( [(tunnel_sock, local_addr)], + # TODO: should this become BlockingIOError too? repeat(socket.error(errno.EAGAIN, "nothing yet")), ) obj = tunnel_sock if tunnel_exception is None else tunnel_exception diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/executor.py new/fabric-3.0.1/tests/executor.py --- old/fabric-2.7.1/tests/executor.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/tests/executor.py 2023-01-21 00:13:54.000000000 +0100 @@ -4,7 +4,7 @@ from fabric.executor import ConnectionCall from fabric.exceptions import NothingToDo -from mock import Mock +from unittest.mock import Mock from pytest import skip, raises # noqa diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/group.py new/fabric-3.0.1/tests/group.py --- old/fabric-2.7.1/tests/group.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/tests/group.py 2023-01-21 00:13:54.000000000 +0100 @@ -1,4 +1,4 @@ -from mock import Mock, patch, call +from unittest.mock import Mock, patch, call from pytest import mark, raises from fabric import Connection, Group, SerialGroup, ThreadingGroup, GroupResult @@ -222,9 +222,7 @@ ("start", Thread.return_value.start.call_count), ("join", Thread.return_value.join.call_count), ): - err = ( - "Expected {} calls to ExceptionHandlingThread.{}, got {}" - ) # noqa + err = "Expected {} calls to ExceptionHandlingThread.{}, got {}" # noqa err = err.format(expected, name, got) assert expected, got == err diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/main.py new/fabric-3.0.1/tests/main.py --- old/fabric-2.7.1/tests/main.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/tests/main.py 2023-04-29 19:40:23.000000000 +0200 @@ -8,7 +8,7 @@ from invoke import run from invoke.util import cd -from mock import patch +from unittest.mock import patch import pytest # because WHY would you expose @skip normally? -_- from pytest_relaxed import raises diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/runners.py new/fabric-3.0.1/tests/runners.py --- old/fabric-2.7.1/tests/runners.py 2022-07-15 00:37:01.000000000 +0200 +++ new/fabric-3.0.1/tests/runners.py 2023-04-29 19:52:38.000000000 +0200 @@ -1,12 +1,9 @@ -try: - from invoke.vendor.six import StringIO -except ImportError: - from six import StringIO +from io import StringIO -from mock import Mock, patch +from unittest.mock import Mock, patch from pytest import skip # noqa -from invoke import pty_size, Result +from invoke import pty_size, Result, Runner from fabric import Config, Connection, Remote, RemoteShell @@ -93,6 +90,12 @@ else: assert False, "Runner failed to raise exception!" + def stop_calls_super_correctly(self, remote): + # RE: #2241 + Runner.stop = Mock() + _runner().run(CMD) + Runner.stop.assert_called_once_with() + def channel_close_skipped_when_channel_not_even_made(self): # I.e. if obtaining self.channel doesn't even happen (i.e. if # Connection.create_session() dies), we need to account for that diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/task.py new/fabric-3.0.1/tests/task.py --- old/fabric-2.7.1/tests/task.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/tests/task.py 2023-01-21 00:13:54.000000000 +0100 @@ -1,6 +1,6 @@ # NOTE: named task.py, not tasks.py, to avoid some occasional pytest weirdness -from mock import Mock +from unittest.mock import Mock from pytest import skip # noqa import fabric @@ -134,7 +134,5 @@ ) # TODO: worth using some subset of real Connection repr() in here? # For now, just stick with hostname. - expected = ( - "<ConnectionCall '_dummy', args: (), kwargs: {}, host='host'>" - ) # noqa + expected = "<ConnectionCall '_dummy', args: (), kwargs: {}, host='host'>" # noqa assert str(call) == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/transfer.py new/fabric-3.0.1/tests/transfer.py --- old/fabric-2.7.1/tests/transfer.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/tests/transfer.py 2023-01-21 00:13:54.000000000 +0100 @@ -1,9 +1,6 @@ -try: - from invoke.vendor.six import StringIO -except ImportError: - from six import StringIO +from io import StringIO -from mock import Mock, call, patch +from unittest.mock import Mock, call, patch from pytest_relaxed import raises from pytest import skip # noqa from paramiko import SFTPAttributes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fabric-2.7.1/tests/util.py new/fabric-3.0.1/tests/util.py --- old/fabric-2.7.1/tests/util.py 2021-12-05 00:24:42.000000000 +0100 +++ new/fabric-3.0.1/tests/util.py 2023-01-21 00:13:54.000000000 +0100 @@ -2,7 +2,7 @@ Tests testing the fabric.util module, not utils for the tests! """ -from mock import patch +from unittest.mock import patch from fabric.util import get_local_user
