Skip to content

Commit 46cb5cb

Browse files
committed
Did a number of changes to the author extraction method of class Draft in order to make it able to match up names with double-word family names on the first page (A. Foo Bar) with (familyname, given-name) ordering (Foo Bar Any) in the Authors' Addresses section. Regression tested against 200+ known good author extraction results. A number of stronger restrictions in regular expressions had to be introduced to avoid regression, which is probably all to the good.
- Legacy-Id: 8507
1 parent 594684a commit 46cb5cb

1 file changed

Lines changed: 34 additions & 19 deletions

File tree

ietf/utils/draft.py

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
import sys
4141
import time
4242

43-
version = "0.33"
43+
version = "0.34"
4444
program = os.path.basename(sys.argv[0])
4545
progdir = os.path.dirname(sys.argv[0])
4646

@@ -508,8 +508,9 @@ def extract_authors(self):
508508

509509
def make_authpat(hon, first, last, suffix):
510510
def dotexp(s):
511-
s = re.sub("\. ", ".* ", s)
512-
s = re.sub("\.$", ".*", s)
511+
s = re.sub(r"\. ", r"\w* ", s)
512+
s = re.sub(r"\.$", r"\w*", s)
513+
s = re.sub(r"\.(\w)", r"\w* \1", s)
513514
return s
514515
first = dotexp(first)
515516
last = dotexp(last)
@@ -521,15 +522,15 @@ def dotexp(s):
521522

522523
# Double names (e.g., Jean-Michel) are abbreviated as two letter
523524
# connected by a dash -- let this expand appropriately
524-
first = re.sub("^([A-Z])-([A-Z])\.\*", r"\1.*-\2.*", first)
525+
first = re.sub(r"^([A-Z])-([A-Z])\\w\*", r"\1.*-\2.*", first)
525526

526527
# Some chinese names are shown with double-letter(latin) abbreviated given names, rather than
527528
# a single-letter(latin) abbreviation:
528-
first = re.sub("^([A-Z])[A-Z]+\.\*", r"\1[-\w]+", first)
529+
first = re.sub(r"^([A-Z])[A-Z]+\\w\*", r"\1[-\w]+", first)
529530

530531
# permit insertion of middle names between first and last, and
531532
# add possible honorific and suffix information
532-
authpat = "(?:^| and )(?:%(hon)s ?)?(%(first)s\S*( +[^ ]+)* +%(last)s)( *\(.*|,( [A-Z][-A-Za-z0-9]*)?| %(suffix)s| [A-Z][a-z]+)?" % {"hon":hon, "first":first, "last":last, "suffix":suffix,}
533+
authpat = r"(?:^| and )(?:%(hon)s ?)?(%(first)s\S*( +[^ ]+)* +%(last)s)( *\(.*|,( [A-Z][-A-Za-z0-9]*)?| %(suffix)s| [A-Z][a-z]+)?" % {"hon":hon, "first":first, "last":last, "suffix":suffix,}
533534
return authpat
534535

535536
authors = []
@@ -545,7 +546,7 @@ def dotexp(s):
545546
self._docheader += line+"\n"
546547
author_on_line = False
547548

548-
_debug( "**" + line)
549+
_debug( " ** " + line)
549550
leading_space = len(re.findall("^ *", line)[0])
550551
line_len = len(line.rstrip())
551552
trailing_space = line_len <= 72 and 72 - line_len or 0
@@ -689,10 +690,15 @@ def dotexp(s):
689690
author = "[A-Z].+ " + author
690691
first, last = author.rsplit(" ", 1)
691692
else:
692-
first, last = author.rsplit(" ", 1)
693-
if "." in first and not ". " in first:
694-
first = first.replace(".", ". ").strip()
695-
693+
if "." in author:
694+
first, last = author.rsplit(".", 1)
695+
first += "."
696+
else:
697+
first, last = author.rsplit(" ", 1)
698+
if "." in first and not ". " in first:
699+
first = first.replace(".", ". ").strip()
700+
first = first.strip()
701+
last = last.strip()
696702
prefix_match = re.search(" %(prefix)s$" % aux, first)
697703
if prefix_match:
698704
prefix = prefix_match.group(1)
@@ -770,17 +776,25 @@ def dotexp(s):
770776
first = given_names
771777
middle = None
772778
names = (first, middle, surname, suffix)
779+
773780
if suffix:
774781
fullname = fullname+" "+suffix
775-
parts = [ n for n in names if n ]
776-
revpt = [ n for n in names if n ]
777-
revpt.reverse()
778-
if not ((" ".join(parts) == fullname) or (" ".join(revpt) == fullname)):
782+
for names in [
783+
(first, middle, surname, suffix),
784+
(first, surname, middle, suffix),
785+
(middle, first, surname, suffix),
786+
(middle, surname, first, suffix),
787+
(surname, first, middle, suffix),
788+
(surname, middle, first, suffix),
789+
]:
790+
parts = [ n for n in names if n ]
791+
if (" ".join(parts) == fullname):
792+
authors[i] = (fullname, first, middle, surname, suffix)
793+
companies[i] = None
794+
break
795+
else:
779796
_warn("Author tuple doesn't match text in draft: %s, %s" % (authors[i], fullname))
780797
authors[i] = None
781-
else:
782-
authors[i] = (fullname, first, middle, surname, suffix)
783-
companies[i] = None
784798
break
785799
except AssertionError:
786800
sys.stderr.write("filename: "+self.filename+"\n")
@@ -819,7 +833,8 @@ def dotexp(s):
819833
# for a in authors:
820834
# if a and a not in companies_seen:
821835
# _debug("Search for: %s"%(r"(^|\W)"+re.sub("\.? ", ".* ", a)+"(\W|$)"))
822-
authmatch = [ a for a in authors[i+1:] if a and not a.lower() in companies_seen and (re.search((r"(?i)(^|\W)"+re.sub("[. ]+", ".* ", a)+"(\W|$)"), line.strip()) or acronym_match(a, line.strip()) )]
836+
authmatch = [ a for a in authors[i+1:] if a and not a.lower() in companies_seen and (re.search((r"(?i)(^|\W)"+re.sub("[. ]+", ".*", a)+"(\W|$)"), line.strip()) or acronym_match(a, line.strip()) )]
837+
823838
if authmatch:
824839
_debug(" ? Other author or company ? : %s" % authmatch)
825840
_debug(" Line: "+line.strip())

0 commit comments

Comments
 (0)