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