Improvements in [tasks] handling
authorClifford Wolf <clifford@clifford.at>
Tue, 6 Mar 2018 17:05:51 +0000 (18:05 +0100)
committerClifford Wolf <clifford@clifford.at>
Tue, 6 Mar 2018 17:05:51 +0000 (18:05 +0100)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
docs/source/reference.rst
sbysrc/sby.py
sbysrc/sby_core.py

index 4f0b67f45b3071a3606748a7a7457bba7f57bde2..1135c6d55024e16cbb2417b89223fb56bf9f082b 100644 (file)
@@ -23,15 +23,14 @@ a single ``.sby`` file. Each line in the ``[tasks]`` section configures one task
 Each task can be assigned additional group aliases, such as ``task_1_or_2``
 and ``task_1_or_3`` in the above example.
 
-A task can be specified as additional command line argument when calling
-``sby`` on a ``.sby`` file:
+One or more tasks can be specified as additional command line arguments when
+calling ``sby`` on a ``.sby`` file:
 
 .. code-block:: text
 
    sby example.sby task2
 
-If no task is specified then the configuration for the first task in the
-``[tasks]`` section is used.
+If no task is specified then all tasks in the ``[tasks]`` section are run.
 
 After the ``[tasks]`` section individual lines can be specified for specific
 tasks or task groups:
index 03f98c370072fda9c12f387c57ca7b5d80779384..1a24841279679b3591a484f2946a14c8315fc900 100644 (file)
@@ -23,7 +23,7 @@ from sby_core import SbyJob
 
 sbyfile = None
 workdir = None
-taskname = None
+tasknames = list()
 opt_force = False
 opt_backup = False
 opt_tmpdir = False
@@ -31,7 +31,7 @@ exe_paths = dict()
 
 def usage():
     print("""
-sby [options] [<jobname>.sby [taskname]]
+sby [options] [<jobname>.sby [tasknames]]
 
     -d <dirname>
         set workdir name. default: <jobname> (without .sby)
@@ -46,7 +46,7 @@ sby [options] [<jobname>.sby [taskname]]
         run in a temporary workdir (remove when finished)
 
     -T taskname
-        set the taskname (useful when sby file is read from stdin)
+        add taskname (useful when sby file is read from stdin)
 
     --yosys <path_to_executable>
     --abc <path_to_executable>
@@ -74,7 +74,7 @@ for o, a in opts:
     elif o == "-t":
         opt_tmpdir = True
     elif o == "-T":
-        taskname = a
+        tasknames.append(a)
     elif o == "--yosys":
         exe_paths["yosys"] = a
     elif o == "--abc":
@@ -90,58 +90,160 @@ for o, a in opts:
     else:
         usage()
 
-if len(args) > 2:
-    usage()
-
 if len(args) > 0:
     sbyfile = args[0]
     assert sbyfile.endswith(".sby")
 
 if len(args) > 1:
-    assert taskname is None
-    taskname = args[1]
+    tasknames = args[1:]
+
 
 early_logmsgs = list()
 
-def early_log(msg):
+def early_log(workdir, msg):
     early_logmsgs.append("SBY [%s] %s" % (workdir, msg))
     print(early_logmsgs[-1])
 
-if workdir is None and sbyfile is not None and not opt_tmpdir:
-    workdir = sbyfile[:-4]
-    if taskname is not None:
-        workdir += "_" + taskname
 
-if workdir is not None:
-    if opt_backup:
-        backup_idx = 0
-        while os.path.exists("%s.bak%03d" % (workdir, backup_idx)):
-            backup_idx += 1
-        early_log("Moving direcory '%s' to '%s'." % (workdir, "%s.bak%03d" % (workdir, backup_idx)))
-        shutil.move(workdir, "%s.bak%03d" % (workdir, backup_idx))
+def read_sbyconfig(sbydata, taskname):
+    cfgdata = list()
+    tasklist = list()
+
+    pycode = None
+    tasks_section = False
+    task_tags_active = set()
+    task_tags_all = set()
+    task_skip_block = False
+    task_skiping_blocks = False
+
+    for line in sbydata:
+        line = line.rstrip("\n")
+        line = line.rstrip("\r")
+
+        if tasks_section and line.startswith("["):
+            tasks_section = False
+
+        if task_skiping_blocks:
+            if line == "--":
+                task_skip_block = False
+                task_skiping_blocks = False
+                continue
+
+        task_skip_line = False
+        for t in task_tags_all:
+            if line.startswith(t+":"):
+                line = line[len(t)+1:].lstrip()
+                match = t in task_tags_active
+            elif line.startswith("~"+t+":"):
+                line = line[len(t)+2:].lstrip()
+                match = t not in task_tags_active
+            else:
+                continue
+
+            if line == "":
+                task_skiping_blocks = True
+                task_skip_block = not match
+                task_skip_line = True
+            else:
+                task_skip_line = not match
+
+            break
+
+        if task_skip_line or task_skip_block:
+            continue
+
+        if tasks_section:
+            line = line.split()
+            if len(line) > 0:
+                tasklist.append(line[0])
+            for t in line:
+                if taskname == line[0]:
+                    task_tags_active.add(t)
+                task_tags_all.add(t)
+
+        elif line == "[tasks]":
+            tasks_section = True
+
+        elif line == "--pycode-begin--":
+            pycode = ""
+
+        elif line == "--pycode-end--":
+            gdict = globals().copy()
+            gdict["cfgdata"] = cfgdata
+            gdict["taskname"] = taskname
+            exec("def output(line):\n  cfgdata.append(line)\n" + pycode, gdict)
+            pycode = None
+
+        else:
+            if pycode is None:
+                cfgdata.append(line)
+            else:
+                pycode += line + "\n"
+
+    return cfgdata, tasklist
+
+
+sbydata = list()
+with (open(sbyfile, "r") if sbyfile is not None else sys.stdin) as f:
+    for line in f:
+        sbydata.append(line)
+
+if len(tasknames) == 0:
+    _, tasknames = read_sbyconfig(sbydata, None)
+    if len(tasknames) == 0:
+        tasknames = [None]
+
+assert (workdir is None) or (len(tasknames) == 1)
+
+
+def run_job(taskname):
+    my_workdir = workdir
+    my_opt_tmpdir = opt_tmpdir
+
+    if my_workdir is None and sbyfile is not None and not my_opt_tmpdir:
+        my_workdir = sbyfile[:-4]
+        if taskname is not None:
+            my_workdir += "_" + taskname
+
+    if my_workdir is not None:
+        if opt_backup:
+            backup_idx = 0
+            while os.path.exists("%s.bak%03d" % (my_workdir, backup_idx)):
+                backup_idx += 1
+            early_log(my_workdir, "Moving direcory '%s' to '%s'." % (my_workdir, "%s.bak%03d" % (my_workdir, backup_idx)))
+            shutil.move(my_workdir, "%s.bak%03d" % (my_workdir, backup_idx))
+
+        if opt_force:
+            early_log(my_workdir, "Removing direcory '%s'." % (my_workdir))
+            if sbyfile:
+                shutil.rmtree(my_workdir, ignore_errors=True)
+
+        os.makedirs(my_workdir)
+
+    else:
+        my_opt_tmpdir = True
+        my_workdir = tempfile.mkdtemp()
 
-    if opt_force:
-        early_log("Removing direcory '%s'." % (workdir))
-        if sbyfile:
-            shutil.rmtree(workdir, ignore_errors=True)
+    sbyconfig, _ = read_sbyconfig(sbydata, taskname)
+    job = SbyJob(sbyconfig, taskname, my_workdir, early_logmsgs)
 
-    os.makedirs(workdir)
+    for k, v in exe_paths.items():
+        job.exe_paths[k] = v
 
-else:
-    opt_tmpdir = True
-    workdir = tempfile.mkdtemp()
+    job.run()
 
-job = SbyJob(sbyfile, taskname, workdir, early_logmsgs)
+    if my_opt_tmpdir:
+        job.log("Removing direcory '%s'." % (my_workdir))
+        shutil.rmtree(my_workdir, ignore_errors=True)
 
-for k, v in exe_paths.items():
-    job.exe_paths[k] = v
+    job.log("DONE (%s, rc=%d)" % (job.status, job.retcode))
+    return job.retcode
 
-job.run()
 
-if opt_tmpdir:
-    job.log("Removing direcory '%s'." % (workdir))
-    shutil.rmtree(workdir, ignore_errors=True)
+retcode = 0
+for t in tasknames:
+    assert (t is None) or (t in tasknames)
+    retcode += run_job(t)
 
-job.log("DONE (%s, rc=%d)" % (job.status, job.retcode))
-sys.exit(job.retcode)
+sys.exit(retcode)
 
index 73dd7e10c91e1d35bbe54c7a8c66223c1ae0fb0c..6ed455d2f7e9b0befe2de1936ae6a4157b30ebd3 100644 (file)
@@ -126,7 +126,7 @@ class SbyTask:
 
 
 class SbyJob:
-    def __init__(self, filename, taskname, workdir, early_logs):
+    def __init__(self, sbyconfig, taskname, workdir, early_logs):
         self.options = dict()
         self.used_options = set()
         self.engines = list()
@@ -166,80 +166,9 @@ class SbyJob:
         mode = None
         key = None
 
-        with (open(filename, "r") if filename else sys.stdin) as f:
-            with open("%s/config.sby" % workdir, "w") as cfgfile:
-                pycode = None
-                tasks_section = False
-                task_tags_active = set()
-                task_tags_all = set()
-                task_skip_block = False
-                task_skiping_blocks = False
-                for line in f:
-                    line = line.rstrip("\n")
-                    line = line.rstrip("\r")
-
-                    if tasks_section and line.startswith("["):
-                        tasks_section = False
-
-                    if task_skiping_blocks:
-                        if line == "--":
-                            task_skip_block = False
-                            task_skiping_blocks = False
-                            continue
-
-                    task_skip_line = False
-                    for t in task_tags_all:
-                        if line.startswith(t+":"):
-                            line = line[len(t)+1:].lstrip()
-                            match = t in task_tags_active
-                        elif line.startswith("~"+t+":"):
-                            line = line[len(t)+2:].lstrip()
-                            match = t not in task_tags_active
-                        else:
-                            continue
-
-                        if line == "":
-                            task_skiping_blocks = True
-                            task_skip_block = not match
-                            task_skip_line = True
-                        else:
-                            task_skip_line = not match
-
-                        break
-
-                    if task_skip_line or task_skip_block:
-                        continue
-
-                    if tasks_section:
-                        line = line.split()
-                        if len(line) > 0:
-                            if taskname is None:
-                                taskname = line[0]
-                                self.log("Configuration file contains tasks. Running default task '%s'." % taskname)
-                        for t in line:
-                            if taskname == line[0]:
-                                task_tags_active.add(t)
-                            task_tags_all.add(t)
-
-                    elif line == "[tasks]":
-                        tasks_section = True
-
-                    elif line == "--pycode-begin--":
-                        pycode = ""
-
-                    elif line == "--pycode-end--":
-                        gdict = globals().copy()
-                        gdict["cfgfile"] = cfgfile
-                        gdict["filename"] = filename
-                        gdict["taskname"] = taskname
-                        exec("def output(*args, **kwargs):\n  print(*args, **kwargs, file=cfgfile)\n" + pycode, gdict)
-                        pycode = None
-
-                    else:
-                        if pycode is None:
-                            print(line, file=cfgfile)
-                        else:
-                            pycode += line + "\n"
+        with open("%s/config.sby" % workdir, "w") as f:
+            for line in sbyconfig:
+                print(line, file=f)
 
         with open("%s/config.sby" % workdir, "r") as f:
             for line in f: