diff options
Diffstat (limited to 'sandbox/paultremblay/python_interface/docutilsToFo/make_stylesheet.py')
| -rw-r--r-- | sandbox/paultremblay/python_interface/docutilsToFo/make_stylesheet.py | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/sandbox/paultremblay/python_interface/docutilsToFo/make_stylesheet.py b/sandbox/paultremblay/python_interface/docutilsToFo/make_stylesheet.py new file mode 100644 index 000000000..ce93742dd --- /dev/null +++ b/sandbox/paultremblay/python_interface/docutilsToFo/make_stylesheet.py @@ -0,0 +1,418 @@ +#! /Library/Frameworks/Python.framework/Versions/2.7/bin/python +# $Id$ +import sys, copy, os, ConfigParser, pprint, types +from docutils_fo_dicts import * +from xml.sax import saxutils +class FOConfigFileException(Exception): + pass + +def dump(object): + pp = pprint.PrettyPrinter(indent=4) + sys.stderr.write(pp.pformat(object)) + sys.stderr.write('\n') + + +class Dump: + def __init__(self): + pass + +class WriteStylesheet: + + def __init__(self, verbose = 0): + self.__verbose = verbose + self.__string = '' + + def __write_start_element(self, name, atts): + pass + + def __write_end_element(self, name): + pass + + def __write_root_start(self): + self.__string += """<xsl:stylesheet + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:fo="http://www.w3.org/1999/XSL/Format" + version="1.1" + >\n\n""" + pass + + def __write_root_end(self): + self.__string +='</xsl:stylesheet>' + + def __write_att_sets(self): + self.__string += '\n <!--ATTRIBUTE SETS-->\n\n' + att_sets = self.__att_sets.keys() + for att_set in att_sets: + self.__string += ' <xsl:attribute-set name="%s">\n' % (att_set) + att_dict = self.__att_sets[att_set] + atts = att_dict.keys() + for att in atts: + self.__string += ' <xsl:attribute name="%s">' % (att) + self.__string += saxutils.escape(att_dict[att]) + self.__string += '</xsl:attribute>\n' + + self.__string += ' </xsl:attribute-set>\n\n' + + def __write_import(self): + self.__string += """ <xsl:import href= "%s"/>\n\n""" % (self.__import_ss) + + def __write_params(self): + self.__string += '\n <!--PARAMS-->\n\n' + the_keys = self.__params.keys() + the_keys.sort() + for the_key in the_keys: + value = saxutils.escape(self.__params[the_key]) + self.__string += ' <xsl:param name = "%s">%s</xsl:param>\n' % (the_key, value) + self.__string += '\n\n' + + def write_stylesheet(self, import_ss, params, att_sets, out=None): + self.__import_ss = import_ss + self.__params = params + self.__att_sets = att_sets + self.__out = out + self.__write_root_start() + self.__write_import() + self.__write_params() + self.__write_att_sets() + self.__write_root_end() + return self.__string + +class PostProcess: + + def __init__(self, params, attribute_sets): + self.__attribute_sets = attribute_sets + self.__params = params + + + # not used + def __test_measure(self, the_string): + """ + test if string is a measure: + 12pt returns 12, pt + 1.5 returns None, None + + """ + accept_units = ['em', 'px', 'in', 'cm', 'mm', 'pt', 'pc'] + try: + float(the_string) + return None, None + except ValueError: + pass + if len(the_string) < 3: + return None, None + unit = the_string[-2:] + if unit not in accept_units: + return None, None + num = the_string[:-2] + try: + num = float(num) + except ValueError: + return None, None + return num, unit + + # not used + def __get_default_font_size(self): + document_att_set = self.__attribute_sets.get('default-page-sequence') + body_att_set = self.__attribute_sets.get('default-flow') + if document_att_set and document_att_set.get('font-size'): + default_font_size = document_att_set.get('font-size') + elif body_att_set and document_att_set.get('font-size'): + default_font_size = body_att_set.get('font-size') + else: + default_font_size = '12pt' + num, unit = self.__test_measure(default_font_size) + if not num: + default_font_size = '12pt' + self.__default_font_size = default_font_size + + def __fix_header_footer(self): + # have to set the param spacing-header to extent, if not already set + #custom-spacing-header-footer + header_att_set = self.__attribute_sets.get('header-region-before') + if header_att_set: + extent = header_att_set.get('extent') + if extent and not self.__params.get('spacing-header'): + # self.__params['spacing-header'] = extent + self.__params['custom-spacing-header-footer'] = 'yes' + + footer_att_set = self.__attribute_sets.get('footer-region-after') + if footer_att_set: + extent = footer_att_set.get('extent') + if extent and not self.__params.get('spacing-footer'): + # self.__params['spacing-footer'] = extent + self.__params['custom-spacing-header-footer'] = 'yes' + + + def __fix_title(self): + doc_tit_att_set = self.__attribute_sets.get('document-title-page-block') + if doc_tit_att_set: + space_before = doc_tit_att_set.get('space-before') + if space_before: + self.__attribute_sets['document-title-page-block']['space-before.conditionality'] = 'retain' + + + def __get_page_layout(self): + odd_page = self.__attribute_sets.get('odd-simple-page-master') + even_page = self.__attribute_sets.get('even-simple-page-master') + first_page = self.__attribute_sets.get('first-simple-page-master') + suppress_first_header = self.__params.get('suppress-first-page-header') + suppress_first_footer = self.__params.get('suppress-first-page-footer') + need_odd_or_even_page = False + if odd_page or even_page: + need_odd_or_even_page = True + need_first_page = False + # if suppress_first_footer or suppress_first_header or first_page: + # need_first_page = True + + if self.__params.get('page-layout'): + page_layout = self.__params.get('page-layout') + elif need_first_page and need_odd_or_even_page: + page_layout = 'first-odd-even' + elif need_first_page: + page_layout = 'first' + elif need_odd_or_even_page: + page_layout = 'odd-even' + else: + page_layout = '' + self.__params['page-layout'] = page_layout + + + + + def post_process(self): + self.__get_default_font_size() + self.__fix_header_footer() + self.__get_page_layout() + self. __fix_title() + return self.__attribute_sets, self.__params + +class ReadConfig: + + def __init__(self, import_ss = None, verbose = 0, config_file = None): + self.__verbose = verbose + if self.__verbose > 4: + sys.stderr.write('modules is "%s"\n' % __file__) + self.__attribute_sets = {} + self.__params = {} + self.__import_ss = import_ss + if not self.__import_ss: + self.__import_ss = os.path.join(os.path.dirname(__file__), 'xsl_fo','docutils_to_fo.xsl') + if os.sep != '/': + self.__correct_path = self.__correct_path(self.__import_ss) + if not os.path.isfile(self.__import_ss): + msg = '"%s" cannot be found\n' % (self.__import_ss) + raise FOConfigFileException(msg) + if self.__verbose > 3: + sys.stderr.write('self.__import_ss (stylesheet to import) is "%s" \n' % self.__import_ss) + self.__config_file = config_file + if self.__verbose > 3 and self.__config_file: + sys.stderr.write('self.__config_file is "%s" \n' % self.__config_file) + + def __correct_path(self, the_path): + """ + make sure the_path is os.path.abs(the_path) and that + the_path really exits or this may not work + + """ + paths = [] + head = None + counter = 1 + while 1: + counter += 1 + if not head: + head = the_path + head, tail = os.path.split(head) + paths.insert(0,tail) + if not tail: + break + if counter > 100: + raise RuntimeError, 'max num recursions (100) reached' + return '/'.join(paths) + + def write_config_file(self, dest=None): + w = WriteStylesheet() + ss_string = w.write_stylesheet(import_ss = self.__import_ss, params = self.__params, + att_sets = self.__attribute_sets) + return ss_string + + + def read_config_files(self): + config = ConfigParser.SafeConfigParser() + config_files = [] + if self.__config_file: + config.read(self.__config_file) + return config + if os.environ.get('HOME'): + config_files.append(os.path.join(os.environ.get('HOME'), '.docutils')) + config_files.append(os.path.join(os.getcwd(), 'docutils.conf')) + for the_path in config_files: + config.read(the_path) + if self.__verbose > 4: + sys.stderr.write('config is: \n' ) + dump(config.items('FO')) + return config + + + def parse_config_files(self): + config = self.read_config_files() + self.__config = config + if not 'FO' in config.sections(): + return + opts = config.items('FO') + opts_dict = {} + for pair_tupple in opts: + first = pair_tupple[0] + second = pair_tupple[1] + fields = first.split('.', 1) + if prop_as_param_dict.get(first): + self.__handle_param(prop_as_param_dict.get(first), second) + elif len(fields) == 2: + self.__handle_attributes(fields[0], fields[1], second) + elif first in param_list: + self.__handle_param(first, second) + elif first in commands_list: + pass + else: + self.__error('"%s" = "%s" not a valid config option\n' % (first, second)) + + def __post_process(self): + post_process_obj = PostProcess(attribute_sets = self.__attribute_sets, params = self.__params) + self.__attribute_sets, self.__params = post_process_obj.post_process() + if self.__verbose > 4: + sys.stderr.write('self.__attribute_sets after post process:\n') + dump(self.__attribute_sets) + sys.stderr.write('self.__params after post process:\n') + dump(self.__params) + sys.stderr.write('\n') + + def __get_shortcut_att_set(self, user_att_set): + format = self.__get_config_option(option = 'option-list.format', default = 'list') + att_set = short_cut_att_sets.get(user_att_set) + if att_set: + return att_set + att_set = short_cut_att_sets2.get((user_att_set, format)) + if att_set: + return att_set + elif att_set == None: + return user_att_set + + def __get_special_set_att(self, user_att_set, user_att): + format = self.__get_config_option(option = 'option-list.format', default = 'list') + spc_att_set_att_list = special_att_set_att_dict.get((user_att_set, user_att)) + if spc_att_set_att_list: + return spc_att_set_att_list + spc_att_set_att_list = special_att_set_att_dict2.get((user_att_set, user_att, format)) + if spc_att_set_att_list: + return spc_att_set_att_list + + + def __handle_attributes(self, user_att_set, user_att, value, check_special = True, s=None): + if special_att_sets_dict.get(user_att_set) and check_special: + self.__handle_special_atts(user_att_set, user_att, value) + return + + # change both att-set and att + spc_att_set_att_list = self.__get_special_set_att(user_att_set, user_att) + if spc_att_set_att_list and check_special: + for new_pair in spc_att_set_att_list: + att_set = new_pair[0] + att = new_pair[1] + self.__add_attribute(att_set, att, value ) + return + att_set = self.__get_shortcut_att_set(user_att_set) + fo_element = att_set_dict.get(att_set) + + spc_att_val_list = special_att_value_dict.get((user_att, value)) + if spc_att_val_list and fo_element: + for new_pair in spc_att_val_list: + att = new_pair[0] + value = new_pair[1] + self.__add_attribute(att_set, att, value ) + return + + elif fo_element: # found a valid att-set + att = custom_atts.get(user_att) + if not att: # valid attriubute, according to FO standards + att = user_att + if att not in which_list.get(fo_element): + self.__error('%s not a valid value for att-set %s' % (user_att, user_att_set)) + else: + self.__add_attribute(att_set, att, value ) + else: + self.__error('%s not a valid attribute-set' % (user_att_set)) + + def __check_value(self, att, value): + special = special_values_dict.get(value) + if special: + if special[0] == att: + return special[1] + else: + return value + else: + return value + + def __add_attribute(self, att_set, att, value): + att_exists = self.__attribute_sets.get(att_set) + if not att_exists: + self.__attribute_sets[att_set] = {} + value = self.__check_value(att, value) + self.__attribute_sets[att_set][att] = value + + def __error(self, msg): + # sys.stderr.write(msg) + # sys.stderr.write('\n') + raise FOConfigFileException(msg) + + def __get_config_option(self, option, section = 'FO', default = None): + try: + option = self.__config.get('FO', 'option-list.format') + return option + except ConfigParser.NoOptionError: + return default + + def __handle_special_atts(self, user_att_set, user_att, value): + # for opt list as list + att_list_dict = {'space-from-option_off':'provisional-distance-between-starts'} + # for opt list as def + att_def_dict = {'':''} + att_def_not_allowed = ['space-from-option_', 'space-from-label_'] + if user_att_set == 'option-list': + format = self.__get_config_option(option = 'option-list.format', default = 'list') + if format == 'list': + changed_att = att_list_dict.get(user_att) + if changed_att: + user_att = changed_att + self.__handle_attributes('option-list', user_att, value, check_special = False) + elif format == 'definition': + if user_att in att_def_not_allowed: + self.__error('%s.%s = %s not a valid attribute property\n' % + (user_att_set, user_att, value)) + self.__handle_attributes('option-list-definition-block', + user_att, value, check_special = False) + else: + self.__error('%s.%s = %s not a valid attribute property\n' % (user_att_set, user_att, value)) + + + def __handle_param(self, param, value): + to_test_dict = param_dict_test.get(param) + if to_test_dict: + correct_value = to_test_dict.get(value) + if correct_value: + self.__params[param] = correct_value + else: + self.__error('%s = %s not a valid command\n' % (param, value)) + else: + self.__params[param] = value + + def make_stylesheet(self): + self.parse_config_files() + self.__post_process() + ss_string = self.write_config_file() + return ss_string + # self.print_att_list() + + +if __name__ == '__main__': + read_config_obj = ReadConfig(import_ss = '/Users/cynthia/tmp/paultremblay/xsl_fo/docutils_to_fo.xsl' ) + ss_string = read_config_obj.main() + print ss_string |
