Merge lp:~matthias-troffaes/pybtex/even-simpler-plugin-loader into lp:pybtex
- even-simpler-plugin-loader
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 893 |
Proposed branch: | lp:~matthias-troffaes/pybtex/even-simpler-plugin-loader |
Merge into: | lp:pybtex |
Diff against target: |
1037 lines (+313/-345) 33 files modified
pybtex/__init__.py (+2/-2) pybtex/backends/__init__.py (+2/-5) pybtex/backends/html.py (+1/-3) pybtex/backends/latex.py (+1/-3) pybtex/backends/plaintext.py (+1/-4) pybtex/bibtex/__init__.py (+1/-1) pybtex/database/input/__init__.py (+1/-2) pybtex/database/input/bibtex.py (+1/-2) pybtex/database/input/bibtexml.py (+1/-2) pybtex/database/input/bibyaml.py (+1/-3) pybtex/database/output/__init__.py (+0/-1) pybtex/database/output/bibtex.py (+0/-2) pybtex/database/output/bibtexml.py (+0/-3) pybtex/database/output/bibyaml.py (+0/-4) pybtex/plugin/__init__.py (+122/-119) pybtex/plugin/make_registry.py (+0/-63) pybtex/plugin/registry.py (+0/-103) pybtex/style/formatting/__init__.py (+0/-1) pybtex/style/formatting/alpha.py (+0/-1) pybtex/style/formatting/plain.py (+0/-1) pybtex/style/formatting/unsrt.py (+0/-1) pybtex/style/formatting/unsrtalpha.py (+0/-1) pybtex/style/labels/__init__.py (+0/-4) pybtex/style/labels/alpha.py (+0/-1) pybtex/style/labels/number.py (+0/-1) pybtex/style/names/__init__.py (+0/-5) pybtex/style/names/lastfirst.py (+0/-2) pybtex/style/names/plain.py (+0/-1) pybtex/style/sorting/__init__.py (+0/-2) pybtex/style/sorting/author_year_title.py (+0/-1) pybtex/style/sorting/none.py (+0/-1) pybtex/tests/plugin_test.py (+119/-0) setup.py (+60/-0) |
To merge this branch: | bzr merge lp:~matthias-troffaes/pybtex/even-simpler-plugin-loader |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrey Golovizin | Approve | ||
Review via email: mp+200667@code.launchpad.net |
Commit message
Description of the change
An implementation just using entry points for all plugins.
Matthias C. M. Troffaes (matthias-troffaes) wrote : | # |
Andrey Golovizin (ero-sennin) wrote : | # |
This makes sense.
There are some things though.
- I'd want to keep Plugin.name, Plugin.aliases and Plugin.suffixes. The idea is that all information about a plugin should be contained in a plugin itself and not be scattered all over. Also, this way it would be possible to call register_
- Please add a license header to plugin_test.py and use two blank lines between top-level definitions. (Just a nitpick.)
Matthias C. M. Troffaes (matthias-troffaes) wrote : | # |
Ok, great! License & pep8 fixes are of course no problem.
Concerning the first point, I sort of convinced myself that, eventually, names/aliases/
Could you bring yourself to think of name, aliases, and suffixes as belonging to the registry system, rather than belonging to the Plugin classes?
Andrey Golovizin (ero-sennin) wrote : | # |
Yes, I think you are right here. So, let's have it merged after you finish with PEP8 fixes.
Matthias C. M. Troffaes (matthias-troffaes) wrote : | # |
(Sorry for the not so quick response.)
Ok, very good! I'll fix the pep8 issue as soon as I find some spare time.
Matthias C. M. Troffaes (matthias-troffaes) wrote : | # |
Ready for review.
Andrey Golovizin (ero-sennin) wrote : | # |
> Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 Andrey Golovizin
Should be "Copyright (c) 2014 Matthias C. M. Troffaes" instead. :) And you should add a line with your name to pybtex/
- 928. By Matthias C. M. Troffaes
-
Update copyright notices.
Matthias C. M. Troffaes (matthias-troffaes) wrote : | # |
Ok, done.
Andrey Golovizin (ero-sennin) wrote : | # |
Great, merged. Thanks for the good work!
Preview Diff
1 | === modified file 'pybtex/__init__.py' |
2 | --- pybtex/__init__.py 2013-08-08 18:12:52 +0000 |
3 | +++ pybtex/__init__.py 2014-02-04 13:09:32 +0000 |
4 | @@ -48,7 +48,7 @@ |
5 | encoding=bib_encoding, |
6 | wanted_entries=aux_data.citations, |
7 | min_crossrefs=min_crossrefs, |
8 | - ).parse_files(aux_data.data, bib_parser.get_default_suffix()) |
9 | + ).parse_files(aux_data.data, bib_parser.default_suffix) |
10 | |
11 | if style is None: |
12 | style = aux_data.style |
13 | @@ -63,5 +63,5 @@ |
14 | formatted_bibliography = style.format_bibliography(bib_data, aux_data.citations) |
15 | |
16 | output_backend = find_plugin('pybtex.backends', output_backend) |
17 | - output_filename = filename + output_backend.get_default_suffix() |
18 | + output_filename = filename + output_backend.default_suffix |
19 | output_backend(output_encoding).write_to_file(formatted_bibliography, output_filename) |
20 | |
21 | === modified file 'pybtex/backends/__init__.py' |
22 | --- pybtex/backends/__init__.py 2013-08-08 11:51:24 +0000 |
23 | +++ pybtex/backends/__init__.py 2014-02-04 13:09:32 +0000 |
24 | @@ -24,12 +24,9 @@ |
25 | from pybtex.utils import deprecated |
26 | |
27 | |
28 | -available_plugins = ('latex', 'html', 'plaintext') |
29 | - |
30 | - |
31 | class BaseBackend(Plugin): |
32 | - default_plugin = 'latex' |
33 | - RenderType = basestring #: the result of render and render_sequence |
34 | + RenderType = basestring #: the result of render and render_sequence |
35 | + default_suffix = None #: the default suffix for an output file |
36 | |
37 | def __init__(self, encoding=None): |
38 | self.encoding = encoding |
39 | |
40 | === modified file 'pybtex/backends/html.py' |
41 | --- pybtex/backends/html.py 2013-08-09 19:30:08 +0000 |
42 | +++ pybtex/backends/html.py 2014-02-04 13:09:32 +0000 |
43 | @@ -35,9 +35,7 @@ |
44 | """ |
45 | |
46 | class Backend(BaseBackend): |
47 | - name = 'html' |
48 | - suffixes = '.html', |
49 | - |
50 | + default_suffix = '.html' |
51 | symbols = { |
52 | 'ndash': u'–', |
53 | 'newblock': u'\n', |
54 | |
55 | === modified file 'pybtex/backends/latex.py' |
56 | --- pybtex/backends/latex.py 2013-08-09 19:38:46 +0000 |
57 | +++ pybtex/backends/latex.py 2014-02-04 13:09:32 +0000 |
58 | @@ -23,9 +23,7 @@ |
59 | |
60 | |
61 | class Backend(BaseBackend): |
62 | - name = 'latex' |
63 | - suffixes = '.bbl', '.tex', '.latex' |
64 | - |
65 | + default_suffix = '.bbl' |
66 | symbols = { |
67 | 'ndash': u'--', |
68 | 'newblock': u'\n\\newblock ', |
69 | |
70 | === modified file 'pybtex/backends/plaintext.py' |
71 | --- pybtex/backends/plaintext.py 2013-08-09 19:30:08 +0000 |
72 | +++ pybtex/backends/plaintext.py 2014-02-04 13:09:32 +0000 |
73 | @@ -23,10 +23,7 @@ |
74 | |
75 | |
76 | class Backend(BaseBackend): |
77 | - name = 'plaintext' |
78 | - aliases = 'text', |
79 | - suffixes = '.txt', |
80 | - |
81 | + default_suffix = '.txt' |
82 | symbols = { |
83 | 'ndash': u'-', |
84 | 'newblock': u' ', |
85 | |
86 | === modified file 'pybtex/bibtex/__init__.py' |
87 | --- pybtex/bibtex/__init__.py 2013-08-08 18:12:52 +0000 |
88 | +++ pybtex/bibtex/__init__.py 2014-02-04 13:09:32 +0000 |
89 | @@ -50,7 +50,7 @@ |
90 | bst_script = bst.parse_file(bst_filename, bst_encoding) |
91 | base_filename = path.splitext(aux_filename)[0] |
92 | bbl_filename = base_filename + path.extsep + 'bbl' |
93 | - bib_filenames = [filename + bib_format.get_default_suffix() for filename in aux_data.data] |
94 | + bib_filenames = [filename + bib_format.default_suffix for filename in aux_data.data] |
95 | bbl_file = pybtex.io.open_unicode(bbl_filename, 'w', encoding=output_encoding) |
96 | interpreter = Interpreter(bib_format, bib_encoding) |
97 | interpreter.run(bst_script, aux_data.citations, bib_filenames, bbl_file, min_crossrefs=min_crossrefs) |
98 | |
99 | === modified file 'pybtex/database/input/__init__.py' |
100 | --- pybtex/database/input/__init__.py 2012-02-12 20:44:25 +0000 |
101 | +++ pybtex/database/input/__init__.py 2014-02-04 13:09:32 +0000 |
102 | @@ -30,9 +30,8 @@ |
103 | |
104 | |
105 | class BaseParser(Plugin): |
106 | - default_plugin = 'bibtex' |
107 | + default_suffix = None |
108 | filename = '<INPUT>' |
109 | - |
110 | unicode_io = False |
111 | |
112 | def __init__(self, encoding=None, wanted_entries=None, min_crossrefs=2, **kwargs): |
113 | |
114 | === modified file 'pybtex/database/input/bibtex.py' |
115 | --- pybtex/database/input/bibtex.py 2013-07-31 13:35:20 +0000 |
116 | +++ pybtex/database/input/bibtex.py 2014-02-04 13:09:32 +0000 |
117 | @@ -296,8 +296,7 @@ |
118 | |
119 | |
120 | class Parser(BaseParser): |
121 | - name = 'bibtex' |
122 | - suffixes = '.bib', |
123 | + default_suffix = '.bib' |
124 | unicode_io = True |
125 | |
126 | macros = None |
127 | |
128 | === modified file 'pybtex/database/input/bibtexml.py' |
129 | --- pybtex/database/input/bibtexml.py 2012-02-12 20:44:25 +0000 |
130 | +++ pybtex/database/input/bibtexml.py 2014-02-04 13:09:32 +0000 |
131 | @@ -32,8 +32,7 @@ |
132 | return s[len(bibtexns):] |
133 | |
134 | class Parser(BaseParser): |
135 | - name = 'bibtexml' |
136 | - suffixes = '.xml', '.bibtexml' |
137 | + default_suffix = '.xml' |
138 | |
139 | def parse_stream(self, stream): |
140 | t = ET.parse(stream) |
141 | |
142 | === modified file 'pybtex/database/input/bibyaml.py' |
143 | --- pybtex/database/input/bibyaml.py 2012-02-12 20:44:25 +0000 |
144 | +++ pybtex/database/input/bibyaml.py 2014-02-04 13:09:32 +0000 |
145 | @@ -25,9 +25,7 @@ |
146 | |
147 | |
148 | class Parser(BaseParser): |
149 | - name = 'bibyaml' |
150 | - aliases = 'yaml', |
151 | - suffixes = '.yaml', '.bibyaml' |
152 | + default_suffix = '.yaml' |
153 | |
154 | def parse_stream(self, stream): |
155 | t = yaml.safe_load(stream) |
156 | |
157 | === modified file 'pybtex/database/output/__init__.py' |
158 | --- pybtex/database/output/__init__.py 2012-02-12 20:44:25 +0000 |
159 | +++ pybtex/database/output/__init__.py 2014-02-04 13:09:32 +0000 |
160 | @@ -27,7 +27,6 @@ |
161 | |
162 | class BaseWriter(Plugin): |
163 | unicode_io = False |
164 | - default_plugin = 'bibtex' |
165 | |
166 | def __init__(self, encoding=None): |
167 | self.encoding = encoding or pybtex.io.get_default_encoding() |
168 | |
169 | === modified file 'pybtex/database/output/bibtex.py' |
170 | --- pybtex/database/output/bibtex.py 2013-08-02 10:39:18 +0000 |
171 | +++ pybtex/database/output/bibtex.py 2014-02-04 13:09:32 +0000 |
172 | @@ -28,8 +28,6 @@ |
173 | class Writer(BaseWriter): |
174 | """Outputs BibTeX markup""" |
175 | |
176 | - name = 'bibtex' |
177 | - suffixes = '.bib', |
178 | unicode_io = True |
179 | |
180 | def quote(self, s): |
181 | |
182 | === modified file 'pybtex/database/output/bibtexml.py' |
183 | --- pybtex/database/output/bibtexml.py 2012-02-12 20:44:25 +0000 |
184 | +++ pybtex/database/output/bibtexml.py 2014-02-04 13:09:32 +0000 |
185 | @@ -67,9 +67,6 @@ |
186 | class Writer(BaseWriter): |
187 | """Outputs BibTeXML markup""" |
188 | |
189 | - name = 'bibtexml' |
190 | - suffixes = '.xml', '.bibtexml' |
191 | - |
192 | def write_stream(self, bib_data, stream): |
193 | def write_persons(persons, role): |
194 | if persons: |
195 | |
196 | === modified file 'pybtex/database/output/bibyaml.py' |
197 | --- pybtex/database/output/bibyaml.py 2013-08-02 10:39:18 +0000 |
198 | +++ pybtex/database/output/bibyaml.py 2014-02-04 13:09:32 +0000 |
199 | @@ -27,10 +27,6 @@ |
200 | class Writer(BaseWriter): |
201 | """Outputs YAML markup""" |
202 | |
203 | - name = 'bibyaml' |
204 | - aliases = 'yaml', |
205 | - suffixes = '.yaml', '.bibyaml' |
206 | - |
207 | def write_stream(self, bib_data, stream): |
208 | def process_person_roles(entry): |
209 | for role, persons in entry.persons.iteritems(): |
210 | |
211 | === modified file 'pybtex/plugin/__init__.py' |
212 | --- pybtex/plugin/__init__.py 2012-02-12 20:44:25 +0000 |
213 | +++ pybtex/plugin/__init__.py 2014-02-04 13:09:32 +0000 |
214 | @@ -1,4 +1,5 @@ |
215 | # Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 Andrey Golovizin |
216 | +# Copyright (c) 2014 Matthias C. M. Troffaes |
217 | # |
218 | # Permission is hereby granted, free of charge, to any person obtaining |
219 | # a copy of this software and associated documentation files (the |
220 | @@ -19,14 +20,31 @@ |
221 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
222 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
223 | |
224 | -import os |
225 | -import sys |
226 | -from itertools import chain |
227 | + |
228 | +import os.path # splitext |
229 | +import pkg_resources |
230 | |
231 | from pybtex.exceptions import PybtexError |
232 | |
233 | |
234 | +class Plugin(object): |
235 | + pass |
236 | + |
237 | + |
238 | +#: default pybtex plugins |
239 | +_DEFAULT_PLUGINS = { |
240 | + "pybtex.database.input": "bibtex", |
241 | + "pybtex.database.output": "bibtex", |
242 | + "pybtex.backends": "latex", |
243 | + "pybtex.style.labels": "number", |
244 | + "pybtex.style.names": "plain", |
245 | + "pybtex.style.sorting": "none", |
246 | + "pybtex.style.formatting": "unsrt", |
247 | +} |
248 | + |
249 | + |
250 | class PluginGroupNotFound(PybtexError): |
251 | + |
252 | def __init__(self, group_name): |
253 | message = u'plugin group {group_name} not found'.format( |
254 | group_name=group_name, |
255 | @@ -35,135 +53,120 @@ |
256 | |
257 | |
258 | class PluginNotFound(PybtexError): |
259 | - def __init__(self, plugin_group, name=None, filename=None): |
260 | - assert plugin_group |
261 | - if name: |
262 | + |
263 | + def __init__(self, plugin_group, name): |
264 | + if not name.startswith('.'): |
265 | message = u'plugin {plugin_group}.{name} not found'.format( |
266 | plugin_group=plugin_group, |
267 | name=name, |
268 | ) |
269 | - elif filename: |
270 | - message = u'cannot determine file type for {filename}'.format( |
271 | - plugin_group=plugin_group, |
272 | - filename=filename, |
273 | - ) |
274 | else: |
275 | - message = u'' # FIXME |
276 | + assert plugin_group.endswith('.suffixes') |
277 | + message = ( |
278 | + u'plugin {plugin_group} for suffix {suffix} not found'.format( |
279 | + plugin_group=plugin_group, |
280 | + suffix=name, |
281 | + ) |
282 | + ) |
283 | |
284 | super(PluginNotFound, self).__init__(message) |
285 | |
286 | |
287 | -class Plugin(object): |
288 | - name = None |
289 | - aliases = () |
290 | - suffixes = () |
291 | - default_plugin = None |
292 | - |
293 | - @classmethod |
294 | - def get_default_suffix(cls): |
295 | - return cls.suffixes[0] |
296 | - |
297 | - |
298 | -class PluginLoader(object): |
299 | - def find_plugin(plugin_group, name): |
300 | - raise NotImplementedError |
301 | - |
302 | - def enumerate_plugin_names(self, plugin_group): |
303 | - raise NotImplementedError |
304 | - |
305 | - |
306 | -class BuiltInPluginLoader(PluginLoader): |
307 | - def get_group_info(self, plugin_group): |
308 | - from pybtex.plugin.registry import plugin_registry |
309 | - try: |
310 | - return plugin_registry[plugin_group] |
311 | - except KeyError: |
312 | - raise PluginGroupNotFound(plugin_group) |
313 | - |
314 | - def find_plugin(self, plugin_group, name=None, filename=None): |
315 | - plugin_group_info = self.get_group_info(plugin_group) |
316 | - module_name = None |
317 | - if name: |
318 | - if name in plugin_group_info['plugins']: |
319 | - module_name = name |
320 | - elif name in plugin_group_info['aliases']: |
321 | - module_name = plugin_group_info['aliases'][name] |
322 | - else: |
323 | - raise PluginNotFound(plugin_group, name=name) |
324 | - elif filename: |
325 | - suffix = os.path.splitext(filename)[1] |
326 | - if suffix in plugin_group_info['suffixes']: |
327 | - module_name = plugin_group_info['suffixes'][suffix] |
328 | - else: |
329 | - raise PluginNotFound(plugin_group, filename=filename) |
330 | - else: |
331 | - module_name = plugin_group_info['default_plugin'] |
332 | - |
333 | - class_name = plugin_group_info['class_name'] |
334 | - return self.import_plugin(plugin_group, module_name, class_name) |
335 | - |
336 | - def import_plugin(self, plugin_group, module_name, class_name): |
337 | - module = __import__(str(plugin_group), globals(), locals(), [str(module_name)]) |
338 | - return getattr(getattr(module, module_name), class_name) |
339 | - |
340 | - def enumerate_plugin_names(self, plugin_group): |
341 | - plugin_group_info = self.get_group_info(plugin_group) |
342 | - return plugin_group_info['plugins'] |
343 | - |
344 | - |
345 | -class EntryPointPluginLoader(PluginLoader): |
346 | - def find_plugin(self, plugin_group, name=None, filename=None): |
347 | - try: |
348 | - import pkg_resources |
349 | - except ImportError: |
350 | - raise PluginNotFound(plugin_group) |
351 | - |
352 | - def load_entry_point(group, name): |
353 | - entry_points = pkg_resources.iter_entry_points(group, name) |
354 | - try: |
355 | - entry_point = entry_points.next() |
356 | - except StopIteration: |
357 | - raise PluginNotFound(plugin_group, name, filename) |
358 | - else: |
359 | - return entry_point.load() |
360 | - |
361 | - if name: |
362 | - return load_entry_point(plugin_group, name) |
363 | - elif filename: |
364 | - suffix = os.path.splitext(filename)[1] |
365 | - return load_entry_point(plugin_group + '.suffixes', suffix) |
366 | - else: |
367 | - raise PluginNotFound(plugin_group) |
368 | - |
369 | - def enumerate_plugin_names(self, plugin_group): |
370 | - try: |
371 | - import pkg_resources |
372 | - except ImportError: |
373 | - return |
374 | - entry_points = pkg_resources.iter_entry_points(plugin_group) |
375 | - return [entry_point.name for entry_point in entry_points] |
376 | - |
377 | - |
378 | -plugin_loaders = [EntryPointPluginLoader(), BuiltInPluginLoader()] |
379 | +def _load_entry_point(group, name): |
380 | + entry_points = pkg_resources.iter_entry_points(group, name) |
381 | + try: |
382 | + entry_point = entry_points.next() |
383 | + except StopIteration: |
384 | + raise PluginNotFound(group, name) |
385 | + else: |
386 | + return entry_point.load() |
387 | |
388 | |
389 | def find_plugin(plugin_group, name=None, filename=None): |
390 | - if isinstance(name, type) and issubclass(name, Plugin): |
391 | - plugin = name |
392 | - #assert plugin.group_name == plugin_group |
393 | - return plugin |
394 | + """Find a :class:`Plugin` class within *plugin_group* which |
395 | + matches *name*, or *filename* if *name* is not specified, or |
396 | + the default plugin if neither *name* nor *filename* is |
397 | + specified. |
398 | + |
399 | + If *name* is specified, return the :class:`Plugin` class |
400 | + registered under *name*. If *filename* is specified, look at |
401 | + its suffix (i.e. extension) and return the :class:`Plugin` |
402 | + class registered for this suffix. |
403 | + """ |
404 | + if plugin_group not in _DEFAULT_PLUGINS: |
405 | + raise PluginGroupNotFound(plugin_group) |
406 | + if name: |
407 | + return _load_entry_point(plugin_group, name) |
408 | + elif filename: |
409 | + suffix = os.path.splitext(filename)[1] |
410 | + return _load_entry_point(plugin_group + '.suffixes', suffix) |
411 | else: |
412 | - for loader in plugin_loaders: |
413 | - try: |
414 | - return loader.find_plugin(plugin_group, name, filename) |
415 | - except PluginNotFound: |
416 | - continue |
417 | - raise PluginNotFound(plugin_group, name, filename) |
418 | + return _load_entry_point(plugin_group, _DEFAULT_PLUGINS[plugin_group]) |
419 | |
420 | |
421 | def enumerate_plugin_names(plugin_group): |
422 | - results = ( |
423 | - loader.enumerate_plugin_names(plugin_group) |
424 | - for loader in plugin_loaders |
425 | - ) |
426 | - return chain(*results) |
427 | + """Enumerate all plugin names for the given *plugin_group*.""" |
428 | + return (entry_point.name |
429 | + for entry_point in pkg_resources.iter_entry_points(plugin_group)) |
430 | + |
431 | + |
432 | +class _FakeEntryPoint(pkg_resources.EntryPoint): |
433 | + |
434 | + def __init__(self, name, klass): |
435 | + self.name = name |
436 | + self.klass = klass |
437 | + |
438 | + def __str__(self): |
439 | + return "%s = :%s" % (self.name, self.klass.__name__) |
440 | + |
441 | + def __repr__(self): |
442 | + return ( |
443 | + "_FakeEntryPoint(name=%r, klass=%s)" |
444 | + % (self.name, self.klass.__name__)) |
445 | + |
446 | + def load(self, require=True, env=None, installer=None): |
447 | + return self.klass |
448 | + |
449 | + def require(self, env=None, installer=None): |
450 | + pass |
451 | + |
452 | + |
453 | +def register_plugin(plugin_group, name, klass, force=False): |
454 | + """Register a plugin on the fly. |
455 | + |
456 | + This works by adding *klass* as a pybtex entry point, under entry |
457 | + point group *plugin_group* and entry point name *name*. |
458 | + |
459 | + To register a suffix, append ".suffixes" to the plugin group, and |
460 | + *name* is then simply the suffix, which should start with a |
461 | + period. |
462 | + |
463 | + If *force* is ``False``, then existing entry points are not |
464 | + overwritten. If an entry point with the given group and name |
465 | + already exists, then returns ``False``, otherwise returns |
466 | + ``True``. |
467 | + |
468 | + If *force* is ``True``, then existing entry points are |
469 | + overwritten, and the function always returns ``True``. |
470 | + """ |
471 | + if not plugin_group.endswith(".suffixes"): |
472 | + # registering a name |
473 | + if plugin_group not in _DEFAULT_PLUGINS: |
474 | + raise PluginGroupNotFound(plugin_group) |
475 | + else: |
476 | + # registering a suffix |
477 | + group, _1, _2 = plugin_group.rpartition(".suffixes") |
478 | + assert _1 == ".suffixes" and _2 == "" |
479 | + if not name.startswith('.'): |
480 | + raise ValueError("a suffix must start with a period") |
481 | + if group not in _DEFAULT_PLUGINS: |
482 | + raise PluginGroupNotFound(group) |
483 | + dist = pkg_resources.get_distribution('pybtex') |
484 | + ep_map = pkg_resources.get_entry_map(dist) |
485 | + if plugin_group not in ep_map: |
486 | + ep_map[plugin_group] = {} |
487 | + if name in ep_map[plugin_group] and not force: |
488 | + return False |
489 | + else: |
490 | + ep_map[plugin_group][name] = _FakeEntryPoint(name, klass) |
491 | + return True |
492 | |
493 | === removed file 'pybtex/plugin/make_registry.py' |
494 | --- pybtex/plugin/make_registry.py 2011-02-27 17:25:55 +0000 |
495 | +++ pybtex/plugin/make_registry.py 1970-01-01 00:00:00 +0000 |
496 | @@ -1,63 +0,0 @@ |
497 | -#!/usr/bin/env python |
498 | - |
499 | -import os |
500 | -import imp |
501 | -import pkgutil |
502 | -import json |
503 | - |
504 | - |
505 | -plugin_types = ( |
506 | - ('pybtex.database.input', 'Parser'), |
507 | - ('pybtex.database.output', 'Writer'), |
508 | - ('pybtex.backends', 'Backend'), |
509 | - ('pybtex.style.labels', 'LabelStyle'), |
510 | - ('pybtex.style.names', 'NameStyle'), |
511 | - ('pybtex.style.sorting', 'SortingStyle'), |
512 | - ('pybtex.style.formatting', 'Style'), |
513 | -) |
514 | - |
515 | - |
516 | -def import_from(module_name, obj_name): |
517 | - module = __import__(module_name, globals(), locals(), [obj_name]) |
518 | - return module, getattr(module, obj_name) |
519 | - |
520 | - |
521 | -def iter_plugins(base_module, class_name): |
522 | - plugin_dir = os.path.dirname(base_module.__file__) |
523 | - for loader, name, is_pkg in pkgutil.iter_modules([plugin_dir]): |
524 | - plugin_module = imp.load_module(name, *imp.find_module(name, [plugin_dir])) |
525 | - yield getattr(plugin_module, class_name) |
526 | - |
527 | - |
528 | -def get_plugin_group_info(plugin_group, class_name): |
529 | - base_module, base_plugin = import_from(plugin_group, 'Base' + class_name) |
530 | - info = { |
531 | - 'class_name': class_name, |
532 | - 'default_plugin': base_plugin.default_plugin, |
533 | - 'plugins': [], |
534 | - 'aliases': {}, |
535 | - 'suffixes': {}, |
536 | - } |
537 | - for plugin in iter_plugins(base_module, class_name): |
538 | - info['plugins'].append(plugin.name) |
539 | - info['aliases'].update(dict.fromkeys(plugin.aliases, plugin.name)) |
540 | - info['suffixes'].update(dict.fromkeys(plugin.suffixes, plugin.name)) |
541 | - return info |
542 | - |
543 | - |
544 | -def get_plugin_registry(): |
545 | - return dict( |
546 | - (plugin_group, get_plugin_group_info(plugin_group, class_name)) |
547 | - for plugin_group, class_name in plugin_types |
548 | - ) |
549 | - |
550 | - |
551 | -def write_plugin_registry(filename): |
552 | - with open(filename, 'wb') as registry_file: |
553 | - registry_file.write('plugin_registry = ') |
554 | - json.dump(get_plugin_registry(), registry_file, indent=4) |
555 | - registry_file.write('\n') |
556 | - |
557 | - |
558 | -if __name__ == '__main__': |
559 | - write_plugin_registry('registry.py') |
560 | |
561 | === removed file 'pybtex/plugin/registry.py' |
562 | --- pybtex/plugin/registry.py 2013-08-09 19:38:46 +0000 |
563 | +++ pybtex/plugin/registry.py 1970-01-01 00:00:00 +0000 |
564 | @@ -1,103 +0,0 @@ |
565 | -plugin_registry = { |
566 | - "pybtex.database.output": { |
567 | - "class_name": "Writer", |
568 | - "suffixes": { |
569 | - ".xml": "bibtexml", |
570 | - ".bibtexml": "bibtexml", |
571 | - ".bibyaml": "bibyaml", |
572 | - ".bib": "bibtex", |
573 | - ".yaml": "bibyaml" |
574 | - }, |
575 | - "aliases": { |
576 | - "yaml": "bibyaml" |
577 | - }, |
578 | - "default_plugin": "bibtex", |
579 | - "plugins": [ |
580 | - "bibtex", |
581 | - "bibtexml", |
582 | - "bibyaml" |
583 | - ] |
584 | - }, |
585 | - "pybtex.style.formatting": { |
586 | - "class_name": "Style", |
587 | - "suffixes": {}, |
588 | - "aliases": {}, |
589 | - "default_plugin": "unsrt", |
590 | - "plugins": [ |
591 | - "plain", |
592 | - "unsrt", |
593 | - "alpha", |
594 | - "unsrtalpha", |
595 | - ] |
596 | - }, |
597 | - "pybtex.style.labels": { |
598 | - "class_name": "LabelStyle", |
599 | - "suffixes": {}, |
600 | - "aliases": {}, |
601 | - "default_plugin": "number", |
602 | - "plugins": [ |
603 | - "number", |
604 | - "alpha", |
605 | - ] |
606 | - }, |
607 | - "pybtex.backends": { |
608 | - "class_name": "Backend", |
609 | - "suffixes": { |
610 | - ".html": "html", |
611 | - ".latex": "latex", |
612 | - ".txt": "plaintext", |
613 | - ".bbl": "latex", |
614 | - ".tex": "latex" |
615 | - }, |
616 | - "aliases": { |
617 | - "text": "plaintext" |
618 | - }, |
619 | - "default_plugin": "latex", |
620 | - "plugins": [ |
621 | - "html", |
622 | - "latex", |
623 | - "plaintext" |
624 | - ] |
625 | - }, |
626 | - "pybtex.database.input": { |
627 | - "class_name": "Parser", |
628 | - "suffixes": { |
629 | - ".xml": "bibtexml", |
630 | - ".bibtexml": "bibtexml", |
631 | - ".bibyaml": "bibyaml", |
632 | - ".bib": "bibtex", |
633 | - ".yaml": "bibyaml" |
634 | - }, |
635 | - "aliases": { |
636 | - "yaml": "bibyaml" |
637 | - }, |
638 | - "default_plugin": "bibtex", |
639 | - "plugins": [ |
640 | - "bibtex", |
641 | - "bibtexml", |
642 | - "bibyaml" |
643 | - ] |
644 | - }, |
645 | - "pybtex.style.names": { |
646 | - "class_name": "NameStyle", |
647 | - "suffixes": {}, |
648 | - "aliases": { |
649 | - "last_first": "lastfirst" |
650 | - }, |
651 | - "default_plugin": "plain", |
652 | - "plugins": [ |
653 | - "lastfirst", |
654 | - "plain" |
655 | - ] |
656 | - }, |
657 | - "pybtex.style.sorting": { |
658 | - "class_name": "SortingStyle", |
659 | - "suffixes": {}, |
660 | - "aliases": {}, |
661 | - "default_plugin": "none", |
662 | - "plugins": [ |
663 | - "author_year_title", |
664 | - "none" |
665 | - ] |
666 | - } |
667 | -} |
668 | |
669 | === modified file 'pybtex/style/formatting/__init__.py' |
670 | --- pybtex/style/formatting/__init__.py 2013-08-07 07:30:30 +0000 |
671 | +++ pybtex/style/formatting/__init__.py 2014-02-04 13:09:32 +0000 |
672 | @@ -31,7 +31,6 @@ |
673 | |
674 | |
675 | class BaseStyle(Plugin): |
676 | - default_plugin = 'unsrt' |
677 | default_name_style = None |
678 | default_label_style = None |
679 | default_sorting_style = None |
680 | |
681 | === modified file 'pybtex/style/formatting/alpha.py' |
682 | --- pybtex/style/formatting/alpha.py 2012-08-09 10:25:06 +0000 |
683 | +++ pybtex/style/formatting/alpha.py 2014-02-04 13:09:32 +0000 |
684 | @@ -23,6 +23,5 @@ |
685 | |
686 | |
687 | class Style(UnsrtStyle): |
688 | - name = 'alpha' |
689 | default_sorting_style = 'author_year_title' |
690 | default_label_style = 'alpha' |
691 | |
692 | === modified file 'pybtex/style/formatting/plain.py' |
693 | --- pybtex/style/formatting/plain.py 2012-02-12 20:44:25 +0000 |
694 | +++ pybtex/style/formatting/plain.py 2014-02-04 13:09:32 +0000 |
695 | @@ -23,5 +23,4 @@ |
696 | |
697 | |
698 | class Style(UnsrtStyle): |
699 | - name = 'plain' |
700 | default_sorting_style = 'author_year_title' |
701 | |
702 | === modified file 'pybtex/style/formatting/unsrt.py' |
703 | --- pybtex/style/formatting/unsrt.py 2012-08-07 13:19:51 +0000 |
704 | +++ pybtex/style/formatting/unsrt.py 2014-02-04 13:09:32 +0000 |
705 | @@ -37,7 +37,6 @@ |
706 | date = words [optional_field('month'), field('year')] |
707 | |
708 | class Style(BaseStyle): |
709 | - name = 'unsrt' |
710 | |
711 | def format_names(self, role, as_sentence=True): |
712 | formatted_names = names(role, sep=', ', sep2 = ' and ', last_sep=', and ') |
713 | |
714 | === modified file 'pybtex/style/formatting/unsrtalpha.py' |
715 | --- pybtex/style/formatting/unsrtalpha.py 2012-08-09 10:25:06 +0000 |
716 | +++ pybtex/style/formatting/unsrtalpha.py 2014-02-04 13:09:32 +0000 |
717 | @@ -23,5 +23,4 @@ |
718 | |
719 | |
720 | class Style(UnsrtStyle): |
721 | - name = 'unsrtalpha' |
722 | default_label_style = 'alpha' |
723 | |
724 | === modified file 'pybtex/style/labels/__init__.py' |
725 | --- pybtex/style/labels/__init__.py 2013-08-02 08:12:50 +0000 |
726 | +++ pybtex/style/labels/__init__.py 2014-02-04 13:09:32 +0000 |
727 | @@ -22,12 +22,8 @@ |
728 | from pybtex.plugin import Plugin |
729 | from pybtex.textutils import width |
730 | |
731 | -available_plugins = ('number', 'alpha') |
732 | - |
733 | |
734 | class BaseLabelStyle(Plugin): |
735 | - default_plugin = 'number' |
736 | - |
737 | def get_longest_label(self, formatted_entries): |
738 | labels = (entry.label for entry in formatted_entries) |
739 | return max(labels, key=width) |
740 | |
741 | === modified file 'pybtex/style/labels/alpha.py' |
742 | --- pybtex/style/labels/alpha.py 2013-08-05 12:55:10 +0000 |
743 | +++ pybtex/style/labels/alpha.py 2014-02-04 13:09:32 +0000 |
744 | @@ -51,7 +51,6 @@ |
745 | return _nonalnum_pattern.sub(u'', _strip_accents(s)) |
746 | |
747 | class LabelStyle(BaseLabelStyle): |
748 | - name = 'alpha' |
749 | |
750 | def format_labels(self, sorted_entries): |
751 | labels = [self.format_label(entry) for entry in sorted_entries] |
752 | |
753 | === modified file 'pybtex/style/labels/number.py' |
754 | --- pybtex/style/labels/number.py 2013-08-01 16:52:31 +0000 |
755 | +++ pybtex/style/labels/number.py 2014-02-04 13:09:32 +0000 |
756 | @@ -24,7 +24,6 @@ |
757 | |
758 | |
759 | class LabelStyle(BaseLabelStyle): |
760 | - name = 'number' |
761 | |
762 | def format_labels(self, sorted_entries): |
763 | for number, entry in enumerate(sorted_entries): |
764 | |
765 | === modified file 'pybtex/style/names/__init__.py' |
766 | --- pybtex/style/names/__init__.py 2012-02-12 20:44:25 +0000 |
767 | +++ pybtex/style/names/__init__.py 2014-02-04 13:09:32 +0000 |
768 | @@ -27,12 +27,7 @@ |
769 | from pybtex.style.template import join, together, node, _format_list |
770 | |
771 | |
772 | -available_plugins = ('plain', 'lastfirst') |
773 | - |
774 | - |
775 | class BaseNameStyle(Plugin): |
776 | - default_plugin = 'plain' |
777 | - |
778 | def format(self, person, abbr=False): |
779 | raise NotImplementedError |
780 | |
781 | |
782 | === modified file 'pybtex/style/names/lastfirst.py' |
783 | --- pybtex/style/names/lastfirst.py 2012-02-12 20:44:25 +0000 |
784 | +++ pybtex/style/names/lastfirst.py 2014-02-04 13:09:32 +0000 |
785 | @@ -25,8 +25,6 @@ |
786 | |
787 | |
788 | class NameStyle(BaseNameStyle): |
789 | - name = 'lastfirst' |
790 | - aliases = 'last_first', |
791 | |
792 | def format(self, person, abbr=False): |
793 | r""" |
794 | |
795 | === modified file 'pybtex/style/names/plain.py' |
796 | --- pybtex/style/names/plain.py 2012-02-12 20:44:25 +0000 |
797 | +++ pybtex/style/names/plain.py 2014-02-04 13:09:32 +0000 |
798 | @@ -25,7 +25,6 @@ |
799 | |
800 | |
801 | class NameStyle(BaseNameStyle): |
802 | - name = 'plain' |
803 | |
804 | def format(self, person, abbr=False): |
805 | r""" |
806 | |
807 | === modified file 'pybtex/style/sorting/__init__.py' |
808 | --- pybtex/style/sorting/__init__.py 2012-02-12 20:44:25 +0000 |
809 | +++ pybtex/style/sorting/__init__.py 2014-02-04 13:09:32 +0000 |
810 | @@ -23,8 +23,6 @@ |
811 | |
812 | |
813 | class BaseSortingStyle(Plugin): |
814 | - default_plugin = 'none' |
815 | - |
816 | def sorting_key(self, entry): |
817 | raise NotImplementedError |
818 | |
819 | |
820 | === modified file 'pybtex/style/sorting/author_year_title.py' |
821 | --- pybtex/style/sorting/author_year_title.py 2012-08-09 13:05:30 +0000 |
822 | +++ pybtex/style/sorting/author_year_title.py 2014-02-04 13:09:32 +0000 |
823 | @@ -23,7 +23,6 @@ |
824 | |
825 | |
826 | class SortingStyle(BaseSortingStyle): |
827 | - name = 'author_year_title' |
828 | |
829 | def sorting_key(self, entry): |
830 | if entry.type in ('book', 'inbook'): |
831 | |
832 | === modified file 'pybtex/style/sorting/none.py' |
833 | --- pybtex/style/sorting/none.py 2012-02-12 20:44:25 +0000 |
834 | +++ pybtex/style/sorting/none.py 2014-02-04 13:09:32 +0000 |
835 | @@ -23,7 +23,6 @@ |
836 | |
837 | |
838 | class SortingStyle(BaseSortingStyle): |
839 | - name = 'none' |
840 | |
841 | def sort(self, entries): |
842 | return entries |
843 | |
844 | === added file 'pybtex/tests/plugin_test.py' |
845 | --- pybtex/tests/plugin_test.py 1970-01-01 00:00:00 +0000 |
846 | +++ pybtex/tests/plugin_test.py 2014-02-04 13:09:32 +0000 |
847 | @@ -0,0 +1,119 @@ |
848 | +# Copyright (c) 2014 Matthias C. M. Troffaes |
849 | +# |
850 | +# Permission is hereby granted, free of charge, to any person obtaining |
851 | +# a copy of this software and associated documentation files (the |
852 | +# "Software"), to deal in the Software without restriction, including |
853 | +# without limitation the rights to use, copy, modify, merge, publish, |
854 | +# distribute, sublicense, and/or sell copies of the Software, and to |
855 | +# permit persons to whom the Software is furnished to do so, subject to |
856 | +# the following conditions: |
857 | +# |
858 | +# The above copyright notice and this permission notice shall be |
859 | +# included in all copies or substantial portions of the Software. |
860 | +# |
861 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
862 | +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
863 | +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
864 | +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
865 | +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
866 | +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
867 | +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
868 | + |
869 | +import nose.tools |
870 | + |
871 | +import pybtex.database.input.bibtex |
872 | +import pybtex.plugin |
873 | +import pybtex.style.formatting.plain |
874 | + |
875 | + |
876 | +def test_plugin_loader(): |
877 | + """Check that all enumerated plugins can be imported.""" |
878 | + for group in pybtex.plugin._DEFAULT_PLUGINS: |
879 | + for name in pybtex.plugin.enumerate_plugin_names(group): |
880 | + pybtex.plugin.find_plugin(group, name) |
881 | + |
882 | + |
883 | +class TestPlugin1(pybtex.plugin.Plugin): |
884 | + pass |
885 | + |
886 | + |
887 | +class TestPlugin2(pybtex.plugin.Plugin): |
888 | + pass |
889 | + |
890 | + |
891 | +class TestPlugin3(pybtex.plugin.Plugin): |
892 | + pass |
893 | + |
894 | + |
895 | +def test_register_plugin_1(): |
896 | + nose.tools.assert_true( |
897 | + pybtex.plugin.register_plugin( |
898 | + 'pybtex.style.formatting', 'yippikayee', TestPlugin1)) |
899 | + nose.tools.assert_is( |
900 | + TestPlugin1, pybtex.plugin.find_plugin( |
901 | + 'pybtex.style.formatting', 'yippikayee')) |
902 | + nose.tools.assert_false( |
903 | + pybtex.plugin.register_plugin( |
904 | + 'pybtex.style.formatting', 'yippikayee', TestPlugin2)) |
905 | + nose.tools.assert_is( |
906 | + TestPlugin1, pybtex.plugin.find_plugin( |
907 | + 'pybtex.style.formatting', 'yippikayee')) |
908 | + nose.tools.assert_true( |
909 | + pybtex.plugin.register_plugin( |
910 | + 'pybtex.style.formatting', 'yippikayee', TestPlugin2, force=True)) |
911 | + nose.tools.assert_is( |
912 | + TestPlugin2, pybtex.plugin.find_plugin( |
913 | + 'pybtex.style.formatting', 'yippikayee')) |
914 | + |
915 | + |
916 | +def test_register_plugin_2(): |
917 | + nose.tools.assert_false( |
918 | + pybtex.plugin.register_plugin( |
919 | + 'pybtex.style.formatting', 'plain', TestPlugin2)) |
920 | + plugin = pybtex.plugin.find_plugin('pybtex.style.formatting', 'plain') |
921 | + nose.tools.assert_is_not(plugin, TestPlugin2) |
922 | + nose.tools.assert_is(plugin, pybtex.style.formatting.plain.Style) |
923 | + |
924 | + |
925 | +def test_register_plugin_3(): |
926 | + nose.tools.assert_true( |
927 | + pybtex.plugin.register_plugin( |
928 | + 'pybtex.style.formatting.suffixes', '.woo', TestPlugin3)) |
929 | + plugin = pybtex.plugin.find_plugin( |
930 | + 'pybtex.style.formatting', filename='test.woo') |
931 | + nose.tools.assert_is(plugin, TestPlugin3) |
932 | + |
933 | + |
934 | +def test_bad_find_plugin(): |
935 | + nose.tools.assert_raises( |
936 | + pybtex.plugin.PluginGroupNotFound, |
937 | + lambda: pybtex.plugin.find_plugin("pybtex.invalid.group", "__oops")) |
938 | + nose.tools.assert_raises( |
939 | + pybtex.plugin.PluginNotFound, |
940 | + lambda: pybtex.plugin.find_plugin("pybtex.style.formatting", "__oops")) |
941 | + nose.tools.assert_raises( |
942 | + pybtex.plugin.PluginNotFound, |
943 | + lambda: pybtex.plugin.find_plugin("pybtex.style.formatting", |
944 | + filename="oh.__oops")) |
945 | + |
946 | + |
947 | +def test_bad_register_plugin(): |
948 | + nose.tools.assert_raises( |
949 | + pybtex.plugin.PluginGroupNotFound, |
950 | + lambda: pybtex.plugin.register_plugin( |
951 | + "pybtex.invalid.group", "__oops", TestPlugin1)) |
952 | + nose.tools.assert_raises( |
953 | + pybtex.plugin.PluginGroupNotFound, |
954 | + lambda: pybtex.plugin.register_plugin( |
955 | + "pybtex.invalid.group.suffixes", ".__oops", TestPlugin1)) |
956 | + # suffixes must start with a dot |
957 | + nose.tools.assert_raises( |
958 | + ValueError, |
959 | + lambda: pybtex.plugin.register_plugin( |
960 | + "pybtex.style.formatting.suffixes", "notasuffix", TestPlugin1)) |
961 | + |
962 | + |
963 | +def test_plugin_suffix(): |
964 | + plugin = pybtex.plugin.find_plugin( |
965 | + "pybtex.database.input", filename="test.bib") |
966 | + nose.tools.assert_is(plugin, pybtex.database.input.bibtex.Parser) |
967 | |
968 | === modified file 'setup.py' |
969 | --- setup.py 2013-08-07 07:36:40 +0000 |
970 | +++ setup.py 2014-02-04 13:09:32 +0000 |
971 | @@ -92,6 +92,66 @@ |
972 | ], |
973 | include_package_data=True, |
974 | cmdclass={'sdist' : Sdist}, |
975 | + entry_points={ |
976 | + 'pybtex.database.input': [ |
977 | + 'bibtex = pybtex.database.input.bibtex:Parser', |
978 | + 'bibtexml = pybtex.database.input.bibtexml:Parser', |
979 | + 'bibyaml = pybtex.database.input.bibyaml:Parser', |
980 | + 'yaml = pybtex.database.input.bibyaml:Parser', |
981 | + ], |
982 | + 'pybtex.database.input.suffixes': [ |
983 | + '.bib = pybtex.database.input.bibtex:Parser', |
984 | + '.xml = pybtex.database.input.bibtexml:Parser', |
985 | + '.bibtexml = pybtex.database.input.bibtexml:Parser', |
986 | + '.bibyaml = pybtex.database.input.bibyaml:Parser', |
987 | + '.yaml = pybtex.database.input.bibyaml:Parser', |
988 | + ], |
989 | + 'pybtex.database.output': [ |
990 | + 'bibtex = pybtex.database.output.bibtex:Writer', |
991 | + 'bibtexml = pybtex.database.output.bibtexml:Writer', |
992 | + 'bibyaml = pybtex.database.output.bibyaml:Writer', |
993 | + 'yaml = pybtex.database.output.bibyaml:Writer', |
994 | + ], |
995 | + 'pybtex.database.output.suffixes': [ |
996 | + '.bib = pybtex.database.output.bibtex:Writer', |
997 | + '.xml = pybtex.database.output.bibtexml:Writer', |
998 | + '.bibtexml = pybtex.database.output.bibtexml:Writer', |
999 | + '.bibyaml = pybtex.database.output.bibyaml:Writer', |
1000 | + '.yaml = pybtex.database.output.bibyaml:Writer', |
1001 | + ], |
1002 | + 'pybtex.backends': [ |
1003 | + 'latex = pybtex.backends.latex:Backend', |
1004 | + 'html = pybtex.backends.html:Backend', |
1005 | + 'plaintext = pybtex.backends.plaintext:Backend', |
1006 | + 'text = pybtex.backends.plaintext:Backend', |
1007 | + ], |
1008 | + 'pybtex.backends.suffixes': [ |
1009 | + '.bbl = pybtex.backends.latex:Backend', |
1010 | + '.tex = pybtex.backends.latex:Backend', |
1011 | + '.latex = pybtex.backends.latex:Backend', |
1012 | + '.html = pybtex.backends.html:Backend', |
1013 | + '.txt = pybtex.backends.plaintext:Backend', |
1014 | + ], |
1015 | + 'pybtex.style.labels': [ |
1016 | + 'number = pybtex.style.labels.number:LabelStyle', |
1017 | + 'alpha = pybtex.style.labels.alpha:LabelStyle', |
1018 | + ], |
1019 | + 'pybtex.style.names': [ |
1020 | + 'plain = pybtex.style.names.plain:NameStyle', |
1021 | + 'lastfirst = pybtex.style.names.lastfirst:NameStyle', |
1022 | + 'last_first = pybtex.style.names.lastfirst:NameStyle', |
1023 | + ], |
1024 | + 'pybtex.style.sorting': [ |
1025 | + 'none = pybtex.style.sorting.none:SortingStyle', |
1026 | + 'author_year_title = pybtex.style.sorting.author_year_title:SortingStyle', |
1027 | + ], |
1028 | + 'pybtex.style.formatting': [ |
1029 | + 'plain = pybtex.style.formatting.plain:Style', |
1030 | + 'unsrt = pybtex.style.formatting.unsrt:Style', |
1031 | + 'alpha = pybtex.style.formatting.alpha:Style', |
1032 | + 'unsrtalpha = pybtex.style.formatting.unsrtalpha:Style', |
1033 | + ], |
1034 | + }, |
1035 | zip_safe=True, |
1036 | **extra |
1037 | ) |
This is now ready for initial review. IMHO this implementation looks a lot cleaner than the old implementation
https:/ /code.launchpad .net/~matthias- troffaes/ pybtex/ simple- plugin- loader/ +merge/ 195366
Thoughts?