# -*- coding: utf-8 -*-
# Mathmaker creates automatically maths exercises sheets
# with their answers
# Copyright 2006-2017 Nicolas Hainaux <nh.techn@gmail.com>
# This file is part of Mathmaker.
# Mathmaker 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; either version 3 of the License, or
# any later version.
# Mathmaker 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 Mathmaker; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import os
import logging
import logging.config
from glob import glob
from pathlib import Path
from shutil import copyfile
from mathmaker import __version__, __software_name__
from mathmaker.lib.tools import ext_dict, load_config
AVAILABLE = {'LANGUAGES': ['fr', 'fr_FR', 'en', 'en_US', 'en_GB'],
'CURRENCY': {'fr': 'euro', 'fr_FR': 'euro',
'en': 'dollar', 'en_US': 'dollar',
'en_GB': 'sterling'}}
[docs]class ContextFilter(logging.Filter):
"""
Removes the 'dbg.' at the beginning of logged messages.
"""
[docs] def filter(self, record):
record.name = record.name[4:]
return True
[docs]def config_dbglogger(sd):
"""
Configures dbg_logger, using to the configuration file values.
"""
d = ext_dict(load_config('debug_conf', sd)).flat()
for loggername, level in d.items():
lg = logging.getLogger(loggername)
lg.setLevel(getattr(logging, level))
lg.addFilter(ContextFilter())
if loggername in ['dbg.db', 'dbg.db_lock', 'dbg.db_timestamp',
'dbg.Exercise.init']:
raw_logger = logging.getLogger('raw')
lg.addHandler(raw_logger.handlers[0])
lg.propagate = False
[docs]class default_object(object):
def __init__(self):
self.MONOMIAL_LETTER = 'x'
self.EQUATION_NAME = 'E'
[docs]class path_object(object):
def __init__(self, dd=None, logger=None):
self.db = dd + '{}-{}.db'.format(__software_name__, __version__)
self.db_dist = dd + '{}.db-dist'.format(__software_name__)
self.natural_nb_tuples_db = dd + 'natural_nb_tuples-{}.db'\
.format(__version__)
self.natural_nb_tuples_db_dist = dd + 'natural_nb_tuples.db-dist'
self.daemon_db = dd + '{}d.db'.format(__software_name__)
self.shapes_db = dd + 'shapes-{}.db'.format(__version__)
self.shapes_db_dist = dd + 'shapes.db-dist'
self.solids_db = dd + 'solids-{}.db'.format(__version__)
self.solids_db_dist = dd + 'solids.db-dist'
self.anglessets_db = dd + 'anglessets-{}.db'.format(__version__)
self.anglessets_db_dist = dd + 'anglessets.db-dist'
logger.info('db={}'.format(self.db))
logger.info('shapes db={}'.format(self.shapes_db))
logger.info('solids db={}'.format(self.solids_db))
logger.info('anglessets db={}'.format(self.anglessets_db))
logger.info('natural_nb_tuples db={}'
.format(self.natural_nb_tuples_db))
if (not os.path.isfile(self.db)
or os.path.getmtime(self.db) < os.path.getmtime(self.db_dist)):
logger.info('Copy main db from {}\n'.format(self.db_dist))
copyfile(self.db_dist, self.db)
if (not os.path.isfile(self.shapes_db)
or os.path.getmtime(self.shapes_db)
< os.path.getmtime(self.shapes_db_dist)):
logger.info('Copy shapes db from {}\n'
.format(self.shapes_db_dist))
copyfile(self.shapes_db_dist, self.shapes_db)
if (not os.path.isfile(self.solids_db)
or os.path.getmtime(self.solids_db)
< os.path.getmtime(self.solids_db_dist)):
logger.info('Copy solids db from {}\n'
.format(self.solids_db_dist))
copyfile(self.solids_db_dist, self.solids_db)
if (not os.path.isfile(self.anglessets_db)
or os.path.getmtime(self.anglessets_db)
< os.path.getmtime(self.anglessets_db_dist)):
logger.info('Copy anglessets db from {}\n'
.format(self.anglessets_db_dist))
copyfile(self.anglessets_db_dist, self.anglessets_db)
if (not os.path.isfile(self.natural_nb_tuples_db)
or os.path.getmtime(self.natural_nb_tuples_db)
< os.path.getmtime(self.natural_nb_tuples_db_dist)):
logger.info('Copy natural_nb_tuples db from {}\n'
.format(self.natural_nb_tuples_db_dist))
copyfile(self.natural_nb_tuples_db_dist, self.natural_nb_tuples_db)
[docs]def init():
global rootdir, localedir, libdir, datadir, settingsdir
global projectdir
global outputdir
global toolsdir
global testsdir
global frameworksdir
global index_path
global db_index_path
global shapes_db_index_path
global solids_db_index_path
global anglessets_db_index_path
global natural_nb_tuples_db_index_path
global default, path
global mainlogger
global dbg_logger
global daemon_logger
global output_watcher_logger
global language
global locale
global currency
global font
global q_numbering_tpl
global q_numbering_tpl_weight
global q_numbering_tpl_slideshows
global q_numbering_tpl_weight_slideshows
global fonts_list_file
global encoding
global xmllint
global euktoeps
global lualatex
global luaotfload_tool
global msgfmt
global round_letters_in_math_expr
global mm_executable
global available_wNl
global luatex_version
luatex_version = ''
settings_dirname = "settings/"
__process_name = os.path.basename(__file__)
__abspath = os.path.abspath(__file__)
__l1 = len(__process_name)
__l2 = len(__abspath)
rootdir = __abspath[:__l2 - __l1][:-(len(settings_dirname))]
testsdir = os.path.join(Path(rootdir).parent, 'tests')
localedir = rootdir + "locale/"
libdir = rootdir + "lib/"
datadir = rootdir + "data/"
fonts_list_file = datadir + 'fonts_list.txt'
toolsdir = rootdir + 'tools/'
frameworksdir = datadir + 'frameworks/'
index_path = frameworksdir + 'index.json'
db_index_path = datadir + 'db_index.json'
shapes_db_index_path = datadir + 'shapes_db_index.json'
solids_db_index_path = datadir + 'solids_db_index.json'
anglessets_db_index_path = datadir + 'anglessets_db_index.json'
natural_nb_tuples_db_index_path = \
datadir + 'natural_nb_tuples_db_index.json'
settingsdir = rootdir + settings_dirname
projectdir = rootdir[:-len('mathmaker/')]
available_wNl = sorted([int(os.path.basename(dirname)[1])
for dirname in glob(datadir + 'w*l')])
default = default_object()
logging.config.dictConfig(load_config('logging', settingsdir))
mainlogger = logging.getLogger("__main__")
mainlogger.info("Starting...")
dbg_logger = logging.getLogger("dbg")
config_dbglogger(settingsdir)
daemon_logger = logging.getLogger('__daemon__')
output_watcher_logger = logging.getLogger("__output_watcher__")
path = path_object(dd=datadir, logger=mainlogger)
CONFIG = load_config('user_config', settingsdir)
xmllint = CONFIG["PATHS"]["XMLLINT"]
lualatex = CONFIG["PATHS"]["LUALATEX"]
luaotfload_tool = CONFIG["PATHS"]["LUAOTFLOAD_TOOL"]
msgfmt = CONFIG["PATHS"]["MSGFMT"]
euktoeps = CONFIG["PATHS"]["EUKTOEPS"]
mm_executable = CONFIG["DAEMON"]["MATHMAKER_EXECUTABLE"]
language = CONFIG['LOCALES'].get('LANGUAGE', 'en_US')
if language not in AVAILABLE['LANGUAGES']:
language = 'en_US'
mainlogger.warning('The language was overriden by an unsupported '
'value (' + str(language) + ') in a '
'a configuration file.')
encoding = CONFIG['LOCALES'].get('ENCODING', 'UTF-8')
if encoding is None:
encoding = 'UTF-8'
mainlogger.warning('The encoding was overriden by None in '
'a configuration file.')
currency = CONFIG['LOCALES'].get('CURRENCY',
AVAILABLE['CURRENCY'][language])
if currency is None:
currency = AVAILABLE['CURRENCY'][language]
if currency not in iter(AVAILABLE['CURRENCY'].values()):
currency = AVAILABLE['CURRENCY'][language]
font = CONFIG['LATEX'].get('FONT') # defaults to None in all cases
q_numbering_tpl = CONFIG['DOCUMENT'].get('QUESTION_NUMBERING_TEMPLATE')
q_numbering_tpl_weight = CONFIG['DOCUMENT']\
.get('QUESTION_NUMBERING_TEMPLATE_WEIGHT')
q_numbering_tpl_slideshows = CONFIG['DOCUMENT']\
.get('QUESTION_NUMBERING_TEMPLATE_SLIDESHOWS')
q_numbering_tpl_weight_slideshows = CONFIG['DOCUMENT']\
.get('QUESTION_NUMBERING_TEMPLATE_WEIGHT_SLIDESHOWS')
# The locale must be redefined after command line options are known
locale = language + '.' + encoding
config_path = CONFIG['PATHS'].get('OUTPUT_DIR')
if os.path.isabs(config_path):
msg = 'The path to outfiles read from the configuration ({}) is ' \
'absolute. It must be a relative path.'.format(config_path)
mainlogger.error(msg)
raise ValueError(msg)
outputdir = os.path.join(Path.home(), config_path)
if not os.path.isdir(outputdir):
mainlogger.warning('The output directory read from the '
'configuration ({}) does not exist.'
.format(outputdir))
try:
Path(outputdir).mkdir(parents=True)
except Exception as e:
mainlogger.exception('Impossible to create the missing output '
'directory')
raise
mainlogger.warning('Created the output directory read from the '
'configuration.')
round_letters_in_math_expr = CONFIG['LATEX']\
.get('ROUND_LETTERS_IN_MATH_EXPR', False)