diff --git a/header.py b/header.py index 33ce868..0a8979a 100644 --- a/header.py +++ b/header.py @@ -5,7 +5,7 @@ % DO NOT MODIFY MANUALLY %------------------------------------------------------------------ -% Authors: +% Authors: % Michel Abdalla % Fabrice Benhamouda % @@ -25,8 +25,8 @@ % 2) one of the following files: % abbrev0.bib % abbrev1.bib -% abbrev2.bib -% abbrev3.bib +% abbrev2.bib +% abbrev3.bib % %------------------------------------------------------------------ @@ -78,7 +78,7 @@ % Examples: % author = "Kamel Bentahar and Pooya Farshim and John Malone-Lee and Nigel P. Smart" ==> BFMS % author = "Don Coppersmith and Jean-Sebastien Coron and -% Fran\c{c}ois Grieu and Shai Halevi and +% Fran{\\c c}ois Grieu and Shai Halevi and % Charanjit S. Jutla and David Naccache and % Julien P. Stern" ==> CCGHJN % diff --git a/mybibtex/database.py b/mybibtex/database.py index 4429bf7..06a9149 100644 --- a/mybibtex/database.py +++ b/mybibtex/database.py @@ -80,7 +80,7 @@ def add_entry(self, key, entry): if not isinstance(key, EntryKey): key = EntryKey.from_string(key) if key in self.entries: - report_error(BibliographyDataError('repeated bibliograhpy entry: %s' % key)) + report_error(BibliographyDataError('repeated bibliography entry: %s' % key)) return entry.collection = self entry.key = key @@ -160,9 +160,9 @@ class Person(object): ['Dixit'] >>> print p.lineage() [] - >>> print unicode(p) + >>> print str(p) Dixit, Avinash K. - >>> p == Person(unicode(p)) + >>> p == Person(str(p)) True >>> p = Person('Dixit, Jr, Avinash K. ') >>> print p.first() @@ -175,9 +175,9 @@ class Person(object): ['Dixit'] >>> print p.lineage() ['Jr'] - >>> print unicode(p) + >>> print str(p) Dixit, Jr, Avinash K. - >>> p == Person(unicode(p)) + >>> p == Person(str(p)) True >>> p = Person('abc') @@ -187,9 +187,9 @@ class Person(object): >>> print p.first(), p.middle(), p.prelast(), p.last(), p.lineage() ['Michail'] ['Markovitch'] [] ['Viktorov'] [] """ - valid_roles = ['author', 'editor'] - style1_re = re.compile('^(.+),\s*(.+)$') - style2_re = re.compile('^(.+),\s*(.+),\s*(.+)$') + valid_roles = ['author', 'editor'] + style1_re = re.compile('^(.+),\\s*(.+)$') + style2_re = re.compile('^(.+),\\s*(.+),\\s*(.+)$') def __init__(self, string="", first="", middle="", prelast="", last="", lineage=""): self._first = [] @@ -278,15 +278,26 @@ def __eq__(self, other): and self._lineage == other._lineage ) - def __unicode__(self): + def __str__(self): # von Last, Jr, First von_last = ' '.join(self._prelast + self._last) jr = ' '.join(self._lineage) first = ' '.join(self._first + self._middle) - return ', '.join(part for part in (von_last, jr, first) if part) + + if jr or (not first and self._prelast): + return ', '.join(part for part in (von_last, jr, first) if part) + if first: + return first + ' ' + von_last + # Yes, there are people who only have 1 "name". + # Bibtex parses this as a lastname, although possibly, + # this person might only have a firstname and no lastname. + return von_last def __repr__(self): - return 'Person({0})'.format(repr(str(self))) + return f"Person({str(self)})" + + def __hash__(self): + return hash(str(self)) def get_part_as_text(self, type): names = getattr(self, '_' + type) @@ -362,13 +373,13 @@ def __init__(self, confkey, year, auth=None, dis=""): self.confkey = confkey """ conference abbreviation for key """ self.auth = auth - """ authors formatted as required in key (last name or first letters or ...) or None if this is a conferece """ + """ authors formatted as required in key (last name or first letters or ...) or None if this is a conference """ self.year = int(year) % 100 """ year of the conference (2 digits) """ self.dis = dis """ disambiguation string ("", "a", "b", "-1", "-2", ...) if same conf, same authors and same year for a paper or if multiple volumes in one conf""" - _str_regexp = re.compile("^([a-zA-Z]+)(?::([a-zA-Z-_']+))?(\d+)(.*)$") + _str_regexp = re.compile("^([a-zA-Z]+)(?::([a-zA-Z-_']+))?(\\d+)(.*)$") @classmethod def from_string(cls, s): @@ -379,7 +390,7 @@ def from_string(cls, s): return cls(confkey, year, auth, dis) def __str__(self): - if self.auth == None: + if self.auth is None: return "{0}{1:02d}{2}".format(self.confkey, self.year, self.dis) else: return "{0}:{1}{2:02d}{3}".format(self.confkey, self.auth, self.year, self.dis) @@ -391,9 +402,9 @@ def __hash__(self): return str(self).__hash__() def __eq__(self, other): - return (self.confkey == other.confkey and - self.auth == other.auth and - self.year == other.year and + return (self.confkey == other.confkey and + self.auth == other.auth and + self.year == other.year and self.dis == other.dis) class Value(list): diff --git a/mybibtex/generator.py b/mybibtex/generator.py index 3582a9b..7583886 100644 --- a/mybibtex/generator.py +++ b/mybibtex/generator.py @@ -11,7 +11,7 @@ # WARNING: do not forge to set this variable to the correct config module when loading this module # FIXME: need to remove this dirty hack! -config = None +config = None class EntryFilter(object, metaclass=ABCMeta): """ Composable entry filters: it is possible to compose a filter FilterA with a filter FilterB by instantiating FilterA(FilterB()) """ @@ -49,7 +49,7 @@ class EntrySort(object, metaclass=ABCMeta): @abstractmethod def key(self, ke): pass - + def sort(self, entries): return sorted(entries, key=self.key) @@ -86,7 +86,7 @@ def proc_dis(self, e): if "crossref" not in e.fields: return "" else: - return EntryKey.from_string(e.fields["crossref"].expand()).dis + return EntryKey.from_string(e.fields["crossref"].expand()).dis pattern_eprint = re.compile(r"^Cryptology ePrint Archive, Report (\d*)/(\d*)") @@ -130,8 +130,8 @@ def key(self, ke): (p1, p2) = self.get_pages(k,e) return "{:<15}-{:0>4d}-{:<10}-{}-{:>10}-{:0>10d}-{:0>20}-{:0>20}".format( - self.proc_confkey(k.confkey), - self.proc_year(k.year), + self.proc_confkey(k.confkey), + self.proc_year(k.year), self.proc_dis(e), self.proc_eprint(e), self.proc_volume(e), @@ -139,37 +139,19 @@ def key(self, ke): p1, p2 ) - + def bibtex_entry_format_fields(db, key, entry, expand_crossrefs=False, expand_values=False): - """ Return a dictionnay of formatted fields """ - - def format_name(person): - def join(l): - return ' '.join([name for name in l if name]) - first = person.get_part_as_text('first') - middle = person.get_part_as_text('middle') - prelast = person.get_part_as_text('prelast') - last = person.get_part_as_text('last') - lineage = person.get_part_as_text('lineage') - s = '' - if last: - s += join([prelast, last]) - if lineage: - s += ', %s' % lineage - if first or middle: - s += ', ' - s += join([first, middle]) - return s + """ Return a dictionary of formatted fields """ def format_persons(persons): - return Value([ValuePartQuote((" and ").join([format_name(person) for person in persons]))]) + return Value([ValuePartQuote((" and ").join([str(person) for person in persons]))]) def format_author(author): res = author.expand().replace(" and ", " and\n" + " "*18) return Value([ValuePartQuote(res, normalize=False)]) fields = entry.fields.copy() - + # expand persons for (role, persons) in entry.persons.items(): if role not in fields: @@ -213,7 +195,7 @@ def format_type(type_): # remove empty fields after expansion if remove_empty_fields: v_expanded = fields[k].to_bib(expand = True) - if v_expanded == '""': + if v_expanded == '""': continue v = fields[k].to_bib(expand = expand_values) @@ -235,28 +217,28 @@ def bibtex_write_entries(out, db, entries, *args, **kwargs): for key, entry in entries: bibtex_write_entry(out, db, key, entry, *args, **kwargs) out.write("\n\n") - + def bibtex_gen(out, db, entry_filter=FilterPaper(), entry_sort=SortConfYearPage(), expand_crossrefs=False, include_crossrefs=False, *args, **kwargs): - """ + """ Generate bibtex file Options: @arg expand_crossrefs: expand crossrefs inside entries instead of keeping the crossref field if True, @arg include_crossrefs: include crossrefs in the output if True and expand_crossrefs=False, @arg expand_values: expand values (using macros) if True - @arg remove_empty_fields: remove empty fields if True, empty fields are ones that are either empty or expand to an empty value + @arg remove_empty_fields: remove empty fields if True, empty fields are ones that are either empty or expand to an empty value (in case expand_values=False and multiple macros values may be used using, e.g., multiple "abbrev*.bib" files, be extra careful) """ entries = dict(entry_filter.filter(db.entries)) bibtex_write_entries( - out, - db, - entry_sort.sort(iter(entries.items())), - expand_crossrefs=expand_crossrefs, + out, + db, + entry_sort.sort(iter(entries.items())), + expand_crossrefs=expand_crossrefs, *args, **kwargs ) - + if expand_crossrefs==False and include_crossrefs==True: # works because an entry crossrefed cannot crossref another entry crossrefs = dict() @@ -267,10 +249,10 @@ def bibtex_gen(out, db, entry_filter=FilterPaper(), entry_sort=SortConfYearPage( crossrefs[crossref] = db.entries[crossref] bibtex_write_entries( - out, - db, - entry_sort.sort(iter(crossrefs.items())), - expand_crossrefs=expand_crossrefs, + out, + db, + entry_sort.sort(iter(crossrefs.items())), + expand_crossrefs=expand_crossrefs, *args, **kwargs ) @@ -282,7 +264,7 @@ def bibtex_gen_str(db, *args, **kwargs): def sql_write_entry(out, entry, crossref=None): """ write entry for an entry in web2py sqlite (entry is a row corresponding to an entry) - @entry + @entry @arg crossref if None, does nothing, otherwise, merge fields in entry """ def key_sort(key): diff --git a/mybibtex/month_names.py b/mybibtex/month_names.py index 0cfba03..488efaa 100644 --- a/mybibtex/month_names.py +++ b/mybibtex/month_names.py @@ -12,4 +12,3 @@ 'nov': 'November', 'dec': 'December' } - diff --git a/mybibtex/parser.py b/mybibtex/parser.py index 4c4f545..d87e5d5 100644 --- a/mybibtex/parser.py +++ b/mybibtex/parser.py @@ -27,13 +27,13 @@ >>> parser = Parser() >>> bib_data = parser.parse_stream(StringIO(u''' ... @String{SCI = "Science"} -... +... ... @String{JFernandez = "Fernandez, Julio M."} ... @String{HGaub = "Gaub, Hermann E."} ... @String{MGautel = "Gautel, Mathias"} ... @String{FOesterhelt = "Oesterhelt, Filipp"} ... @String{MRief = "Rief, Matthias"} -... +... ... @Article{rief97b, ... author = MRief #" and "# MGautel #" and "# FOesterhelt ... #" and "# JFernandez #" and "# HGaub, @@ -209,7 +209,7 @@ def parse_entry_body(self, body_end): def parse_entry_fields(self): while True: self.current_field_name = None - self.current_value = Value() + self.current_value = Value() self.parse_field() if self.current_field_name and self.current_value: self.current_fields.append((self.current_field_name, self.current_value))