1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/moinformat/metadata.py Tue Aug 14 22:33:30 2018 +0200
1.3 @@ -0,0 +1,200 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +"""
1.7 +Metadata for document conversion.
1.8 +
1.9 +Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
1.10 +
1.11 +This program is free software; you can redistribute it and/or modify it under
1.12 +the terms of the GNU General Public License as published by the Free Software
1.13 +Foundation; either version 3 of the License, or (at your option) any later
1.14 +version.
1.15 +
1.16 +This program is distributed in the hope that it will be useful, but WITHOUT
1.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.19 +details.
1.20 +
1.21 +You should have received a copy of the GNU General Public License along with
1.22 +this program. If not, see <http://www.gnu.org/licenses/>.
1.23 +"""
1.24 +
1.25 +from moinformat.input import get_input
1.26 +from moinformat.links import get_linker
1.27 +from moinformat.output import get_output
1.28 +from moinformat.parsers import get_parser, parsers
1.29 +from moinformat.serialisers import get_serialiser, serialisers
1.30 +from moinformat.themes import get_theme
1.31 +
1.32 +class Metadata:
1.33 +
1.34 + "Metadata employed in the document conversion process."
1.35 +
1.36 + defaults = {
1.37 + "input_format" : "moin",
1.38 + "output_context" : "standalone",
1.39 + "output_format" : "moin",
1.40 + }
1.41 +
1.42 + default_effects = {
1.43 + "output_format" : "link_format",
1.44 + }
1.45 +
1.46 + effects = {
1.47 + "input_context" : "input",
1.48 + "input_format" : "parser",
1.49 + "link_format" : "linker",
1.50 + "output_context" : "output",
1.51 + "output_format" : "serialiser",
1.52 + "theme_name" : "theme",
1.53 + }
1.54 +
1.55 + def __init__(self, parameters=None):
1.56 +
1.57 + "Initialise the metadata collection using the 'parameters'."
1.58 +
1.59 + self.parameters = parameters or {}
1.60 +
1.61 + def __repr__(self):
1.62 + return "Metadata(%r)" % self.parameters
1.63 +
1.64 + def copy(self):
1.65 +
1.66 + "Return a copy of this instance."
1.67 +
1.68 + parameters = {}
1.69 + parameters.update(self.parameters)
1.70 + return self.__class__(parameters)
1.71 +
1.72 + def get(self, name, default=None):
1.73 +
1.74 + """
1.75 + Return the setting for 'name', returning 'default' if 'name' is not
1.76 + set. If 'default' is None or omitted and a default is present in the
1.77 + defaults registry, this is returned if no setting is defined.
1.78 + """
1.79 +
1.80 + value = self.parameters.get(name, default)
1.81 + if value is None:
1.82 + return self.defaults.get(name, default)
1.83 + else:
1.84 + return value
1.85 +
1.86 + def has_key(self, name):
1.87 + return self.parameters.has_key(name)
1.88 +
1.89 + def set(self, name, value):
1.90 +
1.91 + "Set 'name' as 'value' in the metadata."
1.92 +
1.93 + self.parameters[name] = value
1.94 +
1.95 + # Invalidate any affected setting.
1.96 +
1.97 + affected = self.effects.get(name)
1.98 +
1.99 + if affected and self.has_key(affected):
1.100 + del self.parameters[affected]
1.101 +
1.102 + # Set any default values.
1.103 +
1.104 + affected = self.default_effects.get(name)
1.105 +
1.106 + if affected and not self.get(affected):
1.107 + self.set(affected, value)
1.108 +
1.109 + def make_object(self, name, fn, typename, typevalue=None):
1.110 +
1.111 + """
1.112 + Make an object to be stored in the setting 'name', using 'fn' to
1.113 + acquire the object class, with the object type being retrieved from the
1.114 + 'typename' setting, this being overwritten by 'typevalue' if specified.
1.115 + Return None if no class is obtained.
1.116 + """
1.117 +
1.118 + # Return any existing object if not reset.
1.119 +
1.120 + if not typevalue:
1.121 + obj = self.get(name)
1.122 + if obj:
1.123 + return obj
1.124 +
1.125 + # Overwrite any existing typename setting.
1.126 +
1.127 + else:
1.128 + self.set(typename, typevalue)
1.129 +
1.130 + # Obtain the class.
1.131 +
1.132 + cls = fn(self.get(typename))
1.133 +
1.134 + if not cls:
1.135 + self.set(name, None)
1.136 + return None
1.137 +
1.138 + # Instantiate the class.
1.139 +
1.140 + obj = cls(self)
1.141 + self.set(name, obj)
1.142 + return obj
1.143 +
1.144 + def get_input(self, name=None):
1.145 +
1.146 + """
1.147 + Make an input context using any given 'name' or otherwise using the
1.148 + "input_context" setting which will be replaced by any given 'name'.
1.149 + """
1.150 +
1.151 + return self.make_object("input", get_input, "input_context", name)
1.152 +
1.153 + def get_linker(self, name=None):
1.154 +
1.155 + """
1.156 + Make a linker using any given 'name' or otherwise using the
1.157 + "link_format" setting which will be replaced by any given 'name'.
1.158 + """
1.159 +
1.160 + return self.make_object("linker", get_linker, "link_format", name)
1.161 +
1.162 + def get_output(self, name=None):
1.163 +
1.164 + """
1.165 + Make an output context using any given 'name' or otherwise using the
1.166 + "output_context" setting which will be replaced by any given 'name'.
1.167 + """
1.168 +
1.169 + return self.make_object("output", get_output, "output_context", name)
1.170 +
1.171 + def get_parser(self, name=None):
1.172 +
1.173 + """
1.174 + Make a parser using any given 'name' or otherwise using the
1.175 + "input_format" setting which will be replaced by any given 'name'.
1.176 + """
1.177 +
1.178 + parser = self.make_object("parser", get_parser, "input_format", name)
1.179 + parser.parsers = parsers
1.180 + return parser
1.181 +
1.182 + def get_serialiser(self, name=None):
1.183 +
1.184 + """
1.185 + Make a serialiser using any given 'name' or otherwise using the
1.186 + "output_format" setting which will be replaced by any given 'name'.
1.187 + """
1.188 +
1.189 + serialiser = self.make_object("serialiser", get_serialiser,
1.190 + "output_format", name)
1.191 + serialiser.serialisers = serialisers
1.192 + return serialiser
1.193 +
1.194 + def get_theme(self, name=None):
1.195 +
1.196 + """
1.197 + Make a theme using any given 'name' or otherwise using the "theme_name"
1.198 + setting which will be replaced by any given 'name'.
1.199 + """
1.200 +
1.201 + return self.make_object("theme", get_theme, "theme_name", name)
1.202 +
1.203 +# vim: tabstop=4 expandtab shiftwidth=4