Commit f963bbb4 authored by Andrey Golovizin's avatar Andrey Golovizin

Get rid of magic FieldDict

parent 5e2ddf57
......@@ -112,7 +112,8 @@ class Field(object):
def value(self):
try:
return self.interpreter.current_entry.fields[self.name]
bib_data = self.interpreter.bib_data
return self.interpreter.current_entry._find_field(self.name, bib_data)
except KeyError:
return MissingField(self.name)
......
......@@ -354,27 +354,6 @@ class BibliographyData(object):
)
class FieldDict(OrderedCaseInsensitiveDict):
def __init__(self, parent, *args, **kwargw):
self.parent = parent
super(FieldDict, self).__init__(*args, **kwargw)
def __getitem__(self, key):
try:
return super(FieldDict, self).__getitem__(key)
except KeyError:
if key in self.parent.persons:
persons = self.parent.persons[key]
return ' and '.join(six.text_type(person) for person in persons)
elif 'crossref' in self:
return self.parent.get_crossref().fields[key]
else:
raise KeyError(key)
def lower(self):
return type(self)(self.parent, self.items_lower())
class RichFieldProxyDict(Mapping):
def __init__(self, fields):
self._fields = fields
......@@ -426,7 +405,7 @@ class Entry(object):
self.type = type_.lower()
self.original_type = type_
self.fields = FieldDict(self, fields)
self.fields = OrderedCaseInsensitiveDict(fields)
self.rich_fields = RichFieldProxyDict(self.fields)
self.persons = OrderedCaseInsensitiveDict(persons)
......@@ -446,8 +425,7 @@ class Entry(object):
)
def __repr__(self):
# representing fields as FieldDict causes problems with representing
# fields.parent, so represent it as a list of tuples
# represent the fields as a list of tuples for simplicity
repr_fields = repr(self.fields.items())
return 'Entry({type_}, fields={fields}, persons={persons})'.format(
......@@ -456,9 +434,6 @@ class Entry(object):
persons=repr(self.persons),
)
def get_crossref(self):
return self.collection.entries[self.fields['crossref']]
def add_person(self, person, role):
self.persons.setdefault(role, []).append(person)
......@@ -470,6 +445,39 @@ class Entry(object):
collection=self.collection,
)
def _find_person_field(self, role):
persons = self.persons[role]
return ' and '.join(six.text_type(person) for person in persons)
def _find_crossref_field(self, name, bib_data):
if bib_data is None or 'crossref' not in self.fields:
raise KeyError(name)
referenced_entry = bib_data.entries[self.fields['crossref']]
return referenced_entry._find_field(name, bib_data)
def _find_field(self, name, bib_data=None):
"""
Find the field with the given ``name`` according to this rules:
- If the given field ``name`` in in ``self.fields``, just return
self.fields[name].
- Otherwise, if ``name`` is ``"authors"`` or ``"editors"`` (or any other
person role), return the list of names as a string, separated by
``" and "``.
- Otherwise, if this entry has a ``crossreff`` field, look up for the
cross-referenced entry and try to find its field with the given
``name``.
"""
try:
return self.fields[name]
except KeyError:
try:
return self._find_person_field(name)
except KeyError:
return self._find_crossref_field(name, bib_data)
@python_2_unicode_compatible
@fix_unicode_literals_in_doctest
......
......@@ -51,16 +51,17 @@ class BaseStyle(Plugin):
self.abbreviate_names = abbreviate_names
self.min_crossrefs = min_crossrefs
def format_entries(self, entries):
def format_entries(self, entries, bib_data=None):
sorted_entries = self.sort(entries)
labels = self.format_labels(sorted_entries)
for label, entry in zip(labels, sorted_entries):
yield self.format_entry(label, entry)
yield self.format_entry(label, entry, bib_data=bib_data)
def format_entry(self, label, entry):
def format_entry(self, label, entry, bib_data=None):
context = {
'entry': entry,
'style': self,
'bib_data': bib_data,
}
try:
get_template = getattr(self, 'get_{}_template'.format(entry.type))
......
......@@ -258,7 +258,9 @@ def field(children, context, name, apply_func=None, raw=False):
assert not children
entry = context['entry']
try:
field = entry.fields[name] if raw else entry.rich_fields[name]
field = entry._find_field(name, bib_data=context.get('bib_data'))
if not raw:
field = richtext.Text.from_latex(field)
except KeyError:
raise FieldIsMissing(name, entry)
else:
......
......@@ -129,13 +129,12 @@ class ReprEvalIO(DatabaseIO):
def deserialize(self, repr_value):
from pybtex.utils import OrderedCaseInsensitiveDict
from pybtex.database import BibliographyData, Entry, Person, FieldDict
from pybtex.database import BibliographyData, Entry, Person
return eval(repr_value, {
'OrderedCaseInsensitiveDict': OrderedCaseInsensitiveDict,
'BibliographyData': BibliographyData,
'Entry': Entry,
'Person': Person,
'FieldDict': FieldDict,
})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment