uk_bin_collection 0.110.0__py3-none-any.whl → 0.111.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uk_bin_collection/tests/input.json +23 -1
 - uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py +1 -1
 - uk_bin_collection/uk_bin_collection/councils/LondonBoroughSutton.py +75 -0
 - uk_bin_collection/uk_bin_collection/councils/MidDevonCouncil.py +93 -0
 - uk_bin_collection/uk_bin_collection/councils/OxfordCityCouncil.py +63 -0
 - {uk_bin_collection-0.110.0.dist-info → uk_bin_collection-0.111.0.dist-info}/METADATA +1 -1
 - {uk_bin_collection-0.110.0.dist-info → uk_bin_collection-0.111.0.dist-info}/RECORD +10 -7
 - {uk_bin_collection-0.110.0.dist-info → uk_bin_collection-0.111.0.dist-info}/LICENSE +0 -0
 - {uk_bin_collection-0.110.0.dist-info → uk_bin_collection-0.111.0.dist-info}/WHEEL +0 -0
 - {uk_bin_collection-0.110.0.dist-info → uk_bin_collection-0.111.0.dist-info}/entry_points.txt +0 -0
 
| 
         @@ -745,7 +745,7 @@ 
     | 
|
| 
       745 
745 
     | 
    
         
             
                    "wiki_command_url_override": "https://lincoln.gov.uk",
         
     | 
| 
       746 
746 
     | 
    
         
             
                    "uprn": "000235024846",
         
     | 
| 
       747 
747 
     | 
    
         
             
                    "postcode": "LN5 7SH",
         
     | 
| 
       748 
     | 
    
         
            -
                    "wiki_name": " 
     | 
| 
      
 748 
     | 
    
         
            +
                    "wiki_name": "Lincoln Council",
         
     | 
| 
       749 
749 
     | 
    
         
             
                    "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
         
     | 
| 
       750 
750 
     | 
    
         
             
                },
         
     | 
| 
       751 
751 
     | 
    
         
             
                "LisburnCastlereaghCityCouncil": {
         
     | 
| 
         @@ -794,6 +794,13 @@ 
     | 
|
| 
       794 
794 
     | 
    
         
             
                    "wiki_name": "London Borough Redbridge",
         
     | 
| 
       795 
795 
     | 
    
         
             
                    "wiki_note": "Follow the instructions [here](https://my.redbridge.gov.uk/RecycleRefuse) until you get the page listing your \"Address\" then copy the entire address text and use that in the house number field."
         
     | 
| 
       796 
796 
     | 
    
         
             
                },
         
     | 
| 
      
 797 
     | 
    
         
            +
                "LondonBoroughSutton": {
         
     | 
| 
      
 798 
     | 
    
         
            +
                    "url": "https://waste-services.sutton.gov.uk/waste",
         
     | 
| 
      
 799 
     | 
    
         
            +
                    "wiki_command_url_override": "https://waste-services.sutton.gov.uk/waste",
         
     | 
| 
      
 800 
     | 
    
         
            +
                    "uprn": "4473006",
         
     | 
| 
      
 801 
     | 
    
         
            +
                    "wiki_name": "London Borough Sutton",
         
     | 
| 
      
 802 
     | 
    
         
            +
                    "wiki_note": "You will need to find your unique property reference by going to (https://waste-services.sutton.gov.uk/waste), entering your details and then using the 7 digit reference in the URL as your UPRN"
         
     | 
| 
      
 803 
     | 
    
         
            +
                },
         
     | 
| 
       797 
804 
     | 
    
         
             
                "LutonBoroughCouncil": {
         
     | 
| 
       798 
805 
     | 
    
         
             
                    "url": "https://myforms.luton.gov.uk",
         
     | 
| 
       799 
806 
     | 
    
         
             
                    "wiki_command_url_override": "https://myforms.luton.gov.uk",
         
     | 
| 
         @@ -839,6 +846,13 @@ 
     | 
|
| 
       839 
846 
     | 
    
         
             
                    "wiki_name": "Mid and East Antrim Borough Council",
         
     | 
| 
       840 
847 
     | 
    
         
             
                    "wiki_note": "Pass the house name/number plus the name of the street with the postcode parameter, wrapped in double quotes.  Check the address in the web site first. This version will only pick the first SHOW button returned by the search or if it is fully unique.  The search is not very predictable (e.g. house number 4 returns 14,24,4,44 etc.)."
         
     | 
| 
       841 
848 
     | 
    
         
             
                },
         
     | 
| 
      
 849 
     | 
    
         
            +
                "MidDevonCouncil": {
         
     | 
| 
      
 850 
     | 
    
         
            +
                    "url": "https://www.middevon.gov.uk",
         
     | 
| 
      
 851 
     | 
    
         
            +
                    "wiki_command_url_override": "https://www.middevon.gov.uk",
         
     | 
| 
      
 852 
     | 
    
         
            +
                    "uprn": "200003997770",
         
     | 
| 
      
 853 
     | 
    
         
            +
                    "wiki_name": "Mid Devon Council",
         
     | 
| 
      
 854 
     | 
    
         
            +
                    "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
         
     | 
| 
      
 855 
     | 
    
         
            +
                },
         
     | 
| 
       842 
856 
     | 
    
         
             
                "MidlothianCouncil": {
         
     | 
| 
       843 
857 
     | 
    
         
             
                    "house_number": "52",
         
     | 
| 
       844 
858 
     | 
    
         
             
                    "postcode": "EH19 2EB",
         
     | 
| 
         @@ -1021,6 +1035,14 @@ 
     | 
|
| 
       1021 
1035 
     | 
    
         
             
                    "wiki_name": "Oldham Council",
         
     | 
| 
       1022 
1036 
     | 
    
         
             
                    "wiki_note": "Replace UPRN in URL with your own UPRN."
         
     | 
| 
       1023 
1037 
     | 
    
         
             
                },
         
     | 
| 
      
 1038 
     | 
    
         
            +
                "OxfordCityCouncil": {
         
     | 
| 
      
 1039 
     | 
    
         
            +
                    "url": "https://www.oxford.gov.uk",
         
     | 
| 
      
 1040 
     | 
    
         
            +
                    "wiki_command_url_override": "https://www.oxford.gov.uk",
         
     | 
| 
      
 1041 
     | 
    
         
            +
                    "uprn": "100120820551",
         
     | 
| 
      
 1042 
     | 
    
         
            +
                    "postcode": "OX3 7QF",
         
     | 
| 
      
 1043 
     | 
    
         
            +
                    "wiki_name": "Oxford City Council",
         
     | 
| 
      
 1044 
     | 
    
         
            +
                    "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
         
     | 
| 
      
 1045 
     | 
    
         
            +
                },
         
     | 
| 
       1024 
1046 
     | 
    
         
             
                "PerthAndKinrossCouncil": {
         
     | 
| 
       1025 
1047 
     | 
    
         
             
                    "url": "https://www.pkc.gov.uk",
         
     | 
| 
       1026 
1048 
     | 
    
         
             
                    "wiki_command_url_override": "https://www.pkc.gov.uk",
         
     | 
| 
         @@ -0,0 +1,75 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            from time import sleep
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            import requests
         
     | 
| 
      
 4 
     | 
    
         
            +
            from bs4 import BeautifulSoup
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            from uk_bin_collection.uk_bin_collection.common import *
         
     | 
| 
      
 7 
     | 
    
         
            +
            from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            # import the wonderful Beautiful Soup and the URL grabber
         
     | 
| 
      
 11 
     | 
    
         
            +
            class CouncilClass(AbstractGetBinDataClass):
         
     | 
| 
      
 12 
     | 
    
         
            +
                """
         
     | 
| 
      
 13 
     | 
    
         
            +
                Concrete classes have to implement all abstract operations of the
         
     | 
| 
      
 14 
     | 
    
         
            +
                base class. They can also override some operations with a default
         
     | 
| 
      
 15 
     | 
    
         
            +
                implementation.
         
     | 
| 
      
 16 
     | 
    
         
            +
                """
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def parse_data(self, page: str, **kwargs) -> dict:
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    user_uprn = kwargs.get("uprn")
         
     | 
| 
      
 21 
     | 
    
         
            +
                    # check_uprn(user_uprn)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    bindata = {"bins": []}
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    URI = f"https://waste-services.sutton.gov.uk/waste/{user_uprn}"
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    s = requests.Session()
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    r = s.get(URI)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    while "Loading your bin days..." in r.text:
         
     | 
| 
      
 30 
     | 
    
         
            +
                        sleep(2)
         
     | 
| 
      
 31 
     | 
    
         
            +
                        r = s.get(URI)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    r.raise_for_status()
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    soup = BeautifulSoup(r.content, "html.parser")
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    current_year = datetime.now().year
         
     | 
| 
      
 37 
     | 
    
         
            +
                    next_year = current_year + 1
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    services = soup.find_all("h3", class_="govuk-heading-m waste-service-name")
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    for service in services:
         
     | 
| 
      
 42 
     | 
    
         
            +
                        bin_type = service.get_text(
         
     | 
| 
      
 43 
     | 
    
         
            +
                            strip=True
         
     | 
| 
      
 44 
     | 
    
         
            +
                        )  # Bin type name (e.g., 'Food waste', 'Mixed recycling')
         
     | 
| 
      
 45 
     | 
    
         
            +
                        if bin_type == "Bulky waste":
         
     | 
| 
      
 46 
     | 
    
         
            +
                            continue
         
     | 
| 
      
 47 
     | 
    
         
            +
                        service_details = service.find_next("div", class_="govuk-grid-row")
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                        next_collection = (
         
     | 
| 
      
 50 
     | 
    
         
            +
                            service_details.find("dt", string="Next collection")
         
     | 
| 
      
 51 
     | 
    
         
            +
                            .find_next_sibling("dd")
         
     | 
| 
      
 52 
     | 
    
         
            +
                            .get_text(strip=True)
         
     | 
| 
      
 53 
     | 
    
         
            +
                        )
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                        next_collection = datetime.strptime(
         
     | 
| 
      
 56 
     | 
    
         
            +
                            remove_ordinal_indicator_from_date_string(next_collection),
         
     | 
| 
      
 57 
     | 
    
         
            +
                            "%A, %d %B",
         
     | 
| 
      
 58 
     | 
    
         
            +
                        )
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                        if next_collection.month == 1:
         
     | 
| 
      
 61 
     | 
    
         
            +
                            next_collection = next_collection.replace(year=next_year)
         
     | 
| 
      
 62 
     | 
    
         
            +
                        else:
         
     | 
| 
      
 63 
     | 
    
         
            +
                            next_collection = next_collection.replace(year=current_year)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                        dict_data = {
         
     | 
| 
      
 66 
     | 
    
         
            +
                            "type": bin_type,
         
     | 
| 
      
 67 
     | 
    
         
            +
                            "collectionDate": next_collection.strftime("%d/%m/%Y"),
         
     | 
| 
      
 68 
     | 
    
         
            +
                        }
         
     | 
| 
      
 69 
     | 
    
         
            +
                        bindata["bins"].append(dict_data)
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    bindata["bins"].sort(
         
     | 
| 
      
 72 
     | 
    
         
            +
                        key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
         
     | 
| 
      
 73 
     | 
    
         
            +
                    )
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                    return bindata
         
     | 
| 
         @@ -0,0 +1,93 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import time
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            import requests
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            from uk_bin_collection.uk_bin_collection.common import *
         
     | 
| 
      
 6 
     | 
    
         
            +
            from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # import the wonderful Beautiful Soup and the URL grabber
         
     | 
| 
      
 10 
     | 
    
         
            +
            class CouncilClass(AbstractGetBinDataClass):
         
     | 
| 
      
 11 
     | 
    
         
            +
                """
         
     | 
| 
      
 12 
     | 
    
         
            +
                Concrete classes have to implement all abstract operations of the
         
     | 
| 
      
 13 
     | 
    
         
            +
                base class. They can also override some operations with a default
         
     | 
| 
      
 14 
     | 
    
         
            +
                implementation.
         
     | 
| 
      
 15 
     | 
    
         
            +
                """
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def parse_data(self, page: str, **kwargs) -> dict:
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    user_uprn = kwargs.get("uprn")
         
     | 
| 
      
 20 
     | 
    
         
            +
                    check_uprn(user_uprn)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    bindata = {"bins": []}
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    SESSION_URL = "https://my.middevon.gov.uk/authapi/isauthenticated?uri=https%253A%252F%252Fmy.middevon.gov.uk%252Fen%252FAchieveForms%252F%253Fform_uri%253Dsandbox-publish%253A%252F%252FAF-Process-2289dd06-9a12-4202-ba09-857fe756f6bd%252FAF-Stage-eb382015-001c-415d-beda-84f796dbb167%252Fdefinition.json%2526redirectlink%253D%25252Fen%2526cancelRedirectLink%253D%25252Fen%2526consentMessage%253Dyes&hostname=my.middevon.gov.uk&withCredentials=true"
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    API_URL = "https://my.middevon.gov.uk/apibroker/runLookup"
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    payload = {
         
     | 
| 
      
 28 
     | 
    
         
            +
                        "formValues": {
         
     | 
| 
      
 29 
     | 
    
         
            +
                            "Your Address": {
         
     | 
| 
      
 30 
     | 
    
         
            +
                                "listAddress": {"value": user_uprn},
         
     | 
| 
      
 31 
     | 
    
         
            +
                            },
         
     | 
| 
      
 32 
     | 
    
         
            +
                        },
         
     | 
| 
      
 33 
     | 
    
         
            +
                    }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    headers = {
         
     | 
| 
      
 36 
     | 
    
         
            +
                        "Content-Type": "application/json",
         
     | 
| 
      
 37 
     | 
    
         
            +
                        "Accept": "application/json",
         
     | 
| 
      
 38 
     | 
    
         
            +
                        "User-Agent": "Mozilla/5.0",
         
     | 
| 
      
 39 
     | 
    
         
            +
                        "X-Requested-With": "XMLHttpRequest",
         
     | 
| 
      
 40 
     | 
    
         
            +
                        "Referer": "https://my.middevon.gov.uk/fillform/?iframe_id=fillform-frame-1&db_id=",
         
     | 
| 
      
 41 
     | 
    
         
            +
                    }
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    ids = [
         
     | 
| 
      
 44 
     | 
    
         
            +
                        "6423144f50ec0",
         
     | 
| 
      
 45 
     | 
    
         
            +
                        "641c7ae9b4c96",
         
     | 
| 
      
 46 
     | 
    
         
            +
                        "645e13a01dba1",
         
     | 
| 
      
 47 
     | 
    
         
            +
                        "642315aacb919",
         
     | 
| 
      
 48 
     | 
    
         
            +
                        "64231699483cf",
         
     | 
| 
      
 49 
     | 
    
         
            +
                        "642421bab7478",
         
     | 
| 
      
 50 
     | 
    
         
            +
                        "6424229605d13",
         
     | 
| 
      
 51 
     | 
    
         
            +
                        "645e14020c9cc",
         
     | 
| 
      
 52 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    rows_data = []
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    for id in ids:
         
     | 
| 
      
 57 
     | 
    
         
            +
                        s = requests.session()
         
     | 
| 
      
 58 
     | 
    
         
            +
                        r = s.get(SESSION_URL)
         
     | 
| 
      
 59 
     | 
    
         
            +
                        r.raise_for_status()
         
     | 
| 
      
 60 
     | 
    
         
            +
                        session_data = r.json()
         
     | 
| 
      
 61 
     | 
    
         
            +
                        sid = session_data["auth-session"]
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                        params = {
         
     | 
| 
      
 64 
     | 
    
         
            +
                            "id": id,
         
     | 
| 
      
 65 
     | 
    
         
            +
                            "repeat_against": "",
         
     | 
| 
      
 66 
     | 
    
         
            +
                            "noRetry": "false",
         
     | 
| 
      
 67 
     | 
    
         
            +
                            "getOnlyTokens": "undefined",
         
     | 
| 
      
 68 
     | 
    
         
            +
                            "log_id": "",
         
     | 
| 
      
 69 
     | 
    
         
            +
                            "app_name": "AF-Renderer::Self",
         
     | 
| 
      
 70 
     | 
    
         
            +
                            # unix_timestamp
         
     | 
| 
      
 71 
     | 
    
         
            +
                            "_": str(int(time.time() * 1000)),
         
     | 
| 
      
 72 
     | 
    
         
            +
                            "sid": sid,
         
     | 
| 
      
 73 
     | 
    
         
            +
                        }
         
     | 
| 
      
 74 
     | 
    
         
            +
                        r = s.post(API_URL, json=payload, headers=headers, params=params)
         
     | 
| 
      
 75 
     | 
    
         
            +
                        r.raise_for_status()
         
     | 
| 
      
 76 
     | 
    
         
            +
                        data = r.json()
         
     | 
| 
      
 77 
     | 
    
         
            +
                        rows_data = data["integration"]["transformed"]["rows_data"]
         
     | 
| 
      
 78 
     | 
    
         
            +
                        if isinstance(rows_data, dict):
         
     | 
| 
      
 79 
     | 
    
         
            +
                            date = datetime.strptime(rows_data["0"]["display"], "%d-%b-%y")
         
     | 
| 
      
 80 
     | 
    
         
            +
                            bin_types = (rows_data["0"]["CollectionItems"]).split(" and ")
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                            for bin_type in bin_types:
         
     | 
| 
      
 83 
     | 
    
         
            +
                                dict_data = {
         
     | 
| 
      
 84 
     | 
    
         
            +
                                    "type": bin_type,
         
     | 
| 
      
 85 
     | 
    
         
            +
                                    "collectionDate": date.strftime(date_format),
         
     | 
| 
      
 86 
     | 
    
         
            +
                                }
         
     | 
| 
      
 87 
     | 
    
         
            +
                                bindata["bins"].append(dict_data)
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    bindata["bins"].sort(
         
     | 
| 
      
 90 
     | 
    
         
            +
                        key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
         
     | 
| 
      
 91 
     | 
    
         
            +
                    )
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                    return bindata
         
     | 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import requests
         
     | 
| 
      
 2 
     | 
    
         
            +
            from bs4 import BeautifulSoup
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            from uk_bin_collection.uk_bin_collection.common import *
         
     | 
| 
      
 5 
     | 
    
         
            +
            from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            # import the wonderful Beautiful Soup and the URL grabber
         
     | 
| 
      
 9 
     | 
    
         
            +
            class CouncilClass(AbstractGetBinDataClass):
         
     | 
| 
      
 10 
     | 
    
         
            +
                """
         
     | 
| 
      
 11 
     | 
    
         
            +
                Concrete classes have to implement all abstract operations of the
         
     | 
| 
      
 12 
     | 
    
         
            +
                base class. They can also override some operations with a default
         
     | 
| 
      
 13 
     | 
    
         
            +
                implementation.
         
     | 
| 
      
 14 
     | 
    
         
            +
                """
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def parse_data(self, page: str, **kwargs) -> dict:
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    user_uprn = kwargs.get("uprn")
         
     | 
| 
      
 19 
     | 
    
         
            +
                    user_postcode = kwargs.get("postcode")
         
     | 
| 
      
 20 
     | 
    
         
            +
                    check_uprn(user_uprn)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    check_postcode(user_postcode)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    bindata = {"bins": []}
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    session_uri = "https://www.oxford.gov.uk/mybinday"
         
     | 
| 
      
 25 
     | 
    
         
            +
                    URI = "https://www.oxford.gov.uk/xfp/form/142"
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    session = requests.Session()
         
     | 
| 
      
 28 
     | 
    
         
            +
                    token_response = session.get(session_uri)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    soup = BeautifulSoup(token_response.text, "html.parser")
         
     | 
| 
      
 30 
     | 
    
         
            +
                    token = soup.find("input", {"name": "__token"}).attrs["value"]
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    form_data = {
         
     | 
| 
      
 33 
     | 
    
         
            +
                        "__token": token,
         
     | 
| 
      
 34 
     | 
    
         
            +
                        "page": "12",
         
     | 
| 
      
 35 
     | 
    
         
            +
                        "locale": "en_GB",
         
     | 
| 
      
 36 
     | 
    
         
            +
                        "q6ad4e3bf432c83230a0347a6eea6c805c672efeb_0_0": user_postcode,
         
     | 
| 
      
 37 
     | 
    
         
            +
                        "q6ad4e3bf432c83230a0347a6eea6c805c672efeb_1_0": user_uprn,
         
     | 
| 
      
 38 
     | 
    
         
            +
                        "next": "Next",
         
     | 
| 
      
 39 
     | 
    
         
            +
                    }
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    collection_response = session.post(URI, data=form_data)
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    collection_soup = BeautifulSoup(collection_response.text, "html.parser")
         
     | 
| 
      
 44 
     | 
    
         
            +
                    for paragraph in collection_soup.find("div", class_="editor").find_all("p"):
         
     | 
| 
      
 45 
     | 
    
         
            +
                        matches = re.match(r"^(\w+) Next Collection: (.*)", paragraph.text)
         
     | 
| 
      
 46 
     | 
    
         
            +
                        if matches:
         
     | 
| 
      
 47 
     | 
    
         
            +
                            collection_type, date_string = matches.groups()
         
     | 
| 
      
 48 
     | 
    
         
            +
                            try:
         
     | 
| 
      
 49 
     | 
    
         
            +
                                date = datetime.strptime(date_string, "%A %d %B %Y").date()
         
     | 
| 
      
 50 
     | 
    
         
            +
                            except ValueError:
         
     | 
| 
      
 51 
     | 
    
         
            +
                                date = datetime.strptime(date_string, "%A %d %b %Y").date()
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                            dict_data = {
         
     | 
| 
      
 54 
     | 
    
         
            +
                                "type": collection_type,
         
     | 
| 
      
 55 
     | 
    
         
            +
                                "collectionDate": date.strftime("%d/%m/%Y"),
         
     | 
| 
      
 56 
     | 
    
         
            +
                            }
         
     | 
| 
      
 57 
     | 
    
         
            +
                            bindata["bins"].append(dict_data)
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                    bindata["bins"].sort(
         
     | 
| 
      
 60 
     | 
    
         
            +
                        key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
         
     | 
| 
      
 61 
     | 
    
         
            +
                    )
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    return bindata
         
     | 
| 
         @@ -2,7 +2,7 @@ uk_bin_collection/README.rst,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU, 
     | 
|
| 
       2 
2 
     | 
    
         
             
            uk_bin_collection/tests/council_feature_input_parity.py,sha256=DO6Mk4ImYgM5ZCZ-cutwz5RoYYWZRLYx2tr6zIs_9Rc,3843
         
     | 
| 
       3 
3 
     | 
    
         
             
            uk_bin_collection/tests/features/environment.py,sha256=VQZjJdJI_kZn08M0j5cUgvKT4k3iTw8icJge1DGOkoA,127
         
     | 
| 
       4 
4 
     | 
    
         
             
            uk_bin_collection/tests/features/validate_council_outputs.feature,sha256=SJK-Vc737hrf03tssxxbeg_JIvAH-ddB8f6gU1LTbuQ,251
         
     | 
| 
       5 
     | 
    
         
            -
            uk_bin_collection/tests/input.json,sha256= 
     | 
| 
      
 5 
     | 
    
         
            +
            uk_bin_collection/tests/input.json,sha256=MN87Jdtb1koa8moUh7SW2eJi800CEp-JiwT8G2wV6A8,81028
         
     | 
| 
       6 
6 
     | 
    
         
             
            uk_bin_collection/tests/output.schema,sha256=ZwKQBwYyTDEM4G2hJwfLUVM-5v1vKRvRK9W9SS1sd18,1086
         
     | 
| 
       7 
7 
     | 
    
         
             
            uk_bin_collection/tests/step_defs/step_helpers/file_handler.py,sha256=Ygzi4V0S1MIHqbdstUlIqtRIwnynvhu4UtpweJ6-5N8,1474
         
     | 
| 
       8 
8 
     | 
    
         
             
            uk_bin_collection/tests/step_defs/test_validate_council.py,sha256=VZ0a81sioJULD7syAYHjvK_-nT_Rd36tUyzPetSA0gk,3475
         
     | 
| 
         @@ -94,7 +94,7 @@ uk_bin_collection/uk_bin_collection/councils/FlintshireCountyCouncil.py,sha256=R 
     | 
|
| 
       94 
94 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/ForestOfDeanDistrictCouncil.py,sha256=YWT2GM2-bQ3Zh9ps1K14XRZfanuJOlV-zHpOOYMXAXY,4893
         
     | 
| 
       95 
95 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/GatesheadCouncil.py,sha256=SRCgYhYs6rv_8C1UEDVORHZgXxcJkoZBjzdYS4Lu-ew,4531
         
     | 
| 
       96 
96 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/GedlingBoroughCouncil.py,sha256=XzfFMCwclh9zAJgsbaj4jywjdiH0wPaFicaVsLrN3ms,2297
         
     | 
| 
       97 
     | 
    
         
            -
            uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py,sha256= 
     | 
| 
      
 97 
     | 
    
         
            +
            uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py,sha256=9N5GXR32gXYBl3i44TITiZ7N73rgqXZmkyenI-kVRQI,2328
         
     | 
| 
       98 
98 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/GloucesterCityCouncil.py,sha256=8Wjvmdvg5blHVrREaEnhhWZaWhYVP4v_KdDVPLIUxaU,4889
         
     | 
| 
       99 
99 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/GuildfordCouncil.py,sha256=9pVrmQhZcK2AD8gX8mNvP--L4L9KaY6L3B822VX6fec,5695
         
     | 
| 
       100 
100 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/HaltonBoroughCouncil.py,sha256=gq_CPqi6qM2oNiHhKKF1lZC86fyKL4lPhh_DN9pJZ04,5971
         
     | 
| 
         @@ -121,6 +121,7 @@ uk_bin_collection/uk_bin_collection/councils/LondonBoroughHarrow.py,sha256=kzKwb 
     | 
|
| 
       121 
121 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/LondonBoroughHounslow.py,sha256=UOeiOxGMvVMm2UFaqjmQpm7vxzqJNSSN8LM9lAUjs2c,3021
         
     | 
| 
       122 
122 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/LondonBoroughLambeth.py,sha256=r9D5lHe5kIRStCd5lRIax16yhb4KTFzzfYEFv1bacWw,2009
         
     | 
| 
       123 
123 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/LondonBoroughRedbridge.py,sha256=A_6Sis5hsF53Th04KeadHRasGbpAm6aoaWJ6X8eC4Y8,6604
         
     | 
| 
      
 124 
     | 
    
         
            +
            uk_bin_collection/uk_bin_collection/councils/LondonBoroughSutton.py,sha256=c2haHOwX7Dy1phVUTv3xaQgM9VeHmFuBwdAgqGcGs8Y,2369
         
     | 
| 
       124 
125 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/LutonBoroughCouncil.py,sha256=vScUi_R8FnBddii2_zLlZBLxuh85mKmCm8nKW3zxky0,2758
         
     | 
| 
       125 
126 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/MaldonDistrictCouncil.py,sha256=PMVt2XFggttPmbWyrBrHJ-W6R_6-0ux1BkY1kj1IKzg,1997
         
     | 
| 
       126 
127 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/MalvernHillsDC.py,sha256=iQG0EkX2npBicvsGKQRYyBGSBvKVUbKvUvvwrC9xV1A,2100
         
     | 
| 
         @@ -128,6 +129,7 @@ uk_bin_collection/uk_bin_collection/councils/ManchesterCityCouncil.py,sha256=RY3 
     | 
|
| 
       128 
129 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/MansfieldDistrictCouncil.py,sha256=F5AiTxImrnjE1k3ry96bfstOf5XSNBJS_4qqmymmh3w,1386
         
     | 
| 
       129 
130 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/MertonCouncil.py,sha256=3Y2Un4xXo1sCcMsudynODSzocV_mMofWkX2JqONDb5o,1997
         
     | 
| 
       130 
131 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/MidAndEastAntrimBoroughCouncil.py,sha256=oOWwU5FSgGej2Mv7FQ66N-EzS5nZgmGsd0WnfLWUc1I,5238
         
     | 
| 
      
 132 
     | 
    
         
            +
            uk_bin_collection/uk_bin_collection/councils/MidDevonCouncil.py,sha256=RjBZ7R3_Pax9p1d2DCygqryjV1RP4BYvqb-rT_KyOEg,3322
         
     | 
| 
       131 
133 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/MidSussexDistrictCouncil.py,sha256=AZgC9wmDLEjUOtIFvf0ehF5LHturXTH4DkE3ioPSVBA,6254
         
     | 
| 
       132 
134 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/MidlothianCouncil.py,sha256=mM5-itJDNhjsT5UEjSFfWppmfmPFSns4u_1QblewuFU,5605
         
     | 
| 
       133 
135 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/MiltonKeynesCityCouncil.py,sha256=3olsWa77L34vz-c7NgeGK9xmNuR4Ws_oAk5D4UpIkPw,2005
         
     | 
| 
         @@ -154,6 +156,7 @@ uk_bin_collection/uk_bin_collection/councils/NorthumberlandCouncil.py,sha256=KEF 
     | 
|
| 
       154 
156 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/NorwichCityCouncil.py,sha256=At-9dEcKBUZSrtJ2RncwvMnV0OVU3pE6kxEYbLL-Av8,2437
         
     | 
| 
       155 
157 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/NottinghamCityCouncil.py,sha256=panTCjnsBOQ98-TBO9xVZk_jcT_gjMhx3Gg5oWxBRLo,1254
         
     | 
| 
       156 
158 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/OldhamCouncil.py,sha256=9dlesCxNoVXlmQaqZj7QFh00smnJbm1Gnjkr_Uvzurs,1771
         
     | 
| 
      
 159 
     | 
    
         
            +
            uk_bin_collection/uk_bin_collection/councils/OxfordCityCouncil.py,sha256=d_bY0cXRDH4kSoWGGCTNN61MNErapSOf2WSTYDJr2r8,2318
         
     | 
| 
       157 
160 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/PerthAndKinrossCouncil.py,sha256=Kos5GzN2co3Ij3tSHOXB9S71Yt78RROCfVRtnh7M1VU,3657
         
     | 
| 
       158 
161 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/PlymouthCouncil.py,sha256=FJqpJ0GJhpjYeyZ9ioZPkKGl-zrqMD3y5iKa07e_i30,3202
         
     | 
| 
       159 
162 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/PortsmouthCityCouncil.py,sha256=xogNgVvwM5FljCziiNLgZ_wzkOnrQkifi1dkPMDRMtg,5588
         
     | 
| 
         @@ -243,8 +246,8 @@ uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bId 
     | 
|
| 
       243 
246 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=EQWRhZ2pEejlvm0fPyOTsOHKvUZmPnxEYO_OWRGKTjs,1158
         
     | 
| 
       244 
247 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
         
     | 
| 
       245 
248 
     | 
    
         
             
            uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=YvmHfZqanwrJ8ToGch34x-L-7yPe31nB_x77_Mgl_vo,4545
         
     | 
| 
       246 
     | 
    
         
            -
            uk_bin_collection-0. 
     | 
| 
       247 
     | 
    
         
            -
            uk_bin_collection-0. 
     | 
| 
       248 
     | 
    
         
            -
            uk_bin_collection-0. 
     | 
| 
       249 
     | 
    
         
            -
            uk_bin_collection-0. 
     | 
| 
       250 
     | 
    
         
            -
            uk_bin_collection-0. 
     | 
| 
      
 249 
     | 
    
         
            +
            uk_bin_collection-0.111.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
         
     | 
| 
      
 250 
     | 
    
         
            +
            uk_bin_collection-0.111.0.dist-info/METADATA,sha256=post7eciEA6fFebAgkqrkux5HHCUNhh-R4t8n0Z3IpU,17574
         
     | 
| 
      
 251 
     | 
    
         
            +
            uk_bin_collection-0.111.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
         
     | 
| 
      
 252 
     | 
    
         
            +
            uk_bin_collection-0.111.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
         
     | 
| 
      
 253 
     | 
    
         
            +
            uk_bin_collection-0.111.0.dist-info/RECORD,,
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
    
        {uk_bin_collection-0.110.0.dist-info → uk_bin_collection-0.111.0.dist-info}/entry_points.txt
    RENAMED
    
    | 
         
            File without changes
         
     |