Loading pybtex/bibtex/interpreter.py +2 −1 Original line number Diff line number Diff line Loading @@ -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) Loading pybtex/database/__init__.py +35 −27 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading @@ -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( Loading @@ -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) Loading @@ -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 Loading pybtex/style/formatting/__init__.py +4 −3 Original line number Diff line number Diff line Loading @@ -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)) Loading pybtex/style/template.py +3 −1 Original line number Diff line number Diff line Loading @@ -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: Loading tests/database_test/database_test.py +1 −2 Original line number Diff line number Diff line Loading @@ -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, }) Loading Loading
pybtex/bibtex/interpreter.py +2 −1 Original line number Diff line number Diff line Loading @@ -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) Loading
pybtex/database/__init__.py +35 −27 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading @@ -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( Loading @@ -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) Loading @@ -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 Loading
pybtex/style/formatting/__init__.py +4 −3 Original line number Diff line number Diff line Loading @@ -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)) Loading
pybtex/style/template.py +3 −1 Original line number Diff line number Diff line Loading @@ -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: Loading
tests/database_test/database_test.py +1 −2 Original line number Diff line number Diff line Loading @@ -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, }) Loading