From eeac2c2797f9e03b191a0947fbec5900fe6793d4 Mon Sep 17 00:00:00 2001
From: Samuel Gaist <samuel.gaist@idiap.ch>
Date: Fri, 12 Apr 2019 17:44:04 +0200
Subject: [PATCH] [scripts] Implement helper script to translate a v1 database
 to v2

This scripts creates the needed protocol templates unless a protocol
template with the same name already exists.
---
 beat/core/scripts/migrate_db_to_v2.py | 158 ++++++++++++++++++++++++++
 1 file changed, 158 insertions(+)
 create mode 100644 beat/core/scripts/migrate_db_to_v2.py

diff --git a/beat/core/scripts/migrate_db_to_v2.py b/beat/core/scripts/migrate_db_to_v2.py
new file mode 100644
index 00000000..707eb5d9
--- /dev/null
+++ b/beat/core/scripts/migrate_db_to_v2.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 :
+
+###################################################################################
+#                                                                                 #
+# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/               #
+# Contact: beat.support@idiap.ch                                                  #
+#                                                                                 #
+# Redistribution and use in source and binary forms, with or without              #
+# modification, are permitted provided that the following conditions are met:     #
+#                                                                                 #
+# 1. Redistributions of source code must retain the above copyright notice, this  #
+# list of conditions and the following disclaimer.                                #
+#                                                                                 #
+# 2. Redistributions in binary form must reproduce the above copyright notice,    #
+# this list of conditions and the following disclaimer in the documentation       #
+# and/or other materials provided with the distribution.                          #
+#                                                                                 #
+# 3. Neither the name of the copyright holder nor the names of its contributors   #
+# may be used to endorse or promote products derived from this software without   #
+# specific prior written permission.                                              #
+#                                                                                 #
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED   #
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE          #
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE    #
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL      #
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR      #
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER      #
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,   #
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE   #
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.            #
+#                                                                                 #
+###################################################################################
+
+"""Migrate a v1 database to v2
+
+Usage:
+  %(prog)s [-v ... | --verbose ...] [--prefix=<path>][-f|--force]
+           <database_identifier>
+  %(prog)s (--help | -h)
+  %(prog)s (--version | -V)
+
+
+Options:
+  -h, --help                 Show this screen
+  -V, --version              Show version
+  -v, --verbose              Increases the output verbosity level
+  -p, --prefix=<path>        Path where the prefix is contained [default: .]
+"""
+
+import os
+import sys
+import copy
+
+from docopt import docopt
+
+from ..version import __version__
+
+from ..database import Database, Storage as DBStorage
+from ..protocoltemplate import ProtocolTemplate, Storage as PTStorage
+from ..utils import setup_logging
+
+
+def main(argv=None):
+    if argv is None:
+        argv = sys.argv[1:]
+
+    prog = os.path.basename(sys.argv[0])
+    completions = dict(prog=prog, version=__version__)
+    args = docopt(
+        __doc__ % completions,
+        argv=argv,
+        options_first=True,
+        version="v%s" % __version__,
+    )
+
+    logger = setup_logging(args["--verbose"], __name__, __name__)
+
+    prefix = args["--prefix"] if args["--prefix"] is not None else "."
+    if not os.path.exists(prefix):
+        logger.error("Prefix not found at: '%s'", prefix)
+        return 1
+
+    database_identifier = args["<database_identifier>"]
+
+    database = Database(prefix, database_identifier)
+
+    if not database.valid:
+        logger.error("Invalid database: '%s'", "\n".join(database.errors))
+        return 1
+
+    if database.schema_version != 1:
+        logger.error("Can't migrate database is not v1")
+        return 1
+
+    db_name, db_version = database_identifier.split("/")
+    new_db_name = f"{db_name}/{int(db_version) + 1}"
+
+    db_storage = DBStorage(prefix, new_db_name)
+    if db_storage.exists():
+        logger.error(f"Database already exists: {new_db_name}")
+        return 1
+
+    database_json = copy.deepcopy(database.data)
+    database_json["schema_version"] = 2
+    database_json["protocols"] = []
+
+    for protocol in database.protocols:
+        sets = database.sets(protocol)
+        set_list = []
+        views = {}
+        for _, set_ in sets.items():
+            views[set_["name"]] = {
+                "view": set_["view"],
+                "parameters": set_.get("parameters", {}),
+            }
+
+            for key in ["template", "view", "parameters"]:
+                if key in set_:
+                    set_.pop(key)
+            set_list.append(set_)
+
+        template = {"schema_version": 1, "sets": set_list}
+
+        pt_name = f"{protocol}/1"
+        pt_storage = PTStorage(prefix, pt_name)
+
+        if pt_storage.exists():
+            logger.info(f"Protocol template already exists: {pt_name}")
+        else:
+            protocol_template = ProtocolTemplate(prefix, template)
+            if not protocol_template.valid:
+                logger.error(
+                    "Invalid protocol created:", "\n".join(protocol_template.errors)
+                )
+                return 1
+            else:
+                protocol_template.write(pt_storage)
+
+        protocol_entry = {"name": protocol, "template": pt_name, "views": views}
+
+        database_json["protocols"].append(protocol_entry)
+
+    new_database = Database(prefix, database_json)
+    if not new_database.valid:
+        logger.error("Invalid database created:", "\n".join(new_database.errors))
+        return 1
+    else:
+        new_database.code = database.code
+        new_database.description = (
+            database.description if database.description is not None else ""
+        )
+        new_database.write(db_storage)
+
+
+if __name__ == "__main__":
+    main()
-- 
GitLab