1 #!/usr/bin/env python 2 3 """ 4 Metadata for document conversion. 5 6 Copyright (C) 2018 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 "input_format" : "moin", 35 "output_context" : "standalone", 36 "output_format" : "moin", 37 } 38 39 default_effects = { 40 "output_format" : "link_format", 41 } 42 43 effects = { 44 "input_context" : "input", 45 "input_format" : "parser", 46 "link_format" : "linker", 47 "output_context" : "output", 48 "output_format" : "serialiser", 49 "theme_name" : "theme", 50 } 51 52 def __init__(self, parameters=None): 53 54 "Initialise the metadata collection using the 'parameters'." 55 56 self.parameters = parameters or {} 57 58 def __repr__(self): 59 return "Metadata(%r)" % self.parameters 60 61 def copy(self): 62 63 "Return a copy of this instance." 64 65 parameters = {} 66 parameters.update(self.parameters) 67 return self.__class__(parameters) 68 69 def get(self, name, default=None): 70 71 """ 72 Return the setting for 'name', returning 'default' if 'name' is not 73 set. If 'default' is None or omitted and a default is present in the 74 defaults registry, this is returned if no setting is defined. 75 """ 76 77 value = self.parameters.get(name, default) 78 if value is None: 79 return self.defaults.get(name, default) 80 else: 81 return value 82 83 def has_key(self, name): 84 return self.parameters.has_key(name) 85 86 def set(self, name, value): 87 88 "Set 'name' as 'value' in the metadata." 89 90 self.parameters[name] = value 91 92 # Invalidate any affected setting. 93 94 affected = self.effects.get(name) 95 96 if affected and self.has_key(affected): 97 del self.parameters[affected] 98 99 # Set any default values. 100 101 affected = self.default_effects.get(name) 102 103 if affected and not self.get(affected): 104 self.set(affected, value) 105 106 def make_object(self, name, fn, typename, typevalue=None): 107 108 """ 109 Make an object to be stored in the setting 'name', using 'fn' to 110 acquire the object class, with the object type being retrieved from the 111 'typename' setting, this being overwritten by 'typevalue' if specified. 112 Return None if no class is obtained. 113 """ 114 115 # Return any existing object if not reset. 116 117 if not typevalue: 118 obj = self.get(name) 119 if obj: 120 return obj 121 122 # Overwrite any existing typename setting. 123 124 else: 125 self.set(typename, typevalue) 126 127 # Obtain the class. 128 129 cls = fn(self.get(typename)) 130 131 if not cls: 132 self.set(name, None) 133 return None 134 135 # Instantiate the class. 136 137 obj = cls(self) 138 self.set(name, obj) 139 return obj 140 141 def get_input(self, name=None): 142 143 """ 144 Make an input context using any given 'name' or otherwise using the 145 "input_context" setting which will be replaced by any given 'name'. 146 """ 147 148 return self.make_object("input", get_input, "input_context", name) 149 150 def get_linker(self, name=None): 151 152 """ 153 Make a linker using any given 'name' or otherwise using the 154 "link_format" setting which will be replaced by any given 'name'. 155 """ 156 157 return self.make_object("linker", get_linker, "link_format", name) 158 159 def get_output(self, name=None): 160 161 """ 162 Make an output context using any given 'name' or otherwise using the 163 "output_context" setting which will be replaced by any given 'name'. 164 """ 165 166 return self.make_object("output", get_output, "output_context", name) 167 168 def get_parser(self, name=None): 169 170 """ 171 Make a parser using any given 'name' or otherwise using the 172 "input_format" setting which will be replaced by any given 'name'. 173 """ 174 175 parser = self.make_object("parser", get_parser, "input_format", name) 176 parser.parsers = parsers 177 return parser 178 179 def get_serialiser(self, name=None): 180 181 """ 182 Make a serialiser using any given 'name' or otherwise using the 183 "output_format" setting which will be replaced by any given 'name'. 184 """ 185 186 serialiser = self.make_object("serialiser", get_serialiser, 187 "output_format", name) 188 serialiser.serialisers = serialisers 189 return serialiser 190 191 def get_theme(self, name=None): 192 193 """ 194 Make a theme using any given 'name' or otherwise using the "theme_name" 195 setting which will be replaced by any given 'name'. 196 """ 197 198 return self.make_object("theme", get_theme, "theme_name", name) 199 200 # vim: tabstop=4 expandtab shiftwidth=4