commit 949e59ffcf2eb09495ec7b42672598af5e0bb656 Author: Damian Johnson atagar@torproject.org Date: Thu Jan 28 09:20:30 2016 -0800
Have get_connections() resolve the pid if not provided with one
Three of our connection resolvers require a pid to function. When provided with a process name instead we raised a ValueError, but we can at least *try* to resolve the name to a pid. If unsuccessful we now raise an IOError. Thanks to toralf for suggesting this change. --- stem/util/connection.py | 20 ++++++++++++++------ test/unit/manual.py | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/stem/util/connection.py b/stem/util/connection.py index cbc6ac2..e72bd12 100644 --- a/stem/util/connection.py +++ b/stem/util/connection.py @@ -166,14 +166,16 @@ def get_connections(resolver, process_pid = None, process_name = None): :returns: **list** of :class:`~stem.util.connection.Connection` instances
:raises: - * **ValueError** if using **Resolver.PROC** or **Resolver.BSD_PROCSTAT** - and the process_pid wasn't provided + * **ValueError** if neither a process_pid nor process_name is provided
* **IOError** if no connections are available or resolution fails (generally they're indistinguishable). The common causes are the command being unavailable or permissions. """
+ if not process_pid and not process_name: + raise ValueError('You must provide a pid or process name to provide connections for') + def _log(msg): if LOG_CONNECTION_RESOLUTION: log.debug(msg) @@ -187,11 +189,17 @@ def get_connections(resolver, process_pid = None, process_name = None): except ValueError: raise ValueError('Process pid was non-numeric: %s' % process_pid)
- if process_pid is None and process_name and resolver == Resolver.NETSTAT_WINDOWS: - process_pid = stem.util.system.pid_by_name(process_name) + if process_pid is None: + all_pids = stem.util.system.pid_by_name(process_name, True)
- if process_pid is None and resolver in (Resolver.NETSTAT_WINDOWS, Resolver.PROC, Resolver.BSD_PROCSTAT): - raise ValueError('%s resolution requires a pid' % resolver) + if len(all_pids) == 0: + if resolver in (Resolver.NETSTAT_WINDOWS, Resolver.PROC, Resolver.BSD_PROCSTAT): + raise IOError("Unable to determine the pid of '%s'. %s requires the pid to provide the connections." % (process_name, resolver)) + elif len(all_pids) == 1: + process_pid = all_pids[0] + else: + if resolver in (Resolver.NETSTAT_WINDOWS, Resolver.PROC, Resolver.BSD_PROCSTAT): + raise IOError("There's multiple processes named '%s'. %s requires a single pid to provide the connections." % (process_name, resolver))
if resolver == Resolver.PROC: return [Connection(*conn) for conn in stem.util.proc.connections(process_pid)] diff --git a/test/unit/manual.py b/test/unit/manual.py index 8711fb7..99628b0 100644 --- a/test/unit/manual.py +++ b/test/unit/manual.py @@ -238,7 +238,7 @@ class TestManual(unittest.TestCase): @patch('tempfile.mkdtemp', Mock(return_value = '/no/such/path')) @patch('shutil.rmtree', Mock()) @patch('stem.manual.open', Mock(return_value = io.BytesIO()), create = True) - @patch('stem.util.system.call', Mock(side_effect = OSError('call failed'))) + @patch('stem.util.system.call', Mock(side_effect = stem.util.system.CallError('call failed', 'a2x -f manpage /no/such/path/tor.1.txt', 1, None, None, 'call failed'))) @patch('stem.util.system.is_available', Mock(return_value = True)) @patch(URL_OPEN, Mock(return_value = io.BytesIO(b'test content'))) def test_download_man_page_when_a2x_fails(self):