"""Detects whether or not an argument list invokes a Python program."""
return args[0] == "python" or args[0] == "wizard"
-def drop_priviledges(dir, options):
+def drop_priviledges(dir, log_file):
"""
Checks if we are running as root. If we are, attempt to drop
priviledges to the user who owns ``dir``, by re-calling
itself using sudo with exec, such that the new process subsumes our
- current one.
+ current one. If ``log_file`` is passed, the file is chown'ed
+ to the user we are dropping priviledges to, so the subprocess
+ can write to it.
"""
if os.getuid():
return
args.append("%s=%s" % (k,v))
args += sys.argv
logging.debug("Dropping priviledges")
- if options.log_file: os.chown(options.log_file, uid, -1)
+ if log_file: os.chown(log_file, uid, -1)
os.execlp('sudo', 'sudo', '-u', '#' + str(uid), *args)
class Shell(object):
>>> sh.call("cat", input='Foobar')
('Foobar', '')
"""
+ if hasattr(self, "_wait"):
+ self._wait()
kwargs.setdefault("interactive", False)
kwargs.setdefault("strip", False)
kwargs.setdefault("python", None)
with ``max`` subprocesses, and result in callback execution
when they finish.
- Before enqueueing a system call with :meth:`call` or :meth:`callAsUser`,
- you should wait for an open slot using :meth:`wait`; otherwise,
- ``max`` rate limiting will have no effect. For example::
-
- sh = ParallelShell()
- for command in commands_to_execute_in_parallel:
- sh.wait()
- sh.call(*command)
- sh.join()
-
.. method:: call(*args, **kwargs)
- Enqueues a system call for parallel processing. Keyword arguments
+ Enqueues a system call for parallel processing. If there are
+ no openings in the queue, this will block. Keyword arguments
are the same as :meth:`Shell.call` with the following additions:
:param on_success: Callback function for success (zero exit status).
super(ParallelShell, self).__init__(dry=dry)
self.running = {}
self.max = max # maximum of commands to run in parallel
+ @staticmethod
+ def make(no_parallelize, max):
+ """Convenience method oriented towards command modules."""
+ if no_parallelize:
+ return DummyParallelShell()
+ else:
+ return ParallelShell(max=max)
def _async(self, proc, args, python, on_success, on_error, **kwargs):
"""
Gets handed a :class:`subprocess.Proc` object from our deferred
execution. See :meth:`Shell.call` source code for details.
"""
self.running[proc.pid] = (proc, args, python, on_success, on_error)
- def wait(self):
+ def _wait(self):
"""
- Blocking call that waits for an open subprocess slot. You should
- call this before enqueuing.
-
- .. note::
-
- This method may become unnecessary in the future.
+ Blocking call that waits for an open subprocess slot. This is
+ automatically called by :meth:`Shell.call`.
"""
# XXX: This API sucks; the actuall call/callAsUser call should
# probably block automatically (unless I have a good reason not to)