Buildroot Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas De Schampheleire <patrickdepinguin@gmail.com>
To: buildroot@busybox.net
Subject: [Buildroot] [PATCHv2 buildroot-test 07/11] autobuild-run: use **kwargs to avoid explicit parameter passthroughs
Date: Sun, 19 Oct 2014 21:30:03 +0200	[thread overview]
Message-ID: <1413747007-24990-8-git-send-email-patrickdepinguin@gmail.com> (raw)
In-Reply-To: <1413747007-24990-1-git-send-email-patrickdepinguin@gmail.com>

From: Thomas De Schampheleire <thomas.de.schampheleire@gmail.com>

The current version of autobuild-run has some extensive explicit
parameter passing, for example:

- fixup_config needs sysinfo, passed via gen_config, in turn via
  run_instance, in turn via main.
- send_results needs username/password settings, passed via
  run_instance, in turn via main.

Everytime a leaf function needs an extra parameter (for example coming
from the arguments or config file), the entire call chain needs to be
adapted to pass along that parameter.

This patch introduces the **kwargs dictionary principle, that allows
implicit parameter passing. A function can accept this dictionary and
extract parameters from it by name. The dictionary can be passed as a
whole to a child function, without explicitly enumerating which entries
in the dictionary are needed in the child.

Signed-off-by: Thomas De Schampheleire <thomas.de.schampheleire@gmail.com>
---
v2: fix missing conversion of 'instance' to kwargs['instance']

 scripts/autobuild-run | 73 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 43 insertions(+), 30 deletions(-)

diff --git a/scripts/autobuild-run b/scripts/autobuild-run
index 40bcaa0..2f83696 100755
--- a/scripts/autobuild-run
+++ b/scripts/autobuild-run
@@ -189,7 +189,7 @@ def get_toolchain_configs():
         configs.append(config)
     return configs
 
-def prepare_build(instance, log):
+def prepare_build(**kwargs):
     """Prepare for the next build of the specified instance
 
     This function prepares the build by making sure all the needed
@@ -197,7 +197,8 @@ def prepare_build(instance, log):
     code, and cleaning up remaining stuff from previous builds.
     """
 
-    idir = "instance-%d" % instance
+    idir = "instance-%d" % kwargs['instance']
+    log = kwargs['log']
 
     log_write(log, "INFO: preparing a new build")
 
@@ -246,7 +247,7 @@ def prepare_build(instance, log):
 
     return 0
 
-def fixup_config(instance, sysinfo):
+def fixup_config(**kwargs):
     """Finalize the configuration and reject any problematic combinations
 
     This function returns 'True' when the configuration has been
@@ -255,9 +256,10 @@ def fixup_config(instance, sysinfo):
     generated).
     """
 
-    idir = "instance-%d" % instance
-    outputdir = os.path.join(idir, "output")
+    idir = "instance-%d" % kwargs['instance']
+    sysinfo = kwargs['sysinfo']
 
+    outputdir = os.path.join(idir, "output")
     with open(os.path.join(outputdir, ".config")) as configf:
         configlines = configf.readlines()
 
@@ -333,7 +335,7 @@ def fixup_config(instance, sysinfo):
 
     return True
 
-def gen_config(instance, log, sysinfo):
+def gen_config(**kwargs):
     """Generate a new random configuration
 
     This function generates the configuration, by choosing a random
@@ -341,7 +343,9 @@ def gen_config(instance, log, sysinfo):
     packages.
     """
 
-    idir = "instance-%d" % instance
+    idir = "instance-%d" % kwargs['instance']
+    log = kwargs['log']
+
     dldir = os.path.join(idir, "dl")
     # We need the absolute path to use with O=, because the relative
     # path to the output directory here is not relative to the
@@ -392,7 +396,7 @@ def gen_config(instance, log, sysinfo):
         if ret != 0:
             log_write(log, "ERROR: cannot generate random configuration")
             return -1
-        if fixup_config(instance, sysinfo):
+        if fixup_config(**kwargs):
             break
 
     ret = subprocess.call(["yes '' 2>/dev/null| make O=%s -C %s oldconfig" % \
@@ -409,10 +413,12 @@ def gen_config(instance, log, sysinfo):
 
     return 0
 
-def do_build(instance, njobs, log, make_opts):
+def do_build(**kwargs):
     """Run the build itself"""
 
-    idir = "instance-%d" % instance
+    idir = "instance-%d" % kwargs['instance']
+    log = kwargs['log']
+
     # We need the absolute path to use with O=, because the relative
     # path to the output directory here is not relative to the
     # Buildroot sources, but to the location of the autobuilder
@@ -423,8 +429,9 @@ def do_build(instance, njobs, log, make_opts):
     f = open(os.path.join(outputdir, "logfile"), "w+")
     log_write(log, "INFO: build started")
     cmd = ["timeout", str(MAX_DURATION), "make", "O=%s" % outputdir,
-            "-C", srcdir, "BR2_DL_DIR=%s" % dldir, "BR2_JLEVEL=%s" % njobs] \
-          + make_opts.split()
+            "-C", srcdir, "BR2_DL_DIR=%s" % dldir,
+            "BR2_JLEVEL=%s" % kwargs['njobs']] \
+          + kwargs['make_opts'].split()
     ret = subprocess.call(cmd, stdout=f, stderr=f)
     # 124 is a special error code that indicates we have reached the
     # timeout
@@ -441,7 +448,7 @@ def do_build(instance, njobs, log, make_opts):
     log_write(log, "INFO: build successful")
     return 0
 
-def send_results(instance, http_login, http_password, submitter, log, result):
+def send_results(result, **kwargs):
     """Prepare and store/send tarball with results
 
     This function prepares the tarball with the results, and either
@@ -449,7 +456,9 @@ def send_results(instance, http_login, http_password, submitter, log, result):
     are available) or stores them locally as tarballs.
     """
 
-    idir = "instance-%d" % instance
+    idir = "instance-%d" % kwargs['instance']
+    log = kwargs['log']
+
     outputdir = os.path.abspath(os.path.join(idir, "output"))
     srcdir = os.path.join(idir, "buildroot")
     resultdir = os.path.join(outputdir, "results")
@@ -484,7 +493,7 @@ def send_results(instance, http_login, http_password, submitter, log, result):
     resultf.close()
 
     with open(os.path.join(resultdir, "submitter"), "w+") as submitterf:
-        submitterf.write(submitter)
+        submitterf.write(kwargs['submitter'])
 
     # Yes, shutil.make_archive() would be nice, but it doesn't exist
     # in Python 2.6.
@@ -494,11 +503,12 @@ def send_results(instance, http_login, http_password, submitter, log, result):
         log_write(log, "ERROR: could not make results tarball")
         sys.exit(1)
 
-    if http_login and http_password:
+    if kwargs['http_login'] and kwargs['http_password']:
         # Submit results. Yes, Python has some HTTP libraries, but
         # none of the ones that are part of the standard library can
         # upload a file without writing dozens of lines of code.
-        ret = subprocess.call(["curl", "-u", "%s:%s" % (http_login, http_password),
+        ret = subprocess.call(["curl", "-u",
+                               "%s:%s" % (kwargs['http_login'], kwargs['http_password']),
                                "-H", "Expect:",
                                "-F", "uploadedfile=@%s" % os.path.join(outputdir, "results.tar.bz2"),
                                "-F", "uploadsubmit=1",
@@ -512,39 +522,40 @@ def send_results(instance, http_login, http_password, submitter, log, result):
         # No http login/password, keep tarballs locally
         with open(os.path.join(outputdir, "results.tar.bz2"), 'rb') as f:
             sha1 = hashlib.sha1(f.read()).hexdigest()
-        resultfilename = "instance-%d-%s.tar.bz2" % (instance, sha1)
+        resultfilename = "instance-%d-%s.tar.bz2" % (kwargs['instance'], sha1)
         os.rename(os.path.join(outputdir, "results.tar.bz2"), resultfilename)
         log_write(log, "INFO: results saved as %s" % resultfilename)
 
-def run_instance(instance, njobs, http_login, http_password, submitter,
-                 make_opts, sysinfo):
+def run_instance(**kwargs):
     """Main per-instance loop
 
     Prepare the build, generate a configuration, run the build, and submit the
     results.
     """
 
-    idir = "instance-%d" % instance
+    idir = "instance-%d" % kwargs['instance']
 
     # If it doesn't exist, create the instance directory
     if not os.path.exists(idir):
         os.mkdir(idir)
 
-    instance_log = open(os.path.join(idir, "instance.log"), "a+")
-    log_write(instance_log, "INFO: instance started")
+    kwargs['log'] = open(os.path.join(idir, "instance.log"), "a+")
+    log_write(kwargs['log'], "INFO: instance started")
+
     while True:
         check_version()
 
-        ret = prepare_build(instance, instance_log)
+        ret = prepare_build(**kwargs)
         if ret != 0:
             continue
 
-        ret = gen_config(instance, instance_log, sysinfo)
+        ret = gen_config(**kwargs)
         if ret != 0:
             continue
 
-        ret = do_build(instance, njobs, instance_log, make_opts)
-        send_results(instance, http_login, http_password, submitter, instance_log, ret)
+        ret = do_build(**kwargs)
+
+        send_results(ret, **kwargs)
 
 # args / config file merging inspired by:
 # https://github.com/docopt/docopt/blob/master/examples/config_file_example.py
@@ -601,9 +612,11 @@ def main():
         sys.exit(1)
     processes = []
     for i in range(0, int(args['--ninstances'])):
-        p = Process(target=run_instance, args=(i, int(args['--njobs']),
-                args['--http-login'], args['--http-password'],
-                args['--submitter'], args['--make-opts'], sysinfo))
+        p = Process(target=run_instance, kwargs={
+            'instance': i, 'njobs': args['--njobs'], 'sysinfo': sysinfo,
+            'http_login': args['--http-login'],
+            'http_password': args['--http-password'],
+            'submitter': args['--submitter'], 'make_opts': args['--make-opts']})
         p.start()
         processes.append(p)
     signal.signal(signal.SIGTERM, sigterm_handler)
-- 
1.8.5.1

  parent reply	other threads:[~2014-10-19 19:30 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-19 19:29 [Buildroot] [PATCHv2 buildroot-test 00/11] autobuild-run improvements Thomas De Schampheleire
2014-10-19 19:29 ` [Buildroot] [PATCHv2 buildroot-test 01/11] autobuild-run: check-requirements does not need to know the login details Thomas De Schampheleire
2014-10-19 20:59   ` Thomas Petazzoni
2014-10-20  9:47     ` Thomas De Schampheleire
2014-10-27 17:56       ` Peter Korsgaard
2014-10-28 11:10         ` Thomas De Schampheleire
2014-10-28 11:14           ` Thomas Petazzoni
2014-10-19 19:29 ` [Buildroot] [PATCHv2 buildroot-test 02/11] autobuild-run: convert regular function comments into docstrings Thomas De Schampheleire
2014-10-19 21:01   ` Thomas Petazzoni
2014-10-19 19:29 ` [Buildroot] [PATCHv2 buildroot-test 03/11] autobuild-run: create main method to locally-scope all variables Thomas De Schampheleire
2014-10-19 21:01   ` Thomas Petazzoni
2014-10-19 19:30 ` [Buildroot] [PATCHv2 buildroot-test 04/11] scripts: add python module docopt Thomas De Schampheleire
2014-10-19 19:30 ` [Buildroot] [PATCHv2 buildroot-test 05/11] autobuild-run: use docopt for argument parsing Thomas De Schampheleire
2014-10-19 19:30 ` [Buildroot] [PATCHv2 buildroot-test 06/11] autobuild-run: add option --make-opts for custom Buildroot options Thomas De Schampheleire
2014-10-19 19:30 ` Thomas De Schampheleire [this message]
2014-10-19 19:30 ` [Buildroot] [PATCHv2 buildroot-test 08/11] autobuild-run: set LC_ALL=C to not use locale settings of host machine Thomas De Schampheleire
2014-10-19 19:30 ` [Buildroot] [PATCHv2 buildroot-test 09/11] autobuild-run: improve the logic to generate build-end.log Thomas De Schampheleire
2014-10-19 19:30 ` [Buildroot] [PATCHv2 buildroot-test 10/11] autobuild-run: save config.log files for failed package Thomas De Schampheleire
2014-10-19 19:44   ` Samuel Martin
2014-10-20  9:45     ` Thomas De Schampheleire
2014-10-19 19:30 ` [Buildroot] [PATCHv2 buildroot-test 11/11] autobuild-run: extend TODO list Thomas De Schampheleire

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1413747007-24990-8-git-send-email-patrickdepinguin@gmail.com \
    --to=patrickdepinguin@gmail.com \
    --cc=buildroot@busybox.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox