1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """
23 Defines the Citator, a class that glues together every aspect related
24 to citations. It reads and stores this information from an XML file,
25 making it easy to distribute per-journal citation styles for instance.
26
27 WARNING: this object loads python modules by their name. It might do
28 nasty things if the file comes from untrusted sources.
29 """
30
31
32 import logging
33 from Pyblio import Compat
34 from gettext import gettext as _
35
36 from Pyblio.Exceptions import ParserError
37
38 log = logging.getLogger('pyblio.cite.citator')
39
41 """ """
42
45
47 tree = Compat.ElementTree.ElementTree(file=fd)
48 root = tree.getroot()
49 if root.tag != 'pyblio-citator':
50 raise ParserError(_("file is not a Citator XML file"))
51
52 self.name = root.find('./name').text
53
54 def get_last(name):
55 name = root.find(name).text.strip()
56 idx = name.rfind('.')
57 return name[:idx], name[idx+1:]
58
59 self.style = get_last('./citation-style')
60 self.keys = get_last('./key-style')
61 self.order = get_last('./bibliography-order')
62 return
63
64 - def prepare(self, db, wp, extra_info=None):
65 """Link the citator with a specific database and word
66 processor. @extra_info is an optional function that will
67 return a string to store along with the entry, if the word
68 processor allows it.
69
70 Args:
71 db: Pyblio.Store.Database
72 wp: Pyblio.Cite.WP.IWordProcessor
73 extra_info: str = fn(Pyblio.Store.Key, Pyblio.Store.Database) or None
74 """
75
76 def load(path):
77 mod = __import__(path[0], {}, {}, [path[1]])
78 return getattr(mod, path[1])
79
80 self.m_style = load(self.style)
81 self.m_keys = load(self.keys)
82 self.m_order = load(self.order)
83
84 self.db = db
85 self.wp = wp
86 self.extra_info = extra_info or (lambda key, db: None)
87
88
89 self.formatter = self.m_style(self.db)
90
91
92 self.keygen = self.m_keys(self.db)
93
95 """ Force an update of keys and bibliography content """
96
97
98
99
100 known = self.wp.fetch()
101 log.info('fetched keys from document: %r' % known)
102
103 if known is not None:
104
105
106
107 self.keygen = self.m_keys(self.db)
108
109 to_update = {}
110 for uid, key, extra in known:
111 newkey = self.keygen.make_key(uid)
112 if newkey != key:
113 to_update[uid] = newkey
114
115 known = self.wp.update_keys(to_update)
116
117
118 insert = self.wp.update_biblio()
119
120 insert.begin_biblio()
121 for uid, key in self.m_order(known):
122 insert.begin_reference(key)
123 insert(self.formatter(self.db[uid]))
124 insert.end_reference(key)
125 insert.end_biblio()
126 return
127
128 - def cite(self, uids):
129 """ Insert the specified record identifiers in the current
130 document"""
131
132 keys = [(ref,
133 self.keygen.make_key(ref),
134 self.extra_info(ref, self.db)) for ref in uids]
135 self.wp.cite(keys, self.db)
136 return
137