Repository: openstates/openstates-scrapers

Issue:
AL failing since at least 2019-05-18
AL has been failing since 2019-05-18

Based on automated runs it appears that AL has not run successfully in 2 days (2019-05-18).


```
  05:16:42 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB446
05:16:43 INFO pupa: save bill HB446 in 2019rs as bill_49a912aa-79f5-11e9-ae5f-02da9b55e94c.json
05:16:43 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB447
05:16:44 INFO pupa: save bill HB447 in 2019rs as bill_4a4216da-79f5-11e9-ae5f-02da9b55e94c.json
05:16:44 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB448
05:16:45 INFO pupa: save bill HB448 in 2019rs as bill_4ada53e6-79f5-11e9-ae5f-02da9b55e94c.json
05:16:45 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB449
05:16:46 INFO pupa: save bill HB449 in 2019rs as bill_4b730f82-79f5-11e9-ae5f-02da9b55e94c.json
05:16:46 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB450
05:16:47 INFO pupa: save bill HB450 in 2019rs as bill_4c0c4bc0-79f5-11e9-ae5f-02da9b55e94c.json
05:16:47 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB451
05:16:48 INFO pupa: save bill HB451 in 2019rs as bill_4ca44fce-79f5-11e9-ae5f-02da9b55e94c.json
05:16:48 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB452
05:16:49 INFO pupa: save bill HB452 in 2019rs as bill_4d3ce89c-79f5-11e9-ae5f-02da9b55e94c.json
05:16:49 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB453
05:16:50 INFO pupa: save bill HB453 in 2019rs as bill_4dd60e78-79f5-11e9-ae5f-02da9b55e94c.json
05:16:50 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB454
05:16:51 INFO pupa: save bill HB454 in 2019rs as bill_4e701aa4-79f5-11e9-ae5f-02da9b55e94c.json
05:16:51 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB455
05:16:52 INFO pupa: save bill HB455 in 2019rs as bill_4f07845c-79f5-11e9-ae5f-02da9b55e94c.json
05:16:52 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB456
05:16:53 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/GetRollCallVoteResults.aspx?VOTE=504&BODY=H&INST=HB456&SESS=1071
05:16:54 INFO pupa: save vote_event 2019rs - 2019-05-02 00:00:00-04:00 - Motion to Adopt adopted Roll Call 504 as vote_event_50d49004-79f5-11e9-ae5f-02da9b55e94c.json
05:16:54 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/GetRollCallVoteResults.aspx?VOTE=505&BODY=H&INST=HB456&SESS=1071
05:16:55 INFO pupa: save vote_event 2019rs - 2019-05-02 00:00:00-04:00 - Motion to Read a Third Time and Pass adopted Roll Call 505 as vote_event_516d47b8-79f5-11e9-ae5f-02da9b55e94c.json
05:16:55 INFO pupa: save bill HB456 in 2019rs as bill_4fa16c7a-79f5-11e9-ae5f-02da9b55e94c.json
05:16:55 INFO scrapelib: GET - http://alisondb.legislature.state.al.us/Alison/SESSBillStatusResult.aspx?BILL=HB457
loaded Open States pupa settings...
al (scrape, import)
  bills: {}
Traceback (most recent call last):
  File "/opt/**PGUSER**/venv-pupa//bin/pupa", line 11, in <module>
    load_entry_point('pupa', 'console_scripts', 'pupa')()
  File "/opt/**PGUSER**/venv-pupa/src/pupa/pupa/cli/__main__.py", line 68, in main
    subcommands[args.subcommand].handle(args, other)
  File "/opt/**PGUSER**/venv-pupa/src/pupa/pupa/cli/commands/update.py", line 278, in handle
    return self.do_handle(args, other, juris)
  File "/opt/**PGUSER**/venv-pupa/src/pupa/pupa/cli/commands/update.py", line 327, in do_handle
    report['scrape'] = self.do_scrape(juris, args, scrapers)
  File "/opt/**PGUSER**/venv-pupa/src/pupa/pupa/cli/commands/update.py", line 175, in do_scrape
    report[scraper_name] = scraper.do_scrape(**scrape_args)
  File "/opt/**PGUSER**/venv-pupa/src/pupa/pupa/scrape/base.py", line 112, in do_scrape
    for obj in self.scrape(**kwargs) or []:
  File "/opt/**PGUSER**/**PGUSER**/**PGUSER**/al/bills.py", line 181, in scrape
    yield from self.scrape_bill_list(BILL_LIST_URL)
  File "/opt/**PGUSER**/**PGUSER**/**PGUSER**/al/bills.py", line 384, in scrape_bill_list
    TIMEZONE.localize(action_date),
  File "/opt/**PGUSER**/venv-pupa/lib/python3.6/site-packages/pytz/tzinfo.py", line 317, in localize
    if dt.tzinfo is not None:
AttributeError: 'NoneType' object has no attribute 'tzinfo'
```

Visit http://bobsled.openstates.org for more info.



Discussion:
HB457 posted an action without a date. Fix in testing.

Resolving patch:
diff --git a/openstates/al/bills.py b/openstates/al/bills.py
--- a/openstates/al/bills.py
+++ b/openstates/al/bills.py
@@ -379,31 +379,32 @@ def scrape_bill_list(self, url):
                 except AttributeError:
                     action_committee = ''
 
-                act = bill.add_action(
-                    action_text,
-                    TIMEZONE.localize(action_date),
-                    chamber=actor,
-                    classification=action_type,
-                )
-                if action_committee:
-                    act.add_related_entity(action_committee, entity_type='organization')
-
-                try:
-                    vote_button = action.xpath('td[9]//text()')[0].strip()
-                except IndexError:
-                    vote_button = ''
-
-                if vote_button.startswith("Roll "):
-                    vote_id = vote_button.split(" ")[-1]
-
-                    yield from self.scrape_vote(
-                        bill=bill,
-                        vote_chamber=action_chamber,
-                        bill_id=bill_id,
-                        vote_id=vote_id,
-                        vote_date=TIMEZONE.localize(action_date),
-                        action_text=action_text
+                if action_date is not None:
+                    act = bill.add_action(
+                        action_text,
+                        TIMEZONE.localize(action_date),
+                        chamber=actor,
+                        classification=action_type,
                     )
+                    if action_committee:
+                        act.add_related_entity(action_committee, entity_type='organization')
+
+                    try:
+                        vote_button = action.xpath('td[9]//text()')[0].strip()
+                    except IndexError:
+                        vote_button = ''
+
+                    if vote_button.startswith("Roll "):
+                        vote_id = vote_button.split(" ")[-1]
+
+                        yield from self.scrape_vote(
+                            bill=bill,
+                            vote_chamber=action_chamber,
+                            bill_id=bill_id,
+                            vote_id=vote_id,
+                            vote_date=TIMEZONE.localize(action_date),
+                            action_text=action_text
+                        )
 
                 if amendment:
                     amend_url = (


Test patch: