* [PATCH 0/3] subprocess: cleanup subprocess calls
@ 2016-09-29 21:34 Stephano Cetola
2016-09-29 21:34 ` [PATCH 1/3] subprocess: remove strings and migrate to direct arrays Stephano Cetola
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Stephano Cetola @ 2016-09-29 21:34 UTC (permalink / raw)
To: openembedded-core
This is the beginning of an effort to move toward a unified way of
using the subprocess module. The end goal is somday create a fork
of the subprocess.run command intro'd in python 3.5.
The biggest hurdle in these efforts is in testing some of the more
obscure code paths that are touched when changing these subprocess
calls. With more time, many of the Popen calls that still exist
could be moved to either check_output or sub.run.
Stephano Cetola (3):
subprocess: remove strings and migrate to direct arrays
utils.py: gut python 2 commands in favor of subprocess.run
subprocess: remove Popen in favor of check_output
meta/classes/buildstats.bbclass | 6 ++++-
meta/classes/spdx.bbclass | 11 ++++----
meta/lib/oe/distro_check.py | 2 +-
meta/lib/oe/package.py | 13 ++++-----
meta/lib/oe/package_manager.py | 59 ++++++++++++++++++++---------------------
meta/lib/oe/utils.py | 11 +++-----
6 files changed, 51 insertions(+), 51 deletions(-)
--
2.10.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/3] subprocess: remove strings and migrate to direct arrays
2016-09-29 21:34 [PATCH 0/3] subprocess: cleanup subprocess calls Stephano Cetola
@ 2016-09-29 21:34 ` Stephano Cetola
2016-09-30 16:10 ` Burton, Ross
2016-09-29 21:34 ` [PATCH 2/3] utils.py: gut python 2 commands in favor of subprocess.run Stephano Cetola
2016-09-29 21:34 ` [PATCH 3/3] subprocess: remove Popen in favor of check_output Stephano Cetola
2 siblings, 1 reply; 7+ messages in thread
From: Stephano Cetola @ 2016-09-29 21:34 UTC (permalink / raw)
To: openembedded-core
When using subprocess call and check_output, it is better to use arrays
rather than strings when possible to avoid whitespace and quoting
problems.
[ YOCTO #9342 ]
Signed-off-by: Stephano Cetola <stephano.cetola@linux.intel.com>
---
meta/lib/oe/distro_check.py | 2 +-
meta/lib/oe/package.py | 13 +++++-----
meta/lib/oe/package_manager.py | 59 +++++++++++++++++++++---------------------
3 files changed, 37 insertions(+), 37 deletions(-)
diff --git a/meta/lib/oe/distro_check.py b/meta/lib/oe/distro_check.py
index 87c52fa..cc973c2 100644
--- a/meta/lib/oe/distro_check.py
+++ b/meta/lib/oe/distro_check.py
@@ -359,7 +359,7 @@ def create_log_file(d, logname):
slogfile = os.path.join(logpath, logname)
if os.path.exists(slogfile):
os.remove(slogfile)
- subprocess.call("touch %s" % logfile, shell=True)
+ subprocess.call(["touch", logfile])
os.symlink(logfile, slogfile)
d.setVar('LOG_FILE', logfile)
return logfile
diff --git a/meta/lib/oe/package.py b/meta/lib/oe/package.py
index 02642f2..ae60a58 100644
--- a/meta/lib/oe/package.py
+++ b/meta/lib/oe/package.py
@@ -18,23 +18,24 @@ def runstrip(arg):
newmode = origmode | stat.S_IWRITE | stat.S_IREAD
os.chmod(file, newmode)
- extraflags = ""
+ stripcmd = [strip]
# kernel module
if elftype & 16:
- extraflags = "--strip-debug --remove-section=.comment --remove-section=.note --preserve-dates"
+ stripcmd.extend(["--strip-debug", "--remove-section=.comment",
+ "--remove-section=.note", "--preserve-dates"])
# .so and shared library
elif ".so" in file and elftype & 8:
- extraflags = "--remove-section=.comment --remove-section=.note --strip-unneeded"
+ stripcmd.extend(["--remove-section=.comment", "--remove-section=.note", "--strip-unneeded"])
# shared or executable:
elif elftype & 8 or elftype & 4:
- extraflags = "--remove-section=.comment --remove-section=.note"
+ stripcmd.extend(["--remove-section=.comment", "--remove-section=.note"])
- stripcmd = "'%s' %s '%s'" % (strip, extraflags, file)
+ stripcmd.append(file)
bb.debug(1, "runstrip: %s" % stripcmd)
try:
- output = subprocess.check_output(stripcmd, stderr=subprocess.STDOUT, shell=True)
+ output = subprocess.check_output(stripcmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
bb.error("runstrip: '%s' strip command failed with %s (%s)" % (stripcmd, e.returncode, e.output))
diff --git a/meta/lib/oe/package_manager.py b/meta/lib/oe/package_manager.py
index 434b898..d217073 100644
--- a/meta/lib/oe/package_manager.py
+++ b/meta/lib/oe/package_manager.py
@@ -358,12 +358,11 @@ class RpmPkgsList(PkgsList):
RpmIndexer(d, rootfs_dir).get_ml_prefix_and_os_list(arch_var, os_var)
# Determine rpm version
- cmd = "%s --version" % self.rpm_cmd
try:
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
+ output = subprocess.check_output([self.rpm_cmd, "--version"], stderr=subprocess.STDOUT).decode("utf-8")
except subprocess.CalledProcessError as e:
bb.fatal("Getting rpm version failed. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
+ "returned %d:\n%s" % (self.rpm_cmd, e.returncode, e.output.decode("utf-8")))
'''
Translate the RPM/Smart format names to the OE multilib format names
@@ -412,16 +411,15 @@ class RpmPkgsList(PkgsList):
return output
def list_pkgs(self):
- cmd = self.rpm_cmd + ' --root ' + self.rootfs_dir
- cmd += ' -D "_dbpath /var/lib/rpm" -qa'
- cmd += " --qf '[%{NAME} %{ARCH} %{VERSION} %{PACKAGEORIGIN}\n]'"
+ cmd = [self.rpm_cmd, '--root', self.rootfs_dir]
+ cmd.extend(['-D', '_dbpath /var/lib/rpm'])
+ cmd.extend(['-qa', '--qf', '[%{NAME} %{ARCH} %{VERSION} %{PACKAGEORIGIN}\n]'])
try:
- # bb.note(cmd)
- tmp_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).strip().decode("utf-8")
+ tmp_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip().decode("utf-8")
except subprocess.CalledProcessError as e:
bb.fatal("Cannot get the installed packages list. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
+ "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
output = dict()
deps = dict()
@@ -949,20 +947,22 @@ class RpmPM(PackageManager):
open(db_config_dir, 'w+').write(DB_CONFIG_CONTENT)
# Create database so that smart doesn't complain (lazy init)
- opt = "-qa"
- cmd = "%s --root %s --dbpath /var/lib/rpm %s > /dev/null" % (
- self.rpm_cmd, self.target_rootfs, opt)
+ cmd = [self.rpm_cmd, '--root', self.target_rootfs, '--dbpath', '/var/lib/rpm', '-qa']
try:
- subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
+ subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
bb.fatal("Create rpm database failed. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
+ "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
# Import GPG key to RPM database of the target system
if self.d.getVar('RPM_SIGN_PACKAGES', True) == '1':
pubkey_path = self.d.getVar('RPM_GPG_PUBKEY', True)
- cmd = "%s --root %s --dbpath /var/lib/rpm --import %s > /dev/null" % (
- self.rpm_cmd, self.target_rootfs, pubkey_path)
- subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
+ cmd = [self.rpm_cmd, '--root', self.target_rootfs, '--dbpath', '/var/lib/rpm', '--import', pubkey_path]
+ try:
+ subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Import GPG key failed. Command '%s' "
+ "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
+
# Configure smart
bb.note("configuring Smart settings")
@@ -1355,17 +1355,16 @@ class RpmPM(PackageManager):
def dump_all_available_pkgs(self):
available_manifest = self.d.expand('${T}/saved/available_pkgs.txt')
available_pkgs = list()
- cmd = "%s %s query --output %s" % \
- (self.smart_cmd, self.smart_opt, available_manifest)
+ cmd = [self.smart_cmd, self.smart_opt, 'query', '--output', available_manifest]
try:
- subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
+ subprocess.check_output(cmd, stderr=subprocess.STDOUT)
with open(available_manifest, 'r') as manifest:
for pkg in manifest.read().split('\n'):
if '@' in pkg:
available_pkgs.append(pkg.strip())
except subprocess.CalledProcessError as e:
bb.note("Unable to list all available packages. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
+ "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
self.fullpkglist = available_pkgs
@@ -1425,12 +1424,12 @@ class RpmPM(PackageManager):
Returns a dictionary with the package info.
"""
def package_info(self, pkg):
- cmd = "%s %s info --urls %s" % (self.smart_cmd, self.smart_opt, pkg)
+ cmd = [self.smart_cmd, self.smart_opt, 'info', '--urls', pkg]
try:
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode("utf-8")
except subprocess.CalledProcessError as e:
bb.fatal("Unable to list available packages. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
+ "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
# Set default values to avoid UnboundLocalError
arch = ""
@@ -1550,18 +1549,18 @@ class OpkgDpkgPM(PackageManager):
os.chdir(tmp_dir)
try:
- cmd = "%s x %s" % (ar_cmd, pkg_path)
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
- cmd = "%s xf data.tar.*" % tar_cmd
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
+ cmd = [ar_cmd, 'x', pkg_path]
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ cmd = [tar_cmd, 'xf', 'data.tar.*']
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
bb.utils.remove(tmp_dir, recurse=True)
bb.fatal("Unable to extract %s package. Command '%s' "
- "returned %d:\n%s" % (pkg_path, cmd, e.returncode, e.output.decode("utf-8")))
+ "returned %d:\n%s" % (pkg_path, ' '.join(cmd), e.returncode, e.output.decode("utf-8")))
except OSError as e:
bb.utils.remove(tmp_dir, recurse=True)
bb.fatal("Unable to extract %s package. Command '%s' "
- "returned %d:\n%s at %s" % (pkg_path, cmd, e.errno, e.strerror, e.filename))
+ "returned %d:\n%s at %s" % (pkg_path, ' '.join(cmd), e.errno, e.strerror, e.filename))
bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
bb.utils.remove(os.path.join(tmp_dir, "debian-binary"))
--
2.10.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/3] utils.py: gut python 2 commands in favor of subprocess.run
2016-09-29 21:34 [PATCH 0/3] subprocess: cleanup subprocess calls Stephano Cetola
2016-09-29 21:34 ` [PATCH 1/3] subprocess: remove strings and migrate to direct arrays Stephano Cetola
@ 2016-09-29 21:34 ` Stephano Cetola
2016-09-29 22:20 ` Christopher Larson
2016-09-29 21:34 ` [PATCH 3/3] subprocess: remove Popen in favor of check_output Stephano Cetola
2 siblings, 1 reply; 7+ messages in thread
From: Stephano Cetola @ 2016-09-29 21:34 UTC (permalink / raw)
To: openembedded-core
getstatusoutput is a wrapper around subprocess.getstatusouput() in
Py3, which is basically deprecated and behaves almost entirely unlike
run().
[ YOCTO #9342 ]
Signed-off-by: Stephano Cetola <stephano.cetola@linux.intel.com>
---
meta/lib/oe/utils.py | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/meta/lib/oe/utils.py b/meta/lib/oe/utils.py
index d6545b1..265f733 100644
--- a/meta/lib/oe/utils.py
+++ b/meta/lib/oe/utils.py
@@ -1,9 +1,4 @@
-try:
- # Python 2
- import commands as cmdstatus
-except ImportError:
- # Python 3
- import subprocess as cmdstatus
+import subprocess
def read_file(filename):
try:
@@ -144,7 +139,9 @@ def packages_filter_out_system(d):
return pkgs
def getstatusoutput(cmd):
- return cmdstatus.getstatusoutput(cmd)
+ compproc = subprocess.run(cmd, stdout=subprocess.PIPE,
+ universal_newlines=True, stderr=subprocess.STDOUT, shell=True)
+ return (compproc.returncode, compproc.stdout)
def trim_version(version, num_parts=2):
--
2.10.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] subprocess: remove Popen in favor of check_output
2016-09-29 21:34 [PATCH 0/3] subprocess: cleanup subprocess calls Stephano Cetola
2016-09-29 21:34 ` [PATCH 1/3] subprocess: remove strings and migrate to direct arrays Stephano Cetola
2016-09-29 21:34 ` [PATCH 2/3] utils.py: gut python 2 commands in favor of subprocess.run Stephano Cetola
@ 2016-09-29 21:34 ` Stephano Cetola
2 siblings, 0 replies; 7+ messages in thread
From: Stephano Cetola @ 2016-09-29 21:34 UTC (permalink / raw)
To: openembedded-core
This begins moving away from the deprecated subprocess calls in an
effort to eventually move to some more global abstraction using the run
convenience method provided in python 3.5.
[ YOCTO #9342 ]
Signed-off-by: Stephano Cetola <stephano.cetola@linux.intel.com>
---
meta/classes/buildstats.bbclass | 6 +++++-
meta/classes/spdx.bbclass | 11 +++++------
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/meta/classes/buildstats.bbclass b/meta/classes/buildstats.bbclass
index 34ecb03..8c2b7b3 100644
--- a/meta/classes/buildstats.bbclass
+++ b/meta/classes/buildstats.bbclass
@@ -163,7 +163,11 @@ python run_buildstats () {
bs = os.path.join(bsdir, "build_stats")
with open(bs, "a") as f:
rootfs = d.getVar('IMAGE_ROOTFS', True)
- rootfs_size = subprocess.Popen(["du", "-sh", rootfs], stdout=subprocess.PIPE).stdout.read()
+ try:
+ rootfs_size = subprocess.check_output(["du", "-sh", rootfs],
+ stderr=subprocess.STDOUT).decode('utf-8')
+ except subprocess.CalledProcessError as e:
+ bb.error("Failed to get rootfs size: %s" % e.output)
f.write("Uncompressed Rootfs size: %s" % rootfs_size)
elif isinstance(e, bb.build.TaskFailed):
diff --git a/meta/classes/spdx.bbclass b/meta/classes/spdx.bbclass
index 0c92765..89394d3 100644
--- a/meta/classes/spdx.bbclass
+++ b/meta/classes/spdx.bbclass
@@ -219,14 +219,13 @@ def hash_string(data):
def run_fossology(foss_command, full_spdx):
import string, re
import subprocess
-
- p = subprocess.Popen(foss_command.split(),
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- foss_output, foss_error = p.communicate()
- if p.returncode != 0:
+
+ try:
+ foss_output = subprocess.check_output(foss_command.split(),
+ stderr=subprocess.STDOUT).decode('utf-8')
+ except subprocess.CalledProcessError as e:
return None
- foss_output = unicode(foss_output, "utf-8")
foss_output = string.replace(foss_output, '\r', '')
# Package info
--
2.10.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] utils.py: gut python 2 commands in favor of subprocess.run
2016-09-29 21:34 ` [PATCH 2/3] utils.py: gut python 2 commands in favor of subprocess.run Stephano Cetola
@ 2016-09-29 22:20 ` Christopher Larson
2016-09-29 22:52 ` Stephano Cetola
0 siblings, 1 reply; 7+ messages in thread
From: Christopher Larson @ 2016-09-29 22:20 UTC (permalink / raw)
To: Stephano Cetola; +Cc: Patches and discussions about the oe-core layer
[-- Attachment #1: Type: text/plain, Size: 1469 bytes --]
On Thu, Sep 29, 2016 at 2:34 PM, Stephano Cetola <
stephano.cetola@linux.intel.com> wrote:
> getstatusoutput is a wrapper around subprocess.getstatusouput() in
> Py3, which is basically deprecated and behaves almost entirely unlike
> run().
>
> [ YOCTO #9342 ]
>
> Signed-off-by: Stephano Cetola <stephano.cetola@linux.intel.com>
> ---
> meta/lib/oe/utils.py | 11 ++++-------
> 1 file changed, 4 insertions(+), 7 deletions(-)
>
> diff --git a/meta/lib/oe/utils.py b/meta/lib/oe/utils.py
> index d6545b1..265f733 100644
> --- a/meta/lib/oe/utils.py
> +++ b/meta/lib/oe/utils.py
> @@ -1,9 +1,4 @@
> -try:
> - # Python 2
> - import commands as cmdstatus
> -except ImportError:
> - # Python 3
> - import subprocess as cmdstatus
> +import subprocess
>
> def read_file(filename):
> try:
> @@ -144,7 +139,9 @@ def packages_filter_out_system(d):
> return pkgs
>
> def getstatusoutput(cmd):
> - return cmdstatus.getstatusoutput(cmd)
> + compproc = subprocess.run(cmd, stdout=subprocess.PIPE,
> + universal_newlines=True, stderr=subprocess.STDOUT, shell=True)
> + return (compproc.returncode, compproc.stdout)
>
This is wrong, we can’t use subprocess.run until we bump our minimum python
version. We only require 3.4, not 3.5.
--
Christopher Larson
clarson at kergoth dot com
Founder - BitBake, OpenEmbedded, OpenZaurus
Maintainer - Tslib
Senior Software Engineer, Mentor Graphics
[-- Attachment #2: Type: text/html, Size: 2065 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] utils.py: gut python 2 commands in favor of subprocess.run
2016-09-29 22:20 ` Christopher Larson
@ 2016-09-29 22:52 ` Stephano Cetola
0 siblings, 0 replies; 7+ messages in thread
From: Stephano Cetola @ 2016-09-29 22:52 UTC (permalink / raw)
To: Christopher Larson; +Cc: Patches and discussions about the oe-core layer
On 09/29, Christopher Larson wrote:
> On Thu, Sep 29, 2016 at 2:34 PM, Stephano Cetola <
> stephano.cetola@linux.intel.com> wrote:
>
> > getstatusoutput is a wrapper around subprocess.getstatusouput() in
> > Py3, which is basically deprecated and behaves almost entirely unlike
> > run().
> >
> > [ YOCTO #9342 ]
> >
> > Signed-off-by: Stephano Cetola <stephano.cetola@linux.intel.com>
> > ---
> > meta/lib/oe/utils.py | 11 ++++-------
> > 1 file changed, 4 insertions(+), 7 deletions(-)
> >
> > diff --git a/meta/lib/oe/utils.py b/meta/lib/oe/utils.py
> > index d6545b1..265f733 100644
> > --- a/meta/lib/oe/utils.py
> > +++ b/meta/lib/oe/utils.py
> > @@ -1,9 +1,4 @@
> > -try:
> > - # Python 2
> > - import commands as cmdstatus
> > -except ImportError:
> > - # Python 3
> > - import subprocess as cmdstatus
> > +import subprocess
> >
> > def read_file(filename):
> > try:
> > @@ -144,7 +139,9 @@ def packages_filter_out_system(d):
> > return pkgs
> >
> > def getstatusoutput(cmd):
> > - return cmdstatus.getstatusoutput(cmd)
> > + compproc = subprocess.run(cmd, stdout=subprocess.PIPE,
> > + universal_newlines=True, stderr=subprocess.STDOUT, shell=True)
> > + return (compproc.returncode, compproc.stdout)
> >
>
> This is wrong, we can’t use subprocess.run until we bump our minimum python
> version. We only require 3.4, not 3.5.
Removed this and resubmitted.
--stephano
> --
> Christopher Larson
> clarson at kergoth dot com
> Founder - BitBake, OpenEmbedded, OpenZaurus
> Maintainer - Tslib
> Senior Software Engineer, Mentor Graphics
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] subprocess: remove strings and migrate to direct arrays
2016-09-29 21:34 ` [PATCH 1/3] subprocess: remove strings and migrate to direct arrays Stephano Cetola
@ 2016-09-30 16:10 ` Burton, Ross
0 siblings, 0 replies; 7+ messages in thread
From: Burton, Ross @ 2016-09-30 16:10 UTC (permalink / raw)
To: Stephano Cetola; +Cc: OE-core
[-- Attachment #1: Type: text/plain, Size: 452 bytes --]
On 29 September 2016 at 22:34, Stephano Cetola <
stephano.cetola@linux.intel.com> wrote:
> - cmd = "%s %s query --output %s" % \
> - (self.smart_cmd, self.smart_opt, available_manifest)
> + cmd = [self.smart_cmd, self.smart_opt, 'query', '--output',
> available_manifest]
>
self.smart_opt is a string containing many options, so this needs to be
transformed to a list of options and embedded correctly.
Ross
[-- Attachment #2: Type: text/html, Size: 1204 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-09-30 16:11 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-09-29 21:34 [PATCH 0/3] subprocess: cleanup subprocess calls Stephano Cetola
2016-09-29 21:34 ` [PATCH 1/3] subprocess: remove strings and migrate to direct arrays Stephano Cetola
2016-09-30 16:10 ` Burton, Ross
2016-09-29 21:34 ` [PATCH 2/3] utils.py: gut python 2 commands in favor of subprocess.run Stephano Cetola
2016-09-29 22:20 ` Christopher Larson
2016-09-29 22:52 ` Stephano Cetola
2016-09-29 21:34 ` [PATCH 3/3] subprocess: remove Popen in favor of check_output Stephano Cetola
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox