1 #!/usr/bin/env python 2 3 """ 4 Metadata for document conversion. 5 6 Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from moinformat.input import get_input 23 from moinformat.links import get_linker 24 from moinformat.output import get_output 25 from moinformat.parsers import get_parser, parsers 26 from moinformat.serialisers import get_serialiser, serialisers 27 from moinformat.themes import get_theme 28 29 class Metadata: 30 31 "Metadata employed in the document conversion process." 32 33 defaults = { 34 "attachments" : "attachments", 35 "input_format" : "moin", 36 "output_context" : "standalone", 37 "output_format" : "moin", 38 "root_pagename" : "FrontPage", 39 } 40 41 default_effects = { 42 "output_format" : "link_format", 43 } 44 45 effects = { 46 "input_context" : "input", 47 "input_format" : "parser", 48 "input_separator" : "input", 49 "link_format" : "linker", 50 "output_context" : "output", 51 "output_format" : "serialiser", 52 "theme_name" : "theme", 53 } 54 55 def __init__(self, parameters=None): 56 57 "Initialise the metadata collection using the 'parameters'." 58 59 self.parameters = parameters or {} 60 61 def __repr__(self): 62 return "Metadata(%r)" % self.parameters 63 64 def copy(self): 65 66 "Return a copy of this instance." 67 68 parameters = {} 69 parameters.update(self.parameters) 70 return self.__class__(parameters) 71 72 def get(self, name, default=None): 73 74 """ 75 Return the setting for 'name', returning 'default' if 'name' is not 76 set. If 'default' is None or omitted and a default is present in the 77 defaults registry, this is returned if no setting is defined. 78 """ 79 80 value = self.parameters.get(name, default) 81 if value is None: 82 return self.defaults.get(name, default) 83 else: 84 return value 85 86 def has_key(self, name): 87 return self.parameters.has_key(name) 88 89 def set(self, name, value): 90 91 "Set 'name' as 'value' in the metadata." 92 93 self.parameters[name] = value 94 95 # Invalidate any affected setting. 96 97 affected = self.effects.get(name) 98 99 if affected and self.has_key(affected): 100 del self.parameters[affected] 101 102 # Set any default values. 103 104 affected = self.default_effects.get(name) 105 106 if affected and not self.get(affected): 107 self.set(affected, value) 108 109 def make_object(self, name, fn, typename, typevalue=None): 110 111 """ 112 Make an object to be stored in the setting 'name', using 'fn' to 113 acquire the object class, with the object type being retrieved from the 114 'typename' setting, this being overwritten by 'typevalue' if specified. 115 Return None if no class is obtained. 116 """ 117 118 # Return any existing object if not reset. 119 120 if not typevalue: 121 obj = self.get(name) 122 if obj: 123 return obj 124 125 # Overwrite any existing typename setting. 126 127 else: 128 self.set(typename, typevalue) 129 130 # Obtain the class. 131 132 cls = fn(self.get(typename)) 133 134 if not cls: 135 self.set(name, None) 136 return None 137 138 # Instantiate the class. 139 140 obj = cls(self) 141 self.set(name, obj) 142 return obj 143 144 def get_input(self, name=None): 145 146 """ 147 Make an input context using any given 'name' or otherwise using the 148 "input_context" setting which will be replaced by any given 'name'. 149 """ 150 151 return self.make_object("input", get_input, "input_context", name) 152 153 def get_linker(self, name=None): 154 155 """ 156 Make a linker using any given 'name' or otherwise using the 157 "link_format" setting which will be replaced by any given 'name'. 158 """ 159 160 return self.make_object("linker", get_linker, "link_format", name) 161 162 def get_output(self, name=None): 163 164 """ 165 Make an output context using any given 'name' or otherwise using the 166 "output_context" setting which will be replaced by any given 'name'. 167 """ 168 169 return self.make_object("output", get_output, "output_context", name) 170 171 def get_parser(self, name=None): 172 173 """ 174 Make a parser using any given 'name' or otherwise using the 175 "input_format" setting which will be replaced by any given 'name'. 176 """ 177 178 parser = self.make_object("parser", get_parser, "input_format", name) 179 parser.parsers = parsers 180 return parser 181 182 def get_serialiser(self, name=None): 183 184 """ 185 Make a serialiser using any given 'name' or otherwise using the 186 "output_format" setting which will be replaced by any given 'name'. 187 """ 188 189 serialiser = self.make_object("serialiser", get_serialiser, 190 "output_format", name) 191 serialiser.serialisers = serialisers 192 return serialiser 193 194 def get_theme(self, name=None): 195 196 """ 197 Make a theme using any given 'name' or otherwise using the "theme_name" 198 setting which will be replaced by any given 'name'. 199 """ 200 201 return self.make_object("theme", get_theme, "theme_name", name) 202 203 # vim: tabstop=4 expandtab shiftwidth=4