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