We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
NY: events aren't scraping
State: NY

Event scraper is broken & needs investigation.

--- 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/ny/events.py`
Content:
```
1 import re
2 import datetime as dt
3 import pytz
4 import lxml.html
5 from billy.scrape.events import EventScraper, Event
6 from openstates.utils import LXMLMixin
7 
8 url = "http://assembly.state.ny.us/leg/?sh=hear"
9 
10 
11 class NYEventScraper(EventScraper, LXMLMixin):
12     _tz = pytz.timezone('US/Eastern')
13     jurisdiction = 'ny'
14 
15     def lower_parse_page(self, url, session):
16         page = self.lxmlize(url)
17         tables = page.xpath("//table[@class='pubhrgtbl']")
18         date = None
19         ctty = None
20         chamber = 'other'
21         for table in tables:
22             metainf = {}
23             rows = table.xpath(".//tr")
24             for row in rows:
25                 tds = row.xpath("./*")
26                 if len(tds) < 2:
27                     continue
28                 key, value = tds
29                 if key.tag == 'th':
30                     date = key.text_content()
31                     date = re.sub("\s+", " ", date)
32                     date = re.sub(".*POSTPONED NEW DATE", "", date).strip()
33                     ctty = value.xpath(".//strong")[0]
34                     ctty = ctty.text_content()
35 
36                     chamber = 'other'
37                     if "senate" in ctty.lower():
38                         chamber = 'upper'
39                     if "house" in ctty.lower():
40                         chamber = 'lower'
41                     if "joint" in ctty.lower():
42                         chamber = 'joint'
43                 elif key.tag == 'td':
44                     key = key.text_content().strip()
45                     value = value.text_content().strip()
46                     value = value.replace(u'\x96', '-')
47                     value = re.sub("\s+", " ", value)
48                     metainf[key] = value
49 
50             time = metainf['Time:']
51             repl = {
52                 "A.M.": "AM",
53                 "P.M.": "PM",
54             }
55             drepl = {
56                 "Sept": "Sep"
57             }
58             for r in repl:
59                 time = time.replace(r, repl[r])
60 
61             for r in drepl:
62                 date = date.replace(r, drepl[r])
63 
64             time = re.sub("-.*", "", time)
65             time = time.strip()
66 
67             year = dt.datetime.now().year
68 
69             date = "%s %s %s" % (
70                 date,
71                 year,
72                 time
73             )
74 
75             if "tbd" in date.lower():
76                 continue
77 
78             date = date.replace(' PLEASE NOTE NEW TIME', '')
79 
80             # Check if the event has been postponed.
81             postponed = 'POSTPONED' in date
82             if postponed:
83                 date = date.replace(' POSTPONED', '')
84 
85             date_formats = ["%B %d %Y %I:%M %p", "%b. %d %Y %I:%M %p"]
86             datetime = None
87             for fmt in date_formats:
88                 try:
89                     datetime = dt.datetime.strptime(date, fmt)
90                 except ValueError:
91                     pass
92 
93             # If the datetime can't be parsed, bail.
94             if datetime is None:
95                 return
96 
97             title_key = set(metainf) & set([
98                 'Public Hearing:', 'Summit:', 'Roundtable:',
99                 'Public Roundtable:', 'Public Meeting:', 'Public Forum:',
100                 'Meeting:'])
101             assert len(title_key) == 1, "Couldn't determine event title."
102             title_key = list(title_key).pop()
103             title = metainf[title_key]
104 
105             title = re.sub(
106                     r"\*\*Click here to view public hearing notice\*\*",
107                     "",
108                     title
109                     )
110 
111             # If event was postponed, add a warning to the title.
112             if postponed:
113                 title = 'POSTPONED: %s' % title
114 
115             event = Event(session, datetime, 'committee:meeting',
116                           title,
117                           location=metainf['Place:'],
118                           contact=metainf['Contact:'])
119             if 'Media Contact:' in metainf:
120                 event.update(media_contact=metainf['Media Contact:'])
121             event.add_source(url)
122             event.add_participant('host',
123                                   ctty,
124                                   'committee',
125                                   chamber=chamber)
126 
127             self.save_event(event)
128 
129     def scrape(self, chamber, session):
130         self.scrape_lower(chamber, session)
131         #self.scrape_upper(chamber, session)
132 
133     def scrape_lower(self, chamber, session):
134         if chamber == 'other':
135             self.lower_parse_page(url, session)
136 
137     """
138     def scrape_upper(self, chamber, session):
139         if chamber != 'upper':
140             return
141 
142         url = (r'http://open.nysenate.gov/legislation/2.0/search.json?'
143                r'term=otype:meeting&pageSize=1000&pageIdx=%d')
144         page_index = 1
145         while True:
146             resp = self.get(url % page_index)
147             if not resp.json():
148                 break
149             if not resp.json()['response']['results']:
150                 break
151             for obj in resp.json()['response']['results']:
152                 event = self.upper_scrape_event(chamber, session, obj)
153                 if event:
154                     self.save_event(event)
155             page_index += 1
156 
157     def upper_scrape_event(self, chamber, session, obj):
158         meeting = obj['data']['meeting']
159         date = int(meeting['meetingDateTime'])
160         date = dt.datetime.fromtimestamp(date / 1000)
161         if str(date.year) not in session:
162             return
163         description = 'Committee Meeting: ' + meeting['committeeName']
164         event = Event(session, date, 'committee:meeting',
165                       description=description,
166                       location=meeting['location'] or 'No location given.')
167         event.add_source(obj['url'])
168         event.add_participant('chair', meeting['committeeChair'],
169                               'legislator', chamber='upper')
170         event.add_participant('host', meeting['committeeName'],
171                               'committee', chamber='upper')
172 
173         rgx = r'([a-z]+)(\d+)'
174         for bill in meeting['bills']:
175             raw_id = bill['senateBillNo']
176             bill_id = ' '.join(re.search(rgx, raw_id, re.I).groups())
177             event.add_related_bill(
178                 bill_id, type='bill',
179                 description=bill['summary'] or 'No description given.')
180         return event
181         """
182
```
--- 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()

```

diff --git a/openstates/ny/events.py b/openstates/ny/events.py
--- a/openstates/ny/events.py
+++ b/openstates/ny/events.py
@@ -26,12 +26,16 @@
                 if len(tds) < 2:
                     continue
                 key, value = tds
-                if key.tag == 'th':
+
+                if key.tag == 'th' and key.get("class") == 'hrgdate':
                     date = key.text_content()
-                    date = re.sub("\s+", " ", date)
+                    date = re.sub(r"\s+", " ", date)
                     date = re.sub(".*POSTPONED NEW DATE", "", date).strip()
-                    ctty = value.xpath(".//strong")[0]
-                    ctty = ctty.text_content()
+
+                # Due to the html structure this shouldn't be an elif
+                # It needs to fire twice in the same loop iteration
+                if value.tag == 'th' and value.get("class") == 'commtitle':
+                    ctty = value.text_content()
 
                     chamber = 'other'
                     if "senate" in ctty.lower():
@@ -40,11 +44,14 @@
                         chamber = 'lower'
                     if "joint" in ctty.lower():
                         chamber = 'joint'
+
+                    coms = value.xpath('.//div[contains(@class,"comm-txt")]/text()')
+
                 elif key.tag == 'td':
                     key = key.text_content().strip()
                     value = value.text_content().strip()
                     value = value.replace(u'\x96', '-')
-                    value = re.sub("\s+", " ", value)
+                    value = re.sub(r"\s+", " ", value)
                     metainf[key] = value
 
             time = metainf['Time:']
@@ -119,10 +126,12 @@
             if 'Media Contact:' in metainf:
                 event.update(media_contact=metainf['Media Contact:'])
             event.add_source(url)
-            event.add_participant('host',
-                                  ctty,
-                                  'committee',
-                                  chamber=chamber)
+
+            for com in coms:
+                event.add_participant('host',
+                                    com.strip(),
+                                    'committee',
+                                    chamber=self.classify_committee(com))
 
             self.save_event(event)
 
@@ -134,6 +143,16 @@
         if chamber == 'other':
             self.lower_parse_page(url, session)
 
+    def classify_committee(self, name):
+        chamber = 'other'
+        if "senate" in name.lower():
+            chamber = 'upper'
+        if "assembly" in name.lower():
+            chamber = 'lower'
+        if "joint" in name.lower():
+            chamber = 'joint'
+        return chamber
+
     """
     def scrape_upper(self, chamber, session):
         if chamber != 'upper':

{"golden_diff": "diff --git a/openstates/ny/events.py b/openstates/ny/events.py\n--- a/openstates/ny/events.py\n+++ b/openstates/ny/events.py\n@@ -26,12 +26,16 @@\n                 if len(tds) < 2:\n                     continue\n                 key, value = tds\n-                if key.tag == 'th':\n+\n+                if key.tag == 'th' and key.get(\"class\") == 'hrgdate':\n                     date = key.text_content()\n-                    date = re.sub(\"\\s+\", \" \", date)\n+                    date = re.sub(r\"\\s+\", \" \", date)\n                     date = re.sub(\".*POSTPONED NEW DATE\", \"\", date).strip()\n-                    ctty = value.xpath(\".//strong\")[0]\n-                    ctty = ctty.text_content()\n+\n+                # Due to the html structure this shouldn't be an elif\n+                # It needs to fire twice in the same loop iteration\n+                if value.tag == 'th' and value.get(\"class\") == 'commtitle':\n+                    ctty = value.text_content()\n \n                     chamber = 'other'\n                     if \"senate\" in ctty.lower():\n@@ -40,11 +44,14 @@\n                         chamber = 'lower'\n                     if \"joint\" in ctty.lower():\n                         chamber = 'joint'\n+\n+                    coms = value.xpath('.//div[contains(@class,\"comm-txt\")]/text()')\n+\n                 elif key.tag == 'td':\n                     key = key.text_content().strip()\n                     value = value.text_content().strip()\n                     value = value.replace(u'\\x96', '-')\n-                    value = re.sub(\"\\s+\", \" \", value)\n+                    value = re.sub(r\"\\s+\", \" \", value)\n                     metainf[key] = value\n \n             time = metainf['Time:']\n@@ -119,10 +126,12 @@\n             if 'Media Contact:' in metainf:\n                 event.update(media_contact=metainf['Media Contact:'])\n             event.add_source(url)\n-            event.add_participant('host',\n-                                  ctty,\n-                                  'committee',\n-                                  chamber=chamber)\n+\n+            for com in coms:\n+                event.add_participant('host',\n+                                    com.strip(),\n+                                    'committee',\n+                                    chamber=self.classify_committee(com))\n \n             self.save_event(event)\n \n@@ -134,6 +143,16 @@\n         if chamber == 'other':\n             self.lower_parse_page(url, session)\n \n+    def classify_committee(self, name):\n+        chamber = 'other'\n+        if \"senate\" in name.lower():\n+            chamber = 'upper'\n+        if \"assembly\" in name.lower():\n+            chamber = 'lower'\n+        if \"joint\" in name.lower():\n+            chamber = 'joint'\n+        return chamber\n+\n     \"\"\"\n     def scrape_upper(self, chamber, session):\n         if chamber != 'upper':\n", "issue": "NY: events aren't scraping\nState: NY\r\n\r\nEvent scraper is broken & needs investigation.\n", "before_files": [{"content": "import re\nimport datetime as dt\nimport pytz\nimport lxml.html\nfrom billy.scrape.events import EventScraper, Event\nfrom openstates.utils import LXMLMixin\n\nurl = \"http://assembly.state.ny.us/leg/?sh=hear\"\n\n\nclass NYEventScraper(EventScraper, LXMLMixin):\n    _tz = pytz.timezone('US/Eastern')\n    jurisdiction = 'ny'\n\n    def lower_parse_page(self, url, session):\n        page = self.lxmlize(url)\n        tables = page.xpath(\"//table[@class='pubhrgtbl']\")\n        date = None\n        ctty = None\n        chamber = 'other'\n        for table in tables:\n            metainf = {}\n            rows = table.xpath(\".//tr\")\n            for row in rows:\n                tds = row.xpath(\"./*\")\n                if len(tds) < 2:\n                    continue\n                key, value = tds\n                if key.tag == 'th':\n                    date = key.text_content()\n                    date = re.sub(\"\\s+\", \" \", date)\n                    date = re.sub(\".*POSTPONED NEW DATE\", \"\", date).strip()\n                    ctty = value.xpath(\".//strong\")[0]\n                    ctty = ctty.text_content()\n\n                    chamber = 'other'\n                    if \"senate\" in ctty.lower():\n                        chamber = 'upper'\n                    if \"house\" in ctty.lower():\n                        chamber = 'lower'\n                    if \"joint\" in ctty.lower():\n                        chamber = 'joint'\n                elif key.tag == 'td':\n                    key = key.text_content().strip()\n                    value = value.text_content().strip()\n                    value = value.replace(u'\\x96', '-')\n                    value = re.sub(\"\\s+\", \" \", value)\n                    metainf[key] = value\n\n            time = metainf['Time:']\n            repl = {\n                \"A.M.\": \"AM\",\n                \"P.M.\": \"PM\",\n            }\n            drepl = {\n                \"Sept\": \"Sep\"\n            }\n            for r in repl:\n                time = time.replace(r, repl[r])\n\n            for r in drepl:\n                date = date.replace(r, drepl[r])\n\n            time = re.sub(\"-.*\", \"\", time)\n            time = time.strip()\n\n            year = dt.datetime.now().year\n\n            date = \"%s %s %s\" % (\n                date,\n                year,\n                time\n            )\n\n            if \"tbd\" in date.lower():\n                continue\n\n            date = date.replace(' PLEASE NOTE NEW TIME', '')\n\n            # Check if the event has been postponed.\n            postponed = 'POSTPONED' in date\n            if postponed:\n                date = date.replace(' POSTPONED', '')\n\n            date_formats = [\"%B %d %Y %I:%M %p\", \"%b. %d %Y %I:%M %p\"]\n            datetime = None\n            for fmt in date_formats:\n                try:\n                    datetime = dt.datetime.strptime(date, fmt)\n                except ValueError:\n                    pass\n\n            # If the datetime can't be parsed, bail.\n            if datetime is None:\n                return\n\n            title_key = set(metainf) & set([\n                'Public Hearing:', 'Summit:', 'Roundtable:',\n                'Public Roundtable:', 'Public Meeting:', 'Public Forum:',\n                'Meeting:'])\n            assert len(title_key) == 1, \"Couldn't determine event title.\"\n            title_key = list(title_key).pop()\n            title = metainf[title_key]\n\n            title = re.sub(\n                    r\"\\*\\*Click here to view public hearing notice\\*\\*\",\n                    \"\",\n                    title\n                    )\n\n            # If event was postponed, add a warning to the title.\n            if postponed:\n                title = 'POSTPONED: %s' % title\n\n            event = Event(session, datetime, 'committee:meeting',\n                          title,\n                          location=metainf['Place:'],\n                          contact=metainf['Contact:'])\n            if 'Media Contact:' in metainf:\n                event.update(media_contact=metainf['Media Contact:'])\n            event.add_source(url)\n            event.add_participant('host',\n                                  ctty,\n                                  'committee',\n                                  chamber=chamber)\n\n            self.save_event(event)\n\n    def scrape(self, chamber, session):\n        self.scrape_lower(chamber, session)\n        #self.scrape_upper(chamber, session)\n\n    def scrape_lower(self, chamber, session):\n        if chamber == 'other':\n            self.lower_parse_page(url, session)\n\n    \"\"\"\n    def scrape_upper(self, chamber, session):\n        if chamber != 'upper':\n            return\n\n        url = (r'http://open.nysenate.gov/legislation/2.0/search.json?'\n               r'term=otype:meeting&pageSize=1000&pageIdx=%d')\n        page_index = 1\n        while True:\n            resp = self.get(url % page_index)\n            if not resp.json():\n                break\n            if not resp.json()['response']['results']:\n                break\n            for obj in resp.json()['response']['results']:\n                event = self.upper_scrape_event(chamber, session, obj)\n                if event:\n                    self.save_event(event)\n            page_index += 1\n\n    def upper_scrape_event(self, chamber, session, obj):\n        meeting = obj['data']['meeting']\n        date = int(meeting['meetingDateTime'])\n        date = dt.datetime.fromtimestamp(date / 1000)\n        if str(date.year) not in session:\n            return\n        description = 'Committee Meeting: ' + meeting['committeeName']\n        event = Event(session, date, 'committee:meeting',\n                      description=description,\n                      location=meeting['location'] or 'No location given.')\n        event.add_source(obj['url'])\n        event.add_participant('chair', meeting['committeeChair'],\n                              'legislator', chamber='upper')\n        event.add_participant('host', meeting['committeeName'],\n                              'committee', chamber='upper')\n\n        rgx = r'([a-z]+)(\\d+)'\n        for bill in meeting['bills']:\n            raw_id = bill['senateBillNo']\n            bill_id = ' '.join(re.search(rgx, raw_id, re.I).groups())\n            event.add_related_bill(\n                bill_id, type='bill',\n                description=bill['summary'] or 'No description given.')\n        return event\n        \"\"\"\n", "path": "openstates/ny/events.py"}], "after_files": [{"content": "import re\nimport datetime as dt\nimport pytz\nimport lxml.html\nfrom billy.scrape.events import EventScraper, Event\nfrom openstates.utils import LXMLMixin\n\nurl = \"http://assembly.state.ny.us/leg/?sh=hear\"\n\n\nclass NYEventScraper(EventScraper, LXMLMixin):\n    _tz = pytz.timezone('US/Eastern')\n    jurisdiction = 'ny'\n\n    def lower_parse_page(self, url, session):\n        page = self.lxmlize(url)\n        tables = page.xpath(\"//table[@class='pubhrgtbl']\")\n        date = None\n        ctty = None\n        chamber = 'other'\n        for table in tables:\n            metainf = {}\n            rows = table.xpath(\".//tr\")\n            for row in rows:\n                tds = row.xpath(\"./*\")\n                if len(tds) < 2:\n                    continue\n                key, value = tds\n\n                if key.tag == 'th' and key.get(\"class\") == 'hrgdate':\n                    date = key.text_content()\n                    date = re.sub(r\"\\s+\", \" \", date)\n                    date = re.sub(\".*POSTPONED NEW DATE\", \"\", date).strip()\n\n                # Due to the html structure this shouldn't be an elif\n                # It needs to fire twice in the same loop iteration\n                if value.tag == 'th' and value.get(\"class\") == 'commtitle':\n                    ctty = value.text_content()\n\n                    chamber = 'other'\n                    if \"senate\" in ctty.lower():\n                        chamber = 'upper'\n                    if \"house\" in ctty.lower():\n                        chamber = 'lower'\n                    if \"joint\" in ctty.lower():\n                        chamber = 'joint'\n\n                    coms = value.xpath('.//div[contains(@class,\"comm-txt\")]/text()')\n\n                elif key.tag == 'td':\n                    key = key.text_content().strip()\n                    value = value.text_content().strip()\n                    value = value.replace(u'\\x96', '-')\n                    value = re.sub(r\"\\s+\", \" \", value)\n                    metainf[key] = value\n\n            time = metainf['Time:']\n            repl = {\n                \"A.M.\": \"AM\",\n                \"P.M.\": \"PM\",\n            }\n            drepl = {\n                \"Sept\": \"Sep\"\n            }\n            for r in repl:\n                time = time.replace(r, repl[r])\n\n            for r in drepl:\n                date = date.replace(r, drepl[r])\n\n            time = re.sub(\"-.*\", \"\", time)\n            time = time.strip()\n\n            year = dt.datetime.now().year\n\n            date = \"%s %s %s\" % (\n                date,\n                year,\n                time\n            )\n\n            if \"tbd\" in date.lower():\n                continue\n\n            date = date.replace(' PLEASE NOTE NEW TIME', '')\n\n            # Check if the event has been postponed.\n            postponed = 'POSTPONED' in date\n            if postponed:\n                date = date.replace(' POSTPONED', '')\n\n            date_formats = [\"%B %d %Y %I:%M %p\", \"%b. %d %Y %I:%M %p\"]\n            datetime = None\n            for fmt in date_formats:\n                try:\n                    datetime = dt.datetime.strptime(date, fmt)\n                except ValueError:\n                    pass\n\n            # If the datetime can't be parsed, bail.\n            if datetime is None:\n                return\n\n            title_key = set(metainf) & set([\n                'Public Hearing:', 'Summit:', 'Roundtable:',\n                'Public Roundtable:', 'Public Meeting:', 'Public Forum:',\n                'Meeting:'])\n            assert len(title_key) == 1, \"Couldn't determine event title.\"\n            title_key = list(title_key).pop()\n            title = metainf[title_key]\n\n            title = re.sub(\n                    r\"\\*\\*Click here to view public hearing notice\\*\\*\",\n                    \"\",\n                    title\n                    )\n\n            # If event was postponed, add a warning to the title.\n            if postponed:\n                title = 'POSTPONED: %s' % title\n\n            event = Event(session, datetime, 'committee:meeting',\n                          title,\n                          location=metainf['Place:'],\n                          contact=metainf['Contact:'])\n            if 'Media Contact:' in metainf:\n                event.update(media_contact=metainf['Media Contact:'])\n            event.add_source(url)\n\n            for com in coms:\n                event.add_participant('host',\n                                    com.strip(),\n                                    'committee',\n                                    chamber=self.classify_committee(com))\n\n            self.save_event(event)\n\n    def scrape(self, chamber, session):\n        self.scrape_lower(chamber, session)\n        #self.scrape_upper(chamber, session)\n\n    def scrape_lower(self, chamber, session):\n        if chamber == 'other':\n            self.lower_parse_page(url, session)\n\n    def classify_committee(self, name):\n        chamber = 'other'\n        if \"senate\" in name.lower():\n            chamber = 'upper'\n        if \"assembly\" in name.lower():\n            chamber = 'lower'\n        if \"joint\" in name.lower():\n            chamber = 'joint'\n        return chamber\n\n    \"\"\"\n    def scrape_upper(self, chamber, session):\n        if chamber != 'upper':\n            return\n\n        url = (r'http://open.nysenate.gov/legislation/2.0/search.json?'\n               r'term=otype:meeting&pageSize=1000&pageIdx=%d')\n        page_index = 1\n        while True:\n            resp = self.get(url % page_index)\n            if not resp.json():\n                break\n            if not resp.json()['response']['results']:\n                break\n            for obj in resp.json()['response']['results']:\n                event = self.upper_scrape_event(chamber, session, obj)\n                if event:\n                    self.save_event(event)\n            page_index += 1\n\n    def upper_scrape_event(self, chamber, session, obj):\n        meeting = obj['data']['meeting']\n        date = int(meeting['meetingDateTime'])\n        date = dt.datetime.fromtimestamp(date / 1000)\n        if str(date.year) not in session:\n            return\n        description = 'Committee Meeting: ' + meeting['committeeName']\n        event = Event(session, date, 'committee:meeting',\n                      description=description,\n                      location=meeting['location'] or 'No location given.')\n        event.add_source(obj['url'])\n        event.add_participant('chair', meeting['committeeChair'],\n                              'legislator', chamber='upper')\n        event.add_participant('host', meeting['committeeName'],\n                              'committee', chamber='upper')\n\n        rgx = r'([a-z]+)(\\d+)'\n        for bill in meeting['bills']:\n            raw_id = bill['senateBillNo']\n            bill_id = ' '.join(re.search(rgx, raw_id, re.I).groups())\n            event.add_related_bill(\n                bill_id, type='bill',\n                description=bill['summary'] or 'No description given.')\n        return event\n        \"\"\"\n", "path": "openstates/ny/events.py"}]}