Package: legcop
legcopThelegcop(Legislature Common Operating Picture) package provides python libraries to interact with various APIs containing information
about legislative activity in the U.S. Congress and the 54 States & Territories.You can install legcop usingpip install legcopTable of ContentsLEGISCANImportingMethodsLEGISCANThe LegiScan API provides access to the legislative activity of the U.S. State
and Federal Legislatures.Use of the LegiScan API requires an API key which you may obtain for free athttps://legiscan.com/legiscan.To learn more about LegiScan's internal functionality you can always peruse the
user manual/documentation athttps://legiscan.com/gaits/documentation/legiscan.ImportingWe interact with LegiScan usingLegiScanobjects.#importfromlegcopimportLegiScan#instantiate LegiScanapi_key=#YOUR API KEY HERElegis=LegiScan(api_key)TheLegiScanobject provides functions to interact with each of the API
endpoints defined in thehttps://legiscan.comdocumentation. The best way to learn
what the API offers is to simply start exploring. A good place to start is with
the list of all available legislative sessions for a particular state.Let's take a look at what's available for Alaska. Bear in mind that LegiScan
expects postal abbreviations for the state name, and therefore so does this
package.state='ak'ak_sessions=legis.get_session_list(state=state)print(ak_sessions)This prints the following:[{'session_id': 1622, 'state_id': 2, 'year_start': 2019, 'year_end': 2020, 'special': 0, 
    'session_name': '31st Legislature', 'name': '31st Legislature', 
    'session_hash': '38cb885fdbd4f65551b7f55c887da845', 'push_safe': 0}, 
{'session_id': 1397, 'state_id': 2, 'year_start': 2017, 'year_end': 2018, 
    'special': 0, 'session_name': '30th Legislature', 'name': '30th Legislature', 
    'session_hash': '4d7b98daa30b3e4459ae14d6b288a301', 'push_safe': 1}, 
{'session_id': 1117, 'state_id': 2, 'year_start': 2015, 'year_end': 2016, 
    'special': 0, 'session_name': '29th Legislature', 'name': '29th Legislature', 
    'session_hash': '49a2faf62f731cb5d6bd0e67689d2045', 'push_safe': 1}, 
{'session_id': 991, 'state_id': 2, 'year_start': 2013, 'year_end': 2014, 
    'special': 0, 'session_name': '28th Legislature', 'name': '28th Legislature', 
    'session_hash': 'c20fa4dfbc1f76119875f11ec6eed813', 'push_safe': 1}, 
{'session_id': 122, 'state_id': 2, 'year_start': 2011, 'year_end': 2012, 
    'special': 0, 'session_name': '27th Legislature', 'name': '27th Legislature', 
    'session_hash': 'b8b0ebf9519f5ff319453b5ac136bbfa', 'push_safe': 1}, 
{'session_id': 58, 'state_id': 2, 'year_start': 2009, 'year_end': 2010, 
    'special': 0, 'session_name': '26th Legislature', 'name': '26th Legislature', 
    'session_hash': '0a97bd55407d490f885805d7f7eee984', 'push_safe': 1}]As you can see, each session comes with asession_id,year_start, andyear_end. Using this information we can choose a session and pull the list of
associated datasets from the API.For this example we'll simply look at the most recent session, which is at index0in theak_sessionslist.#get start year of most recent Alaska Legislature sessionstart_most_recent_session=ak_sessions[0]['year_start']#get access key for most recent sessiondatasetlist=legis.get_dataset_list(state=state,year=start_most_recent_session)#assign the associated access_key and session_id to variablesaccess_key=datasetlist[0]['access_key']session_id=datasetlist[0]['session_id']Now that we have theaccess_keyandsession_idfor the legislative session
we're interested in we can pull the full dataset from the API.#pull datasetdataset=legis.get_dataset(session_id=session_id,access_key=access_key)#assert that the dataset is good to goassertdataset['status']=='OK'The API returns a zipped, non-human-readable file.LegiScanprovides a
convenient method for translating this into a human-readable zipfile.readable_dataset = legis.recode_zipfile(dataset)You now have azipfile.ZipFileobject. To learn more about the available
methods on this object have a look at the documentation athttps://docs.python.org/3/library/zipfile.html.Here's an example of how to read the contents of one of the zipped files usingzipfile.#get list of all filenames in the datasetnamelist=readable_dataset.namelist()#select oneitem=namelist[0]content=readable_dataset.read(item)#convert this from bytes to python dictimportjsoncontent=content.decode('UTF-8')content=json.loads(content)forkey,valueincontent['bill'].items():print('{}:{}'.format(key,value))This prints out the following for Alaska House Bill 1:bill_id: 1146445
change_hash: 1b8cdc5d7c7e19020f3b215db7f2abed
session_id: 1622
session: {'session_id': 1622, 'session_name': '31st Legislature', 
        'session_title': '31st Legislature', 'year_start': 2019, 
        'year_end': 2020, 'special': 0}
url: https://legiscan.com/AK/bill/HB1/2019
state_link: http://www.akleg.gov/basis/Bill/Detail/31?Root=HB1
completed: 0
status: 1
status_date: 2019-02-20
progress: [{'date': '2019-02-20', 'event': 1}, {'date': '2019-02-20', 'event': 9}]
state: AK
state_id: 2
bill_number: HB1
bill_type: B
bill_type_id: 1
body: H
body_id: 13
current_body: H
current_body_id: 13
title: License In-home Care Providers/agencies
description: An Act relating to the Department of Health and Social Services; 
            relating to in-home personal care services agencies; establishing 
            the In-Home Personal Care Services Advisory Board; and providing 
            for an effective date.
committee: {'committee_id': 2134, 'chamber': 'H', 'chamber_id': 13, 
            'name': 'Health & Social Services'}
pending_committee_id: 2134
history: [{'date': '2019-02-20', 'action': 'PREFILE RELEASED 1/7/19', 
            'chamber': 'H', 'chamber_id': 13, 'importance': 0}, 
        {'date': '2019-02-20', 'action': 'READ THE FIRST TIME - REFERRALS', 
            'chamber': 'H', 'chamber_id': 13, 'importance': 1}, 
        {'date': '2019-02-20', 'action': 'HSS, L&C', 'chamber': 'H', 
            'chamber_id': 13, 'importance': 0}, 
        {'date': '2019-02-20', 'action': 'REFERRED TO HEALTH & SOCIAL SERVICES', 
            'chamber': 'H', 'chamber_id': 13, 'importance': 1}]
sponsors: [{'people_id': 19096, 'person_hash': 'q63acg3w', 'party_id': 2, 
            'party': 'R', 'role_id': 1, 'role': 'Rep', 'name': 'DeLena Johnson', 
            'first_name': 'DeLena', 'middle_name': 'M.', 'last_name': 'Johnson', 
            'suffix': '', 'nickname': '', 'district': 'HD-011', 'ftm_eid': 9405351, 
            'votesmart_id': 153695, 'opensecrets_id': '', 'knowwho_pid': 499617, 
            'ballotpedia': 'Delena_Johnson', 'sponsor_type_id': 1, 
            'sponsor_order': 1, 'committee_sponsor': 0, 'committee_id': '0'}]
sasts: []
subjects: [{'subject_id': 4508, 'subject_name': 'Disabilities'}, 
           {'subject_id': 4478, 'subject_name': 'Licensing'}, 
           {'subject_id': 4545, 'subject_name': 'Medical Care'}, 
           {'subject_id': 4552, 'subject_name': 'Occupations & Professions'}, 
           {'subject_id': 4481, 'subject_name': 'Senior Citizens'}]
texts: [{'doc_id': 1844262, 'date': '2019-01-07', 'type': 'Introduced', 
        'type_id': 1, 'mime': 'application/pdf', 'mime_id': 2, 
        'url': 'https://legiscan.com/AK/text/HB1/id/1844262', 
        'state_link': 'http://www.akleg.gov/PDF/31/Bills/HB0001A.PDF', 
        'text_size': 497807}]
votes: []
amendments: []
supplements: []
calendar: []MethodsIt may be the case that you have a very specific item of interest and don't want
to pull down an entire legislative session's dataset. legiscan.com provides
convenient API calls to meet this need. For each of these,LegiScanprovides
an associated function.get_session_list(state)Get list of all available sessions for a stateget_master_list(state=None, session_id=None)Get list of bills for the current session in a state or for a given session
identifierget_bill(bill_id=None, state=None, bill_number=None)Get primary bill detail information including sponsors, committee references,
full history, bill text, and roll call information.This function expects either a bill identifier or a state and bill number
combination. The bill identifier is preferred, and required for fetching bills
from prior sessions.get_bill_text(bill_id, use_base64=False)Get bill text, including date, draft revision information, and MIME type.Ifuse_base64is False (default) bill text is returned in ASCII for easy
readability.Otherwise, text is base64 encoded to allow for PDF and Word
data transfers.get_amendment(amendment_id)Get amendment text including date, adoption status, MIME type, and
title/description information. Amendment text is encoded in base64 to allow for
PDF and Word data transfers.get_supplement(supplement_id)Get supplement text including type of supplement, date, MIME type and text
description/information. Supplement text is base64 encoded to allow for PDF and
Word data transfer.get_roll_call(roll_call_id)Roll call detail for individual votes and summary information.get_person(people_id)Legislator information including name, role, and a followthemoney.org person
identifier.search(state, bill_number=None, query=None, year=2, page=1)Get a page of results for a search against the LegiScan full text engine;
returns a paginated result set.Specify a bill number or query string. Year can be an exact year or a number
between 1 and 4, inclusive. These integers have the following meanings:
1 = all years
2 = current year, the default
3 = recent years
4 = prior years
Page is the result set page number to returnget_dataset_list(state=None, year=None)Get a list of available datasets with optional filtersget_dataset(session_id = None, access_key=None)Returns a single ZIP archive for the requested dataset containing all bills,
votes, and people for the selected session.To get a list of available datasets useget_dataset_list(). Select anaccess_keyandsession_idfrom the results to use an inputs forget_dataset().get_session_people(session_id)Retrieve a list of people records active in a specific session idget_sponsored_list(people_id)Retrieve a list of bills sponsored by an individual legislatorrecode_zipfile(zipped_dataset)This function re-encodes the zipped dataset produced by the API to make it
human-readable.It then returns a zipfile.Zipfile object. For more information about how to
access/manipulate this object, refer to the zipfile docs:https://docs.python.org/3/library/zipfile.html#zipfile-objects