2011-02-14 18:18:51 +00:00
|
|
|
#!/usr/bin/python
|
2011-03-24 19:04:02 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
|
|
|
|
|
|
|
###############################################################################
|
|
|
|
# OpenLP - Open Source Lyrics Projection #
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
# Copyright (c) 2008-2011 Raoul Snyman #
|
|
|
|
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
|
|
|
|
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
|
|
|
|
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
|
2011-05-24 20:47:05 +00:00
|
|
|
# Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode #
|
|
|
|
# Woldsund #
|
2011-03-24 19:04:02 +00:00
|
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
# This program is free software; you can redistribute it and/or modify it #
|
|
|
|
# under the terms of the GNU General Public License as published by the Free #
|
|
|
|
# Software Foundation; version 2 of the License. #
|
|
|
|
# #
|
|
|
|
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
|
|
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
|
|
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
|
|
|
# more details. #
|
|
|
|
# #
|
|
|
|
# You should have received a copy of the GNU General Public License along #
|
|
|
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
|
|
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
|
|
|
###############################################################################
|
2011-02-14 18:18:51 +00:00
|
|
|
|
|
|
|
# TODOs:
|
|
|
|
# - defaults for non-supplied expansions:
|
2011-03-24 19:04:02 +00:00
|
|
|
# template contains
|
2011-02-14 18:18:51 +00:00
|
|
|
|
|
|
|
import ConfigParser
|
|
|
|
import logging
|
|
|
|
import optparse
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
|
|
|
|
# variable expansion:
|
|
|
|
# - %(dog)s --- normal python expansion
|
|
|
|
# - %(dog%)s --- no python expansion, leave as is (stripping the trailing %)
|
2011-02-14 21:26:49 +00:00
|
|
|
# - %(dog:cat) --- if there is an expansion for dog, dog will be used;
|
|
|
|
# otherwise if cat exists cat will be used
|
|
|
|
# - %(dog=cat) --- if there is an expansion for dog, dog will be used;
|
|
|
|
# otherwise "cat" will be used
|
|
|
|
# re_conf = re.compile(r'(?<!%)%\((?P<key>[^\(]+?)\)s')
|
2011-03-24 19:04:02 +00:00
|
|
|
re_conf = re.compile(r'(?P<verbatim>%?)%\((?P<key>[^+=:&\)]+?)'
|
2011-02-14 21:26:49 +00:00
|
|
|
+ '(?:(?P<kind>[+=:&])(?P<default>[^\)]+))?\)(?P<type>s|d)')
|
|
|
|
|
|
|
|
def expand_variable(match, expansions, errors):
|
2011-02-14 18:18:51 +00:00
|
|
|
key = match.group('key')
|
|
|
|
kind = match.group('kind')
|
|
|
|
default = match.group('default')
|
|
|
|
typ = match.group('type')
|
|
|
|
verbatim = match.group('verbatim')
|
|
|
|
|
|
|
|
if verbatim:
|
|
|
|
return match.group(0)[1:]
|
|
|
|
|
|
|
|
# literal default
|
|
|
|
if kind == '=':
|
|
|
|
if key in expansions:
|
|
|
|
return expansions[key]
|
|
|
|
return default
|
|
|
|
|
|
|
|
# variable default
|
|
|
|
if kind == ':' and default in expansions:
|
|
|
|
return expansions[default]
|
|
|
|
|
|
|
|
if kind == '+' and default in expansions:
|
|
|
|
if key in expansions:
|
|
|
|
key = expansions[key]
|
|
|
|
if typ == 's':
|
|
|
|
return '%s%s' % (key, expansions[default])
|
|
|
|
if typ == 'd':
|
|
|
|
try:
|
|
|
|
return str(int(key) + int(expansions[default]))
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if kind == '&' and default in expansions:
|
|
|
|
if typ == 's':
|
|
|
|
return '%s%s' % (key, expansions[default])
|
|
|
|
if typ == 'd':
|
|
|
|
try:
|
|
|
|
return str(int(key) + int(expansions[default]))
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if key in expansions:
|
|
|
|
return expansions[key]
|
2011-03-24 19:04:02 +00:00
|
|
|
|
2011-02-14 18:18:51 +00:00
|
|
|
if not match.group(0) in errors:
|
|
|
|
errors.append(match.group(0))
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
options = None
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
|
|
|
# get config file
|
|
|
|
parser = optparse.OptionParser()
|
2011-02-14 21:26:49 +00:00
|
|
|
parser.add_option('-c', '--config', dest='config',
|
|
|
|
help='config file', metavar='CONFIG')
|
|
|
|
parser.add_option('-t', '--template', dest='template',
|
|
|
|
help='template file', metavar='TEMPLATE')
|
|
|
|
parser.add_option('-x', '--expandto', dest='expanded',
|
|
|
|
help='expanded file', metavar='EXPANDED')
|
|
|
|
parser.add_option('-e', '--echo', dest='echo',
|
|
|
|
help='echo variable', metavar='ECHOVAR')
|
2011-02-14 18:18:51 +00:00
|
|
|
|
|
|
|
(options, args) = parser.parse_args()
|
|
|
|
|
|
|
|
if not options.config:
|
|
|
|
parser.error('option --config|-c is required')
|
|
|
|
if not os.path.exists(options.config):
|
|
|
|
parser.error('config file "%s" does not exist' % options.config)
|
|
|
|
if not options.echo:
|
|
|
|
if not options.template:
|
|
|
|
parser.error('option --template|-t is required')
|
|
|
|
if not os.path.exists(options.template):
|
2011-02-14 21:26:49 +00:00
|
|
|
parser.error('template file "%s" does not exist' \
|
|
|
|
% options.template)
|
2011-02-14 18:18:51 +00:00
|
|
|
if not options.expanded:
|
|
|
|
parser.error('option --expandto|-e is required')
|
|
|
|
|
|
|
|
logHandler = logging.StreamHandler()
|
2011-02-14 21:26:49 +00:00
|
|
|
logHandler.setFormatter(logging.Formatter('%(asctime)s %(levelname)-8s '
|
|
|
|
+ ' %(message)s', '%a, %d %b %Y %H:%M:%S'))
|
2011-02-14 18:18:51 +00:00
|
|
|
logging.getLogger().addHandler(logHandler)
|
|
|
|
logging.getLogger().setLevel(logging.DEBUG)
|
|
|
|
|
|
|
|
config = ConfigParser.RawConfigParser()
|
|
|
|
config.readfp(open(options.config, 'r'))
|
|
|
|
|
|
|
|
if not config.has_section('openlp'):
|
2011-02-14 21:26:49 +00:00
|
|
|
logging.error('[expander] %s: config file "%s" lacks an [openlp] '
|
|
|
|
+ 'section', options.template, options.config)
|
2011-02-14 18:18:51 +00:00
|
|
|
|
|
|
|
expansions = dict()
|
|
|
|
for k in config.options('openlp'):
|
|
|
|
expansions[k] = config.get('openlp', k)
|
|
|
|
|
|
|
|
# commandline overrides?
|
|
|
|
for override in args:
|
|
|
|
if not '=' in override:
|
|
|
|
continue
|
2011-03-24 19:04:02 +00:00
|
|
|
|
2011-02-14 18:18:51 +00:00
|
|
|
(k, v) = override.split('=', 2)
|
|
|
|
expansions[k] = v
|
|
|
|
|
|
|
|
if options.echo:
|
|
|
|
if options.echo in expansions:
|
|
|
|
print expansions[options.echo]
|
|
|
|
sys.exit(0)
|
|
|
|
else:
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
# closure to capture expansions and errors variable
|
|
|
|
errors = []
|
|
|
|
expanded = []
|
2011-03-24 19:04:02 +00:00
|
|
|
|
2011-02-14 18:18:51 +00:00
|
|
|
try:
|
|
|
|
# try to expand the template
|
|
|
|
line = 0
|
|
|
|
faulty = False
|
|
|
|
|
|
|
|
template = open(options.template, 'r')
|
|
|
|
raw = template.readlines()
|
|
|
|
template.close()
|
|
|
|
|
|
|
|
def _expand(m):
|
2011-02-14 21:26:49 +00:00
|
|
|
return expand_variable(m, expansions = expansions, errors = errors)
|
2011-03-24 19:04:02 +00:00
|
|
|
|
2011-02-14 18:18:51 +00:00
|
|
|
for l in raw:
|
|
|
|
line += 1
|
2011-02-14 21:26:49 +00:00
|
|
|
exp = re_conf.sub(_expand, l)
|
2011-02-14 18:18:51 +00:00
|
|
|
if errors:
|
|
|
|
for key in errors:
|
2011-02-14 21:26:49 +00:00
|
|
|
logging.error('[expander] %s: line %d: could not expand '
|
|
|
|
+ 'key "%s"', options.template, line, key)
|
2011-02-14 18:18:51 +00:00
|
|
|
faulty = True
|
|
|
|
errors = []
|
|
|
|
else:
|
|
|
|
expanded.append(exp)
|
|
|
|
|
|
|
|
if faulty:
|
|
|
|
sys.exit(1)
|
|
|
|
|
2011-02-14 21:26:49 +00:00
|
|
|
# successfully expanded template, now backup potentially existing
|
|
|
|
# target file
|
2011-02-14 18:18:51 +00:00
|
|
|
targetFile = options.expanded % expansions
|
|
|
|
if os.path.exists(targetFile):
|
|
|
|
if os.path.exists('%s~' % targetFile):
|
|
|
|
os.unlink('%s~' % targetFile)
|
|
|
|
os.rename(options.expanded, '%s~' % targetFile)
|
2011-02-14 21:26:49 +00:00
|
|
|
logging.info('[expander] %s: backed up existing target file "%s" '
|
|
|
|
+ 'to "%s"', options.template, targetFile,
|
|
|
|
'%s~' % options.expanded)
|
2011-02-14 18:18:51 +00:00
|
|
|
|
2011-02-14 21:26:49 +00:00
|
|
|
# make sure that target directory exists
|
2011-02-14 18:18:51 +00:00
|
|
|
targetDir = os.path.dirname(targetFile)
|
|
|
|
if not os.path.exists(targetDir):
|
|
|
|
os.makedirs(targetDir)
|
|
|
|
|
|
|
|
# write target file
|
|
|
|
try:
|
|
|
|
target = open(targetFile, 'w')
|
|
|
|
for exp in expanded:
|
|
|
|
target.write(exp)
|
|
|
|
target.close()
|
|
|
|
except Exception, e:
|
2011-02-14 21:26:49 +00:00
|
|
|
logging.error('[expander] %s: could not expand to "%s"',
|
|
|
|
options.template, options.expaned, e)
|
2011-02-14 18:18:51 +00:00
|
|
|
|
|
|
|
# copy over file access mode from template
|
|
|
|
mode = os.stat(options.template)
|
|
|
|
os.chmod(options.expanded, mode.st_mode)
|
|
|
|
|
|
|
|
logging.info('[expander] expanded "%s" to "%s"',
|
|
|
|
options.template, options.expanded)
|
2011-03-24 19:04:02 +00:00
|
|
|
|
2011-02-14 18:18:51 +00:00
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|