rel
[librarian.git] / src / librarian / embeds / __init__.py
1 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
3 #
4 import importlib
5 from lxml import etree
6
7 known_types = {
8     'application/mathml+xml': 'librarian.embeds.mathml.MathML',
9     'application/x-latex': 'librarian.embeds.latex.LaTeX',
10 }
11
12
13 class Embed():
14     @classmethod
15     def transforms_to(cls, mime_types, downgrade=False):
16         matches = set()
17         for name, method in cls.__dict__.iteritems():
18             if hasattr(method, "embed_converts_to"):
19                 conv_type, conv_downgrade = method.embed_converts_to
20                 if downgrade == conv_downgrade and conv_type in mime_types:
21                     matches.add(conv_type)
22         return matches
23
24     def transform_to(self, mime_type, downgrade=False):
25         for name, method in type(self).__dict__.iteritems():
26             if hasattr(method, "embed_converts_to"):
27                 conv_type, conv_downgrade = method.embed_converts_to
28                 if downgrade == conv_downgrade and conv_type == mime_type:
29                     return method(self)
30
31
32 class DataEmbed(Embed):
33     def __init__(self, data=None):
34         self.data = data
35
36
37 class TreeEmbed(Embed):
38     def __init__(self, tree=None):
39         if isinstance(tree, etree._Element):
40             tree = etree.ElementTree(tree)
41         self.tree = tree
42
43
44 def converts_to(mime_type, downgrade=False):
45     def decorator(method):
46         method.embed_converts_to = mime_type, downgrade
47         return method
48     return decorator
49
50
51 def downgrades_to(mime_type):
52     return converts_to(mime_type, True)
53
54
55 def create_embed(mime_type, tree=None, data=None):
56     embed = known_types.get(mime_type)
57     if embed is None:
58         embed = DataEmbed if tree is None else TreeEmbed
59     else:
60         mod_name, cls_name = embed.rsplit('.', 1)
61         mod = importlib.import_module(mod_name)
62         embed = getattr(mod, cls_name)
63
64     return embed(data if tree is None else tree)