Auto module package

Discuss about Group-Office development here

Moderator: Developers

Posts: 66
Joined: Fri Jun 21, 2013 2:55 pm

Auto module package

Postby richarddodd » Tue Sep 30, 2014 9:20 pm


I made a module to package up a groupoffice module. This involves
- converting the tables to an install.sql file
- copying theme info from master to all other themes
- zipping it all up

It's a work in progress (the first 2 things work), but it's still cool

Code: Select all

#!/usr/bin/env python3

from __future__ import print_function

import argparse
import subprocess
import pymysql
import re
import os
import sys
import shutil
# debug
from pprint import pprint

def read_groupoffice_config():
    """note: will break if do something like $config['example']='foo"bar';"""
    go_config = {}
    config_re = re.compile(r"""
            \$config\[['"] # matches $config['
                ([^'"]+)   # word
            ['"]\]=['"]    # ']='
                ([^'"]+)   # word
            ['"];          # ';
            """, re.X)
        with open('/etc/groupoffice/config.php', 'r') as f:
            for line in f:
                m = config_re.match(line)
                if m:
                    go_config[] =
        return go_config
    except IOError as e:
        raise IOError("Could not open /etc/groupoffice/config.php (check permissions)")

def main():
    # constants
    sql_get_tables = """
    WHERE table_name LIKE '{prefix}_%'
        OR table_name LIKE 'go_links_${prefix}_%'
        OR table_name LIKE 'go_cf_{prefix}_%'
        OR table_name LIKE 'cf_{prefix}_%'

    # Remove executing comments
    comments_re = re.compile(r"""
            ^\/\*!      # starts with /*!
            [0-9]{5}.*? # match 5 numbers than anything (non-greedy)
            \*\/;$\n    # ends with */\n;
            """, re.X | re.M)

    # Remove auto increment
    ai_re = re.compile(r"AUTO_INCREMENT=\d+ ")

    # Remove custom fields
    cf_re = re.compile(r"""
        CREATE\ TABLE\ `(cf_\w+)`\ \(\n
        \ \ `model_id`\ int\(11\)\ NOT\ NULL,\n
        PRIMARY\ KEY\ \(`model_id`\)
        """, re.X | re.S)

        go_config = read_groupoffice_config()
    except Exception as e:
        print(e, file=sys.stderr)
        go_config = {
            "db_name": "groupoffice",
            "db_pass": "groupoffice",
            "db_user": "groupoffice"

    p = argparse.ArgumentParser(description="""Run utility transformations
    on groupoffice custom modules""")
    p.add_argument('-a', '--all', action="store_true", default=False,
            help="enable all stages")
    p.add_argument('-d', '--database', action="store_true", default=False,
            help="enable install.sql generation stage")
    p.add_argument('-t', '--theme', action="store_true", default=False,
            help="create the InnerCircles theme from Default theme")
    p.add_argument('-T', '--tar', action="store_true", default=False,
            help="create a zip of all the module for easy install")
    p.add_argument('--db_name', default=go_config["db_name"],
            help="the name of the groupoffice database")
    p.add_argument('--db_pass', default=go_config["db_pass"],
            help="the passwored of the groupoffice database")
    p.add_argument('--db_user', default=go_config["db_user"],
            help="the username for the groupoffice database")
    p.add_argument('--module', help="the module name", default=\
            os.path.split(os.getcwd())[-1]) # directory name
    p.add_argument('--style_source', default='Default',
            help="the directory to copy style info from")
    p.add_argument('--style_dest', default='InnerCircles',
            help="the directories to copy style info to, separated by "
                "commas (no spaces)")
    args = p.parse_args()

    if args.all or args.database:
        conn = pymysql.connect(host='localhost', port=3306, user=args.db_user,
                passwd=args.db_pass, db=args.db_name)
        cur = conn.cursor()
        tables = cur.fetchone()[0]
        if not tables or not tables.strip():
            raise Exception("Cannot find any tables with prefix {prefix}"\
        install = str(subprocess.check_output(['mysqldump', args.db_name] + \
                list(tables.split(' ')) + \
                ['--no-data', '--user='+args.db_user, '--password='+args.db_pass]))
        install = ai_re.sub('', comments_re.sub('', install))
        install = cf_re.sub("CREATE TABLE `\\1` (\n"
              "  `model_id` int(11) NOT NULL,\n"
              "  PRIMARY KEY (`model_id`)", install)
        with open(os.path.join('install','install.sql'), 'w') as f:

    if (args.all or args.theme) and args.style_dest:
        os.makedirs(os.path.join('views', 'Extjs3', 'themes', args.style_source),
                mode=0o755, exist_ok=True)
        for dest in args.style_dest.split(','):
            shutil.rmtree(os.path.join('views', 'Extjs3', 'themes', dest),
                os.path.join('views', 'Extjs3', 'themes', args.style_source),
                os.path.join('views', 'Extjs3', 'themes', dest)

if __name__ == '__main__':

Who is online

Users browsing this forum: No registered users and 2 guests