prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  How to annotate first initials in XML
  @mjpost and I have been discussing offline: When an author's name is written using a first initial on the paper itself, but the complete first name is known (at least probably), how should it be written in the XML? Some ideas (others are possible):
  
  ```
  a) <author><first>Matt</first><last>Post</last></author>
  b) <author><first>M[att]</first><last>Post</last></author>
  c) <author><first complete="Matt">M.</first><last>Post</last></author>
  d) <author><first initials="M.">Matt</first><last>Post</last></author>
  e) <author><first>M<completion>att</completion></first><last>Post</last></author>
  ```
  
  We have a big influx of these, thanks to the hard work of the LREC organizers supplying complete first names, so if the answer is anything other than (a), it would be nice to decide before merging in the new ones.
  
  JATS uses (d) but without the period (https://jats.nlm.nih.gov/archiving/tag-library/1.1d1/n-zu82.html).
  
  Some special cases to consider:
  
  - Initials are not always initials: `Wm.` to `William`, `R.` to `Bob`
  - Middle initials, double first names, second last names, etc. can be expanded from initials as well.
  - ADDED: Possibly related, possibly a can of worms: There are some (but not many) papers where the author's name is written _only_ in a non-Latin script (e.g., https://www.aclweb.org/anthology/O00-1008), so the editor has filled in a transliteration.
  
  </issue>
  <code>
  [start of bin/check_name_variants.py]
  1 import yaml
  2 import sys
  3 import lxml.etree as etree
  4 
  5 person_fields = {'canonical', 'variants', 'comment'}
  6 name_fields = {'first', 'last', 'papers'}
  7 
  8 def text(node):
  9     """Extract text from an XML node."""
  10     if node is None: return ''
  11     s = ''.join(node.itertext())
  12     return ' '.join(s.split())
  13 
  14 def name(d):
  15     return (d['first'], d['last'])
  16 
  17 if len(sys.argv) > 2:
  18     names = set()
  19     for xmlfilename in sys.argv[2:]:
  20         try:
  21             tree = etree.parse(xmlfilename)
  22         except:
  23             print(xmlfilename)
  24             raise
  25         for paper in tree.getroot().findall('paper'):
  26             for person in paper.xpath('./author|./editor'):
  27                 first = text(person.find('first'))
  28                 last = text(person.find('last'))
  29                 names.add((first,last))
  30 else:
  31     names = None
  32 
  33 doc = yaml.load(open(sys.argv[1]))
  34 
  35 assert isinstance(doc, list)
  36 for person in doc:
  37     assert isinstance(person, dict), person
  38     assert set(person.keys()).issubset(person_fields), person
  39     assert 'canonical' in person, person
  40     assert isinstance(person['canonical'], dict), person
  41     assert set(person['canonical']).issubset(name_fields), person
  42     if names is not None and name(person['canonical']) not in names:
  43         print('unused name', person['canonical'])
  44     dupes = {name(person['canonical'])}
  45     assert 'variants' in person, person
  46     assert isinstance(person['variants'], list), person
  47     for variant in person['variants']:
  48         assert set(variant).issubset(name_fields), person
  49         if names is not None and name(variant) not in names:
  50             print('unused name', variant)
  51         assert name(variant) not in dupes, variant
  52         dupes.add(name(variant))
  53         
  54
  [end of bin/check_name_variants.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/bin/check_name_variants.py b/bin/check_name_variants.py
  --- a/bin/check_name_variants.py
  +++ b/bin/check_name_variants.py
  @@ -1,14 +1,19 @@
   import yaml
   import sys
   import lxml.etree as etree
  +import logging
   
   person_fields = {'canonical', 'variants', 'comment'}
   name_fields = {'first', 'last', 'papers'}
   
   def text(node):
       """Extract text from an XML node."""
  -    if node is None: return ''
  -    s = ''.join(node.itertext())
  +    if node is None:
  +        return ''
  +    if 'complete' in node.attrib:
  +        s = node.attrib['complete']
  +    else:
  +        s = ''.join(node.itertext())
       return ' '.join(s.split())
   
   def name(d):
  @@ -20,7 +25,7 @@
           try:
               tree = etree.parse(xmlfilename)
           except:
  -            print(xmlfilename)
  +            logging.error("couldn't parse {}".format(xmlfilename))
               raise
           for paper in tree.getroot().findall('paper'):
               for person in paper.xpath('./author|./editor'):
  @@ -40,14 +45,15 @@
       assert isinstance(person['canonical'], dict), person
       assert set(person['canonical']).issubset(name_fields), person
       if names is not None and name(person['canonical']) not in names:
  -        print('unused name', person['canonical'])
  +        logging.warning('unused name: {}'.format(person['canonical']))
       dupes = {name(person['canonical'])}
       assert 'variants' in person, person
       assert isinstance(person['variants'], list), person
       for variant in person['variants']:
           assert set(variant).issubset(name_fields), person
           if names is not None and name(variant) not in names:
  -            print('unused name', variant)
  +            logging.warning('unused name: {}'.format(variant))
           assert name(variant) not in dupes, variant
           dupes.add(name(variant))
           
  +print(yaml.dump(doc, allow_unicode=True))
  
verification_info: {"golden_diff": "diff --git a/bin/check_name_variants.py b/bin/check_name_variants.py\n--- a/bin/check_name_variants.py\n+++ b/bin/check_name_variants.py\n@@ -1,14 +1,19 @@\n import yaml\n import sys\n import lxml.etree as etree\n+import logging\n \n person_fields = {'canonical', 'variants', 'comment'}\n name_fields = {'first', 'last', 'papers'}\n \n def text(node):\n     \"\"\"Extract text from an XML node.\"\"\"\n-    if node is None: return ''\n-    s = ''.join(node.itertext())\n+    if node is None:\n+        return ''\n+    if 'complete' in node.attrib:\n+        s = node.attrib['complete']\n+    else:\n+        s = ''.join(node.itertext())\n     return ' '.join(s.split())\n \n def name(d):\n@@ -20,7 +25,7 @@\n         try:\n             tree = etree.parse(xmlfilename)\n         except:\n-            print(xmlfilename)\n+            logging.error(\"couldn't parse {}\".format(xmlfilename))\n             raise\n         for paper in tree.getroot().findall('paper'):\n             for person in paper.xpath('./author|./editor'):\n@@ -40,14 +45,15 @@\n     assert isinstance(person['canonical'], dict), person\n     assert set(person['canonical']).issubset(name_fields), person\n     if names is not None and name(person['canonical']) not in names:\n-        print('unused name', person['canonical'])\n+        logging.warning('unused name: {}'.format(person['canonical']))\n     dupes = {name(person['canonical'])}\n     assert 'variants' in person, person\n     assert isinstance(person['variants'], list), person\n     for variant in person['variants']:\n         assert set(variant).issubset(name_fields), person\n         if names is not None and name(variant) not in names:\n-            print('unused name', variant)\n+            logging.warning('unused name: {}'.format(variant))\n         assert name(variant) not in dupes, variant\n         dupes.add(name(variant))\n         \n+print(yaml.dump(doc, allow_unicode=True))\n", "issue": "How to annotate first initials in XML\n@mjpost and I have been discussing offline: When an author's name is written using a first initial on the paper itself, but the complete first name is known (at least probably), how should it be written in the XML? Some ideas (others are possible):\r\n\r\n```\r\na) <author><first>Matt</first><last>Post</last></author>\r\nb) <author><first>M[att]</first><last>Post</last></author>\r\nc) <author><first complete=\"Matt\">M.</first><last>Post</last></author>\r\nd) <author><first initials=\"M.\">Matt</first><last>Post</last></author>\r\ne) <author><first>M<completion>att</completion></first><last>Post</last></author>\r\n```\r\n\r\nWe have a big influx of these, thanks to the hard work of the LREC organizers supplying complete first names, so if the answer is anything other than (a), it would be nice to decide before merging in the new ones.\r\n\r\nJATS uses (d) but without the period (https://jats.nlm.nih.gov/archiving/tag-library/1.1d1/n-zu82.html).\r\n\r\nSome special cases to consider:\r\n\r\n- Initials are not always initials: `Wm.` to `William`, `R.` to `Bob`\r\n- Middle initials, double first names, second last names, etc. can be expanded from initials as well.\r\n- ADDED: Possibly related, possibly a can of worms: There are some (but not many) papers where the author's name is written _only_ in a non-Latin script (e.g., https://www.aclweb.org/anthology/O00-1008), so the editor has filled in a transliteration.\n", "before_files": [{"content": "import yaml\nimport sys\nimport lxml.etree as etree\n\nperson_fields = {'canonical', 'variants', 'comment'}\nname_fields = {'first', 'last', 'papers'}\n\ndef text(node):\n    \"\"\"Extract text from an XML node.\"\"\"\n    if node is None: return ''\n    s = ''.join(node.itertext())\n    return ' '.join(s.split())\n\ndef name(d):\n    return (d['first'], d['last'])\n\nif len(sys.argv) > 2:\n    names = set()\n    for xmlfilename in sys.argv[2:]:\n        try:\n            tree = etree.parse(xmlfilename)\n        except:\n            print(xmlfilename)\n            raise\n        for paper in tree.getroot().findall('paper'):\n            for person in paper.xpath('./author|./editor'):\n                first = text(person.find('first'))\n                last = text(person.find('last'))\n                names.add((first,last))\nelse:\n    names = None\n\ndoc = yaml.load(open(sys.argv[1]))\n\nassert isinstance(doc, list)\nfor person in doc:\n    assert isinstance(person, dict), person\n    assert set(person.keys()).issubset(person_fields), person\n    assert 'canonical' in person, person\n    assert isinstance(person['canonical'], dict), person\n    assert set(person['canonical']).issubset(name_fields), person\n    if names is not None and name(person['canonical']) not in names:\n        print('unused name', person['canonical'])\n    dupes = {name(person['canonical'])}\n    assert 'variants' in person, person\n    assert isinstance(person['variants'], list), person\n    for variant in person['variants']:\n        assert set(variant).issubset(name_fields), person\n        if names is not None and name(variant) not in names:\n            print('unused name', variant)\n        assert name(variant) not in dupes, variant\n        dupes.add(name(variant))\n        \n", "path": "bin/check_name_variants.py"}]}