prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  RI: state legislator first names contain middle initials
  For example, https://openstates.org/api/v1/legislators/RIL000179/ has first_name of "Moira J." and nothing in middle_name for Moira J. Walsh.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `openstates/ri/legislators.py`
  Content:
  ```
  1 import re
  2 import string
  3 
  4 from billy.scrape import NoDataForPeriod
  5 from billy.scrape.legislators import LegislatorScraper, Legislator
  6 from openstates.utils import LXMLMixin
  7 
  8 import lxml.html
  9 import xlrd
  10 
  11 excel_mapping = {
  12     'district': 0,
  13     'town_represented': 1,
  14     'full_name': 2,
  15     'party': 3,
  16     'address': 4,
  17     'email': 5,
  18 }
  19 
  20 class RILegislatorScraper(LegislatorScraper, LXMLMixin):
  21     jurisdiction = 'ri'
  22     latest_only = True
  23 
  24     def scrape(self, chamber, term):
  25         if chamber == 'upper':
  26             url = ('http://webserver.rilin.state.ri.us/Documents/Senators.xls')
  27             rep_type = 'Senator'
  28             source_url = 'http://www.rilin.state.ri.us/senators/default.aspx'
  29             source_url_title_replacement = rep_type
  30             contact_url = 'http://webserver.rilin.state.ri.us/Email/SenEmailListDistrict.asp'
  31         elif chamber == 'lower':
  32             url = ('http://webserver.rilin.state.ri.us/Documents/Representatives.xls')
  33             rep_type = 'Representative'
  34             source_url = 'http://www.rilin.state.ri.us/representatives/default.aspx'
  35             source_url_title_replacement = 'Rep. '
  36             contact_url = 'http://webserver.rilin.state.ri.us/Email/RepEmailListDistrict.asp'
  37 
  38         self.urlretrieve(url, 'ri_leg.xls')
  39 
  40         wb = xlrd.open_workbook('ri_leg.xls')
  41         sh = wb.sheet_by_index(0)
  42 
  43         # This isn't perfect but it's cheap and better than using the
  44         # XLS doc as the source URL for all legislators.
  45         # 374: RI: legislator url
  46         leg_source_url_map = {}
  47         leg_page = self.lxmlize(source_url)
  48 
  49         for link in leg_page.xpath('//td[@class="ms-vb2"]'):
  50             leg_name = link.text_content().replace(source_url_title_replacement,'')
  51             leg_url = link.xpath("..//a")[0].attrib['href']
  52             leg_source_url_map[leg_name] = leg_url
  53 
  54         for rownum in xrange(1, sh.nrows):
  55             d = {}
  56             for field, col_num in excel_mapping.iteritems():
  57                 d[field] = sh.cell(rownum, col_num).value
  58 
  59             if d['full_name'].upper() == "VACANT":
  60                 self.warning(
  61                     "District {}'s seat is vacant".format(int(d['district'])))
  62                 continue
  63 
  64             slug = re.match(
  65                 "(?P<class>sen|rep)-(?P<slug>.*)@(rilin\.state\.ri\.us|rilegislature\.gov)", d['email']
  66             )
  67             
  68             if 'asp' in d['email']:
  69                 d['email'] = None
  70 
  71             if d['email'] is not None:
  72                 info = slug.groupdict()
  73                 info['chamber'] = "senators" if info['class'] == 'sen' else "representatives"
  74 
  75                 url = ("http://www.rilin.state.ri.us/{chamber}/"
  76                        "{slug}/Pages/Biography.aspx".format(**info))
  77 
  78             dist = str(int(d['district']))
  79             district_name = dist
  80 
  81             assert d['full_name'].startswith(rep_type), "Improper name found"
  82             full_name = re.sub(r"^{}(?=\s?[A-Z].*$)".format(rep_type), '', d['full_name']).strip()
  83             translate = {
  84                 "Democrat"    : "Democratic",
  85                 "Republican"  : "Republican",
  86                 "Independent" : "Independent"
  87             }
  88 
  89             homepage_url = None
  90             url_names = lxml.html.fromstring(self.get(source_url).text)
  91             url_names = url_names.xpath('//td[@class="ms-vb2"]/a/@href')
  92             modified_name = re.sub(r'[^\w\s]', '', full_name)
  93             modified_name = modified_name.replace(' ', '').strip('').lower()
  94 
  95             for el in url_names:
  96                 if 'default.aspx' in el:
  97                     el = el.replace('default.aspx', '')
  98                     el = el.strip('')
  99                 if el[-1] == '/':
  100                     el = el[:-1]
  101                 el = el.lower()
  102                 url_name_array = el.split('/')
  103                 if url_name_array[-1] in modified_name:
  104                     #remove '/default.aspx' and add last name
  105                     homepage_url = source_url[:-12] + url_name_array[-1]
  106 
  107             kwargs = {
  108                 "town_represented": d['town_represented'],
  109             }
  110 
  111             contact = self.lxmlize(contact_url)
  112             contact_phone = contact.xpath('//tr[@valign="TOP"]//td[@class="bodyCopy"]/text() | //td[@class="bodyCopy"]//center/text()')
  113 
  114             phone = None
  115             for el in contact_phone:
  116                 if len(el) <= 2 and dist == el:
  117                     number = contact_phone.index(el)
  118                     phone = contact_phone[number + 2]
  119                     phone = phone.strip()
  120 
  121             email = None
  122             if d['email'] is not None:
  123                 email = d['email']
  124 
  125             if homepage_url is not None:
  126                 kwargs['url'] = homepage_url
  127 
  128             if d['address'] is '':
  129                 d['address'] = 'No Address Found'
  130 
  131             leg = Legislator(term, chamber, district_name, full_name,
  132                              '', '', '',
  133                              translate[d['party']],
  134                              **kwargs)
  135 
  136             leg.add_office('district', 'Dictrict Office', address=d['address'], phone=phone, email=email)
  137             leg.add_source(source_url)
  138             leg.add_source(contact_url)
  139             if homepage_url:
  140                 leg.add_source(homepage_url)
  141             self.save_legislator(leg)
  142
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/openstates/ri/legislators.py b/openstates/ri/legislators.py
  --- a/openstates/ri/legislators.py
  +++ b/openstates/ri/legislators.py
  @@ -128,8 +128,14 @@
               if d['address'] is '':
                   d['address'] = 'No Address Found'
   
  +            # RI is very fond of First M. Last name formats and
  +            # they're being misparsed upstream, so fix here
  +            (first, middle, last) = ('','','')
  +            if re.match(r'^\S+\s[A-Z]\.\s\S+$', full_name):
  +                (first, middle, last) = full_name.split()
  +                
               leg = Legislator(term, chamber, district_name, full_name,
  -                             '', '', '',
  +                             first, last, middle,
                                translate[d['party']],
                                **kwargs)
  
verification_info: {"golden_diff": "diff --git a/openstates/ri/legislators.py b/openstates/ri/legislators.py\n--- a/openstates/ri/legislators.py\n+++ b/openstates/ri/legislators.py\n@@ -128,8 +128,14 @@\n             if d['address'] is '':\n                 d['address'] = 'No Address Found'\n \n+            # RI is very fond of First M. Last name formats and\n+            # they're being misparsed upstream, so fix here\n+            (first, middle, last) = ('','','')\n+            if re.match(r'^\\S+\\s[A-Z]\\.\\s\\S+$', full_name):\n+                (first, middle, last) = full_name.split()\n+                \n             leg = Legislator(term, chamber, district_name, full_name,\n-                             '', '', '',\n+                             first, last, middle,\n                              translate[d['party']],\n                              **kwargs)\n", "issue": "RI: state legislator first names contain middle initials\nFor example, https://openstates.org/api/v1/legislators/RIL000179/ has first_name of \"Moira J.\" and nothing in middle_name for Moira J. Walsh.\n", "before_files": [{"content": "import re\nimport string\n\nfrom billy.scrape import NoDataForPeriod\nfrom billy.scrape.legislators import LegislatorScraper, Legislator\nfrom openstates.utils import LXMLMixin\n\nimport lxml.html\nimport xlrd\n\nexcel_mapping = {\n    'district': 0,\n    'town_represented': 1,\n    'full_name': 2,\n    'party': 3,\n    'address': 4,\n    'email': 5,\n}\n\nclass RILegislatorScraper(LegislatorScraper, LXMLMixin):\n    jurisdiction = 'ri'\n    latest_only = True\n\n    def scrape(self, chamber, term):\n        if chamber == 'upper':\n            url = ('http://webserver.rilin.state.ri.us/Documents/Senators.xls')\n            rep_type = 'Senator'\n            source_url = 'http://www.rilin.state.ri.us/senators/default.aspx'\n            source_url_title_replacement = rep_type\n            contact_url = 'http://webserver.rilin.state.ri.us/Email/SenEmailListDistrict.asp'\n        elif chamber == 'lower':\n            url = ('http://webserver.rilin.state.ri.us/Documents/Representatives.xls')\n            rep_type = 'Representative'\n            source_url = 'http://www.rilin.state.ri.us/representatives/default.aspx'\n            source_url_title_replacement = 'Rep. '\n            contact_url = 'http://webserver.rilin.state.ri.us/Email/RepEmailListDistrict.asp'\n\n        self.urlretrieve(url, 'ri_leg.xls')\n\n        wb = xlrd.open_workbook('ri_leg.xls')\n        sh = wb.sheet_by_index(0)\n\n        # This isn't perfect but it's cheap and better than using the\n        # XLS doc as the source URL for all legislators.\n        # 374: RI: legislator url\n        leg_source_url_map = {}\n        leg_page = self.lxmlize(source_url)\n\n        for link in leg_page.xpath('//td[@class=\"ms-vb2\"]'):\n            leg_name = link.text_content().replace(source_url_title_replacement,'')\n            leg_url = link.xpath(\"..//a\")[0].attrib['href']\n            leg_source_url_map[leg_name] = leg_url\n\n        for rownum in xrange(1, sh.nrows):\n            d = {}\n            for field, col_num in excel_mapping.iteritems():\n                d[field] = sh.cell(rownum, col_num).value\n\n            if d['full_name'].upper() == \"VACANT\":\n                self.warning(\n                    \"District {}'s seat is vacant\".format(int(d['district'])))\n                continue\n\n            slug = re.match(\n                \"(?P<class>sen|rep)-(?P<slug>.*)@(rilin\\.state\\.ri\\.us|rilegislature\\.gov)\", d['email']\n            )\n            \n            if 'asp' in d['email']:\n                d['email'] = None\n\n            if d['email'] is not None:\n                info = slug.groupdict()\n                info['chamber'] = \"senators\" if info['class'] == 'sen' else \"representatives\"\n\n                url = (\"http://www.rilin.state.ri.us/{chamber}/\"\n                       \"{slug}/Pages/Biography.aspx\".format(**info))\n\n            dist = str(int(d['district']))\n            district_name = dist\n\n            assert d['full_name'].startswith(rep_type), \"Improper name found\"\n            full_name = re.sub(r\"^{}(?=\\s?[A-Z].*$)\".format(rep_type), '', d['full_name']).strip()\n            translate = {\n                \"Democrat\"    : \"Democratic\",\n                \"Republican\"  : \"Republican\",\n                \"Independent\" : \"Independent\"\n            }\n\n            homepage_url = None\n            url_names = lxml.html.fromstring(self.get(source_url).text)\n            url_names = url_names.xpath('//td[@class=\"ms-vb2\"]/a/@href')\n            modified_name = re.sub(r'[^\\w\\s]', '', full_name)\n            modified_name = modified_name.replace(' ', '').strip('').lower()\n\n            for el in url_names:\n                if 'default.aspx' in el:\n                    el = el.replace('default.aspx', '')\n                    el = el.strip('')\n                if el[-1] == '/':\n                    el = el[:-1]\n                el = el.lower()\n                url_name_array = el.split('/')\n                if url_name_array[-1] in modified_name:\n                    #remove '/default.aspx' and add last name\n                    homepage_url = source_url[:-12] + url_name_array[-1]\n\n            kwargs = {\n                \"town_represented\": d['town_represented'],\n            }\n\n            contact = self.lxmlize(contact_url)\n            contact_phone = contact.xpath('//tr[@valign=\"TOP\"]//td[@class=\"bodyCopy\"]/text() | //td[@class=\"bodyCopy\"]//center/text()')\n\n            phone = None\n            for el in contact_phone:\n                if len(el) <= 2 and dist == el:\n                    number = contact_phone.index(el)\n                    phone = contact_phone[number + 2]\n                    phone = phone.strip()\n\n            email = None\n            if d['email'] is not None:\n                email = d['email']\n\n            if homepage_url is not None:\n                kwargs['url'] = homepage_url\n\n            if d['address'] is '':\n                d['address'] = 'No Address Found'\n\n            leg = Legislator(term, chamber, district_name, full_name,\n                             '', '', '',\n                             translate[d['party']],\n                             **kwargs)\n\n            leg.add_office('district', 'Dictrict Office', address=d['address'], phone=phone, email=email)\n            leg.add_source(source_url)\n            leg.add_source(contact_url)\n            if homepage_url:\n                leg.add_source(homepage_url)\n            self.save_legislator(leg)\n", "path": "openstates/ri/legislators.py"}], "after_files": [{"content": "import re\nimport string\n\nfrom billy.scrape import NoDataForPeriod\nfrom billy.scrape.legislators import LegislatorScraper, Legislator\nfrom openstates.utils import LXMLMixin\n\nimport lxml.html\nimport xlrd\n\nexcel_mapping = {\n    'district': 0,\n    'town_represented': 1,\n    'full_name': 2,\n    'party': 3,\n    'address': 4,\n    'email': 5,\n}\n\nclass RILegislatorScraper(LegislatorScraper, LXMLMixin):\n    jurisdiction = 'ri'\n    latest_only = True\n\n    def scrape(self, chamber, term):\n        if chamber == 'upper':\n            url = ('http://webserver.rilin.state.ri.us/Documents/Senators.xls')\n            rep_type = 'Senator'\n            source_url = 'http://www.rilin.state.ri.us/senators/default.aspx'\n            source_url_title_replacement = rep_type\n            contact_url = 'http://webserver.rilin.state.ri.us/Email/SenEmailListDistrict.asp'\n        elif chamber == 'lower':\n            url = ('http://webserver.rilin.state.ri.us/Documents/Representatives.xls')\n            rep_type = 'Representative'\n            source_url = 'http://www.rilin.state.ri.us/representatives/default.aspx'\n            source_url_title_replacement = 'Rep. '\n            contact_url = 'http://webserver.rilin.state.ri.us/Email/RepEmailListDistrict.asp'\n\n        self.urlretrieve(url, 'ri_leg.xls')\n\n        wb = xlrd.open_workbook('ri_leg.xls')\n        sh = wb.sheet_by_index(0)\n\n        # This isn't perfect but it's cheap and better than using the\n        # XLS doc as the source URL for all legislators.\n        # 374: RI: legislator url\n        leg_source_url_map = {}\n        leg_page = self.lxmlize(source_url)\n\n        for link in leg_page.xpath('//td[@class=\"ms-vb2\"]'):\n            leg_name = link.text_content().replace(source_url_title_replacement,'')\n            leg_url = link.xpath(\"..//a\")[0].attrib['href']\n            leg_source_url_map[leg_name] = leg_url\n\n        for rownum in xrange(1, sh.nrows):\n            d = {}\n            for field, col_num in excel_mapping.iteritems():\n                d[field] = sh.cell(rownum, col_num).value\n\n            if d['full_name'].upper() == \"VACANT\":\n                self.warning(\n                    \"District {}'s seat is vacant\".format(int(d['district'])))\n                continue\n\n            slug = re.match(\n                \"(?P<class>sen|rep)-(?P<slug>.*)@(rilin\\.state\\.ri\\.us|rilegislature\\.gov)\", d['email']\n            )\n            \n            if 'asp' in d['email']:\n                d['email'] = None\n\n            if d['email'] is not None:\n                info = slug.groupdict()\n                info['chamber'] = \"senators\" if info['class'] == 'sen' else \"representatives\"\n\n                url = (\"http://www.rilin.state.ri.us/{chamber}/\"\n                       \"{slug}/Pages/Biography.aspx\".format(**info))\n\n            dist = str(int(d['district']))\n            district_name = dist\n\n            assert d['full_name'].startswith(rep_type), \"Improper name found\"\n            full_name = re.sub(r\"^{}(?=\\s?[A-Z].*$)\".format(rep_type), '', d['full_name']).strip()\n            translate = {\n                \"Democrat\"    : \"Democratic\",\n                \"Republican\"  : \"Republican\",\n                \"Independent\" : \"Independent\"\n            }\n\n            homepage_url = None\n            url_names = lxml.html.fromstring(self.get(source_url).text)\n            url_names = url_names.xpath('//td[@class=\"ms-vb2\"]/a/@href')\n            modified_name = re.sub(r'[^\\w\\s]', '', full_name)\n            modified_name = modified_name.replace(' ', '').strip('').lower()\n\n            for el in url_names:\n                if 'default.aspx' in el:\n                    el = el.replace('default.aspx', '')\n                    el = el.strip('')\n                if el[-1] == '/':\n                    el = el[:-1]\n                el = el.lower()\n                url_name_array = el.split('/')\n                if url_name_array[-1] in modified_name:\n                    #remove '/default.aspx' and add last name\n                    homepage_url = source_url[:-12] + url_name_array[-1]\n\n            kwargs = {\n                \"town_represented\": d['town_represented'],\n            }\n\n            contact = self.lxmlize(contact_url)\n            contact_phone = contact.xpath('//tr[@valign=\"TOP\"]//td[@class=\"bodyCopy\"]/text() | //td[@class=\"bodyCopy\"]//center/text()')\n\n            phone = None\n            for el in contact_phone:\n                if len(el) <= 2 and dist == el:\n                    number = contact_phone.index(el)\n                    phone = contact_phone[number + 2]\n                    phone = phone.strip()\n\n            email = None\n            if d['email'] is not None:\n                email = d['email']\n\n            if homepage_url is not None:\n                kwargs['url'] = homepage_url\n\n            if d['address'] is '':\n                d['address'] = 'No Address Found'\n\n            # RI is very fond of First M. Last name formats and\n            # they're being misparsed upstream, so fix here\n            (first, middle, last) = ('','','')\n            if re.match(r'^\\S+\\s[A-Z]\\.\\s\\S+$', full_name):\n                (first, middle, last) = full_name.split()\n                \n            leg = Legislator(term, chamber, district_name, full_name,\n                             first, last, middle,\n                             translate[d['party']],\n                             **kwargs)\n\n            leg.add_office('district', 'Dictrict Office', address=d['address'], phone=phone, email=email)\n            leg.add_source(source_url)\n            leg.add_source(contact_url)\n            if homepage_url:\n                leg.add_source(homepage_url)\n            self.save_legislator(leg)\n", "path": "openstates/ri/legislators.py"}]}