* ubuntutools.subprocess:

- New drop-in replacement wrapper module around subprocess that
    backports the restore_signals kwarg and defaults close_fds=True
  - Switch everything previously using subprocess to use
    ubuntutools.subprocess instead (LP: #785854)
This commit is contained in:
Evan Broder 2011-06-24 16:32:07 +02:00 committed by Stefano Rivera
commit 19c33e5e32
21 changed files with 141 additions and 38 deletions

View File

@ -24,12 +24,13 @@
# This script is used to check if a package and all its build
# dependencies are in main or not.
import subprocess
import sys
import apt_pkg
import apt
from ubuntutools import subprocess
def process_deps(cache, deps):
"""Takes a list of (build) dependencies and processes it."""

View File

@ -22,7 +22,6 @@ import getopt
import lazr.restfulclient
import os
import re
import subprocess
import sys
import logging
import glob
@ -31,6 +30,7 @@ import fnmatch
from launchpadlib.launchpad import Launchpad
from ubuntutools.config import UDTConfig
from ubuntutools import subprocess
COMMAND_LINE_SYNTAX_ERROR = 1
VERSION_DETECTION_FAILED = 2

View File

@ -21,7 +21,6 @@
import optparse
import os
import shutil
import subprocess
import sys
import tempfile
@ -39,6 +38,7 @@ from ubuntutools.builder import get_builder
from ubuntutools.misc import system_distribution, vendor_to_distroinfo, \
codename_to_distribution
from ubuntutools.question import YesNoQuestion
from ubuntutools import subprocess
def error(msg):
Logger.error(msg)

24
debian/changelog vendored
View File

@ -9,6 +9,11 @@ ubuntu-dev-tools (0.126) UNRELEASED; urgency=low
* backportpackage, doc/backportpackage.1: Accept codenames from any
distribution in the parenting chain. Makes it possible to, e.g.,
backport from Debian. (LP: #703099)
* ubuntutools.subprocess:
- New drop-in replacement wrapper module around subprocess that
backports the restore_signals kwarg and defaults close_fds=True
- Switch everything previously using subprocess to use
ubuntutools.subprocess instead (LP: #785854)
-- Evan Broder <evan@ebroder.net> Sat, 11 Jun 2011 05:11:23 -0700
@ -46,25 +51,6 @@ ubuntu-dev-tools (0.125ubuntu1) oneiric; urgency=low
-- Didier Roche <didrocks@ubuntu.com> Fri, 24 Jun 2011 11:50:17 +0200
ubuntu-dev-tools (0.124) unstable; urgency=low
[ Benjamin Drung ]
* Move add-patch, edit-patch, suspicious-source, what-patch, and wrap-and-sort
from ubuntu-dev-tools into devscripts (Closes: #568481).
[ Daniel Holbach ]
* bitesize:
- display error message properly (LP: #785973).
- error out if bug is already marked as 'bitesize'.
- rephrase bug comment and subscribe person who adds the comment.
- work-around LP:336866 and LP:254901.
[ Stefano Rivera ]
* mk-sbuild:
- maintainer_name isn't mandatory any more (LP: #787051)
-- Benjamin Drung <bdrung@debian.org> Wed, 25 May 2011 18:27:46 +0200
ubuntu-dev-tools (0.123) unstable; urgency=low
[ Stefano Rivera ]

3
dgetlp
View File

@ -32,7 +32,6 @@ import email.feedparser
import hashlib
import optparse
import os
import subprocess
import sys
import urllib2
@ -43,6 +42,8 @@ except ImportError:
"use this utility.")
sys.exit(1)
from ubuntutools import subprocess
USAGE = u"""Usage: %prog [-d|(-v|-q)] <Launchpad URL>
This scripts simulates «dget»'s behaviour for files hosted at

View File

@ -25,10 +25,10 @@
#
import os
import subprocess
import sys
from optparse import OptionParser
from ubuntutools.lp.lpapicache import PersonTeam
from ubuntutools import subprocess
def main():
usage = "Usage: %prog [-d <directory>] -t <team> [-o <operation>]"

View File

@ -25,7 +25,6 @@
from optparse import OptionParser, SUPPRESS_HELP
import re
import sys
import subprocess
try:
import SOAPpy
@ -37,6 +36,7 @@ except ImportError:
from launchpadlib.launchpad import Launchpad
from ubuntutools.config import UDTConfig
from ubuntutools import subprocess
def main():
bug_re = re.compile(r"bug=(\d+)")

View File

@ -22,13 +22,14 @@
import datetime
import os
import subprocess
import sys
import tempfile
from launchpadlib.launchpad import Launchpad
from launchpadlib.errors import HTTPError
from ubuntutools import subprocess
def create_release(project, version):
'''Create new release and milestone for LP project.'''

View File

@ -30,13 +30,13 @@
# that the target distribution is always meant to be Ubuntu Hardy.
import os
import subprocess
import sys
from devscripts.logger import Logger
from ubuntutools.distro_info import DebianDistroInfo
import ubuntutools.misc
from ubuntutools import subprocess
class PbuilderDist:
def __init__(self, builder):

View File

@ -25,7 +25,6 @@ import debian.debian_support
import optparse
import os
import shutil
import subprocess
import sys
from devscripts.logger import Logger
@ -38,6 +37,7 @@ from ubuntutools.requestsync.mail import (getDebianSrcPkg
from ubuntutools.requestsync.lp import getDebianSrcPkg, getUbuntuSrcPkg
from ubuntutools.lp import udtexceptions
from ubuntutools.lp.lpapicache import Launchpad
from ubuntutools import subprocess
class Version(debian.debian_support.Version):

View File

@ -21,7 +21,8 @@
# ##################################################################
import sys
import subprocess
from ubuntutools import subprocess
def extract(iso, path):
command = ['isoinfo', '-R', '-i', iso, '-x', path]

View File

@ -31,7 +31,6 @@ from __future__ import with_statement
import hashlib
import os.path
import subprocess
import urllib2
import urlparse
import re
@ -45,6 +44,7 @@ from devscripts.logger import Logger
from ubuntutools.config import UDTConfig
from ubuntutools.lp.lpapicache import (Launchpad, Distribution,
SourcePackagePublishingHistory)
from ubuntutools import subprocess
class DownloadError(Exception):
"Unable to pull a source package"

View File

@ -19,9 +19,9 @@
#
import os
import subprocess
from devscripts.logger import Logger
from ubuntutools import subprocess
def _build_preparation(result_directory):
"""prepares the builder for building a package"""

View File

@ -26,11 +26,11 @@
import locale
import os
import os.path
from subprocess import Popen, PIPE
import sys
from ubuntutools import distro_info
from ubuntutools.lp.udtexceptions import PocketDoesNotExistError
from ubuntutools.subprocess import Popen, PIPE
_system_distribution_chain = []
def system_distribution_chain():

View File

@ -24,9 +24,10 @@ import sys
import urllib2
import re
import tempfile
import subprocess
from debian.changelog import Changelog
from ubuntutools import subprocess
def raw_input_exit_on_ctrlc(*args, **kwargs):
'''
A wrapper around raw_input() to exit with a normalized message on Control-C

View File

@ -22,13 +22,13 @@
import os
import sys
import subprocess
import smtplib
import socket
from debian.changelog import Version
from ubuntutools.archive import rmadison, FakeSPPH
from ubuntutools.distro_info import DebianDistroInfo
from ubuntutools.requestsync.common import raw_input_exit_on_ctrlc
from ubuntutools import subprocess
from ubuntutools.lp.udtexceptions import PackageNotFoundException
__all__ = [

View File

@ -16,7 +16,8 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import os
import subprocess
from ubuntutools import subprocess
class Patch(object):
def __init__(self, patch_file):

View File

@ -19,7 +19,6 @@ import os
import pwd
import re
import shutil
import subprocess
import sys
import debian.changelog
@ -28,6 +27,7 @@ import launchpadlib.launchpad
from devscripts.logger import Logger
from ubuntutools import subprocess
from ubuntutools.update_maintainer import update_maintainer
from ubuntutools.question import Question, YesNoQuestion, input_number

109
ubuntutools/subprocess.py Normal file
View File

@ -0,0 +1,109 @@
"""Drop-in replacement for subprocess with better defaults
This is an API-compatible replacement for the built-in subprocess
module whose defaults better line up with our tastes.
In particular, it:
- Adds support for the restore_signals flag if subprocess itself
doesn't support it
- Defaults close_fds to True
"""
from __future__ import absolute_import
import inspect
import signal
import subprocess
from subprocess import PIPE, STDOUT, CalledProcessError
__all__ = ['Popen', 'call', 'check_call', 'check_output', 'CalledProcessError', 'PIPE', 'STDOUT']
class Popen(subprocess.Popen):
def __init__(self, *args, **kwargs):
kwargs.setdefault('close_fds', True)
if 'restore_signals' not in inspect.getargspec(subprocess.Popen.__init__)[0]:
given_preexec_fn = kwargs.pop('preexec_fn', None)
restore_signals = kwargs.pop('restore_signals', True)
def preexec_fn():
if restore_signals:
for sig in ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ'):
if hasattr(signal, sig):
signal.signal(getattr(signal, sig),
signal.SIG_DFL)
if given_preexec_fn:
given_preexec_fn()
kwargs['preexec_fn'] = preexec_fn
subprocess.Popen.__init__(self, *args, **kwargs)
# call, check_call, and check_output are copied directly from the
# subprocess module shipped with Python 2.7.1-5ubuntu2
def call(*popenargs, **kwargs):
"""Run command with arguments. Wait for command to complete, then
return the returncode attribute.
The arguments are the same as for the Popen constructor. Example:
retcode = call(["ls", "-l"])
"""
return Popen(*popenargs, **kwargs).wait()
def check_call(*popenargs, **kwargs):
"""Run command with arguments. Wait for command to complete. If
the exit code was zero then return, otherwise raise
CalledProcessError. The CalledProcessError object will have the
return code in the returncode attribute.
The arguments are the same as for the Popen constructor. Example:
check_call(["ls", "-l"])
"""
retcode = call(*popenargs, **kwargs)
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise CalledProcessError(retcode, cmd)
return 0
def check_output(*popenargs, **kwargs):
r"""Run command with arguments and return its output as a byte string.
If the exit code was non-zero it raises a CalledProcessError. The
CalledProcessError object will have the return code in the returncode
attribute and output in the output attribute.
The arguments are the same as for the Popen constructor. Example:
>>> check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
The stdout argument is not allowed as it is used internally.
To capture standard error in the result, use stderr=STDOUT.
>>> check_output(["/bin/sh", "-c",
... "ls -l non_existent_file ; exit 0"],
... stderr=STDOUT)
'ls: non_existent_file: No such file or directory\n'
"""
if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.')
process = Popen(stdout=PIPE, *popenargs, **kwargs)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise CalledProcessError(retcode, cmd, output=output)
return output

View File

@ -18,10 +18,10 @@ import fcntl
import os
import select
import signal
import subprocess
import time
import setup
from ubuntutools import subprocess
from ubuntutools.test import unittest
BLACKLIST = {

View File

@ -15,10 +15,10 @@
# PERFORMANCE OF THIS SOFTWARE.
import re
import subprocess
import setup
from ubuntutools.test import unittest
from ubuntutools import subprocess
WHITELIST = [re.compile(': %s$' % x) for x in (
# Wildcard import:
@ -28,6 +28,8 @@ WHITELIST = [re.compile(': %s$' % x) for x in (
# mox:
r"Instance of '.+' has no '(WithSideEffects|MultipleTimes|AndReturn)' "
r"member",
# pylint doesn't like *args/**kwargs
r"Instance of 'Popen' has no '.*' member",
)]
class PylintTestCase(unittest.TestCase):