uk_bin_collection 0.109.2__py3-none-any.whl → 0.111.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -126,6 +126,13 @@
126
126
  "url": "https://www.birmingham.gov.uk/xfp/form/619",
127
127
  "wiki_name": "Birmingham City Council"
128
128
  },
129
+ "BlabyDistrictCouncil": {
130
+ "url": "https://www.blaby.gov.uk",
131
+ "wiki_command_url_override": "https://www.blaby.gov.uk",
132
+ "uprn": "100030401782",
133
+ "wiki_name": "Blaby District Council",
134
+ "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
135
+ },
129
136
  "BlackburnCouncil": {
130
137
  "skip_get_url": true,
131
138
  "uprn": "100010733027",
@@ -189,6 +196,13 @@
189
196
  "wiki_name": "Bromley Borough Council",
190
197
  "wiki_note": "Follow the instructions [here](https://recyclingservices.bromley.gov.uk/waste) until the \"Your bin days\" page then copy the URL and replace the URL in the command."
191
198
  },
199
+ "BromsgroveDistrictCouncil": {
200
+ "url": "https://www.bromsgrove.gov.uk",
201
+ "wiki_command_url_override": "https://www.bromsgrove.gov.uk",
202
+ "uprn": "100120584652",
203
+ "wiki_name": "Bromsgrove District Council",
204
+ "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
205
+ },
192
206
  "BroxtoweBoroughCouncil": {
193
207
  "postcode": "NG16 2LY",
194
208
  "skip_get_url": true,
@@ -243,6 +257,13 @@
243
257
  "url": "https://www.cardiff.gov.uk/ENG/resident/Rubbish-and-recycling/When-are-my-bins-collected/Pages/default.aspx",
244
258
  "wiki_name": "Cardiff Council"
245
259
  },
260
+ "CarmarthenshireCountyCouncil": {
261
+ "url": "https://www.carmarthenshire.gov.wales",
262
+ "wiki_command_url_override": "https://www.carmarthenshire.gov.wales",
263
+ "uprn": "10004859302",
264
+ "wiki_name": "Carmarthenshire County Council",
265
+ "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
266
+ },
246
267
  "CastlepointDistrictCouncil": {
247
268
  "skip_get_url": true,
248
269
  "uprn": "4525",
@@ -416,6 +437,13 @@
416
437
  "url": "https://www.ealing.gov.uk/site/custom_scripts/WasteCollectionWS/home/FindCollection",
417
438
  "wiki_name": "Ealing Council"
418
439
  },
440
+ "EastAyrshireCouncil": {
441
+ "url": "https://www.east-ayrshire.gov.uk",
442
+ "wiki_command_url_override": "https://www.east-ayrshire.gov.uk",
443
+ "uprn": "127074727",
444
+ "wiki_name": "East Ayrshire Council",
445
+ "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
446
+ },
419
447
  "EastCambridgeshireCouncil": {
420
448
  "skip_get_url": true,
421
449
  "uprn": "10002597178",
@@ -436,8 +464,8 @@
436
464
  "wiki_name": "East Herts Council"
437
465
  },
438
466
  "EastLindseyDistrictCouncil": {
439
- "house_number": "Raf Coningsby",
440
- "postcode": "LN4 4SY",
467
+ "house_number": "1",
468
+ "postcode": "PE22 0YD",
441
469
  "skip_get_url": true,
442
470
  "url": "https://www.e-lindsey.gov.uk/",
443
471
  "web_driver": "http://selenium:4444",
@@ -717,7 +745,7 @@
717
745
  "wiki_command_url_override": "https://lincoln.gov.uk",
718
746
  "uprn": "000235024846",
719
747
  "postcode": "LN5 7SH",
720
- "wiki_name": "Tunbridge Wells Council",
748
+ "wiki_name": "Lincoln Council",
721
749
  "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
722
750
  },
723
751
  "LisburnCastlereaghCityCouncil": {
@@ -766,6 +794,13 @@
766
794
  "wiki_name": "London Borough Redbridge",
767
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."
768
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
+ },
769
804
  "LutonBoroughCouncil": {
770
805
  "url": "https://myforms.luton.gov.uk",
771
806
  "wiki_command_url_override": "https://myforms.luton.gov.uk",
@@ -811,6 +846,13 @@
811
846
  "wiki_name": "Mid and East Antrim Borough Council",
812
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.)."
813
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
+ },
814
856
  "MidlothianCouncil": {
815
857
  "house_number": "52",
816
858
  "postcode": "EH19 2EB",
@@ -993,6 +1035,14 @@
993
1035
  "wiki_name": "Oldham Council",
994
1036
  "wiki_note": "Replace UPRN in URL with your own UPRN."
995
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
+ },
996
1046
  "PerthAndKinrossCouncil": {
997
1047
  "url": "https://www.pkc.gov.uk",
998
1048
  "wiki_command_url_override": "https://www.pkc.gov.uk",
@@ -1106,6 +1156,13 @@
1106
1156
  "url": "https://www.salford.gov.uk/bins-and-recycling/bin-collection-days/your-bin-collections",
1107
1157
  "wiki_name": "Salford City Council"
1108
1158
  },
1159
+ "SeftonCouncil": {
1160
+ "house_number": "1",
1161
+ "postcode": "L20 6GG",
1162
+ "url": "https://www.sefton.gov.uk",
1163
+ "wiki_name": "Sefton Council",
1164
+ "wiki_note": "Pass the postcode and house number in their respective arguments, both wrapped in quotes."
1165
+ },
1109
1166
  "SevenoaksDistrictCouncil": {
1110
1167
  "house_number": "60 Hever Road",
1111
1168
  "postcode": "TN15 6EB",
@@ -0,0 +1,56 @@
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
+ check_uprn(user_uprn)
20
+ bindata = {"bins": []}
21
+
22
+ URI = f"https://my.blaby.gov.uk/set-location.php?ref={user_uprn}&redirect=collections"
23
+
24
+ # Make the GET request
25
+ response = requests.get(URI)
26
+
27
+ # Parse the HTML
28
+ soup = BeautifulSoup(response.content, "html.parser")
29
+
30
+ # Find each collection container based on the class "box-item"
31
+ for container in soup.find_all(class_="box-item"):
32
+
33
+ # Get the next collection dates from the <p> tag containing <strong>
34
+ dates_tag = (
35
+ container.find("p", string=lambda text: "Next" in text)
36
+ .find_next("p")
37
+ .find("strong")
38
+ )
39
+ collection_dates = (
40
+ dates_tag.text.strip().split(", and then ")
41
+ if dates_tag
42
+ else "No dates found"
43
+ )
44
+
45
+ for collection_date in collection_dates:
46
+ dict_data = {
47
+ "type": container.find("h2").text.strip(),
48
+ "collectionDate": collection_date,
49
+ }
50
+ bindata["bins"].append(dict_data)
51
+
52
+ bindata["bins"].sort(
53
+ key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
54
+ )
55
+
56
+ return bindata
@@ -0,0 +1,55 @@
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
+ check_uprn(user_uprn)
20
+ bindata = {"bins": []}
21
+
22
+ URI = f"https://bincollections.bromsgrove.gov.uk/BinCollections/Details?uprn={user_uprn}"
23
+
24
+ # Make the GET request
25
+ response = requests.get(URI)
26
+
27
+ # Parse the HTML
28
+ soup = BeautifulSoup(response.content, "html.parser")
29
+
30
+ # Find each collection container
31
+ for container in soup.find_all(class_="collection-container"):
32
+ # Get the bin type from the heading
33
+ bin_type = container.find(class_="heading").text.strip()
34
+
35
+ # Get the next collection date from the caption
36
+ next_collection = (
37
+ container.find(class_="caption")
38
+ .text.replace("Next collection ", "")
39
+ .strip()
40
+ )
41
+
42
+ dict_data = {
43
+ "type": bin_type,
44
+ "collectionDate": datetime.strptime(
45
+ next_collection,
46
+ "%A, %d %B %Y",
47
+ ).strftime("%d/%m/%Y"),
48
+ }
49
+ bindata["bins"].append(dict_data)
50
+
51
+ bindata["bins"].sort(
52
+ key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
53
+ )
54
+
55
+ return bindata
@@ -0,0 +1,55 @@
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
+ check_uprn(user_uprn)
20
+ bindata = {"bins": []}
21
+
22
+ URI = f"https://www.carmarthenshire.gov.wales/umbraco/Surface/SurfaceRecycling/Index/?uprn={user_uprn}&lang=en-GB"
23
+
24
+ # Make the GET request
25
+ response = requests.get(URI)
26
+
27
+ # Parse the HTML
28
+ soup = BeautifulSoup(response.content, "html.parser")
29
+
30
+ # Find each bin collection container
31
+ for container in soup.find_all(class_="bin-day-container"):
32
+ # Get the bin type based on the class (e.g., Blue, Black, Garden, Nappy)
33
+ bin_type = container.get("class")[1] # Second class represents the bin type
34
+
35
+ # Find the next collection date
36
+ date_tag = container.find(class_="font11 text-center")
37
+ if date_tag:
38
+ collection_date = date_tag.text.strip()
39
+ else:
40
+ continue
41
+
42
+ dict_data = {
43
+ "type": bin_type,
44
+ "collectionDate": datetime.strptime(
45
+ collection_date,
46
+ "%A %d/%m/%Y",
47
+ ).strftime("%d/%m/%Y"),
48
+ }
49
+ bindata["bins"].append(dict_data)
50
+
51
+ bindata["bins"].sort(
52
+ key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
53
+ )
54
+
55
+ return bindata
@@ -0,0 +1,46 @@
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
+ check_uprn(user_uprn)
20
+ bindata = {"bins": []}
21
+
22
+ URI = f"https://www.east-ayrshire.gov.uk/Housing/RubbishAndRecycling/Collection-days/ViewYourRecyclingCalendar.aspx?r={user_uprn}"
23
+
24
+ # Make the GET request
25
+ response = requests.get(URI)
26
+
27
+ # Parse the HTML
28
+ soup = BeautifulSoup(response.content, "html.parser")
29
+
30
+ # Find each <time> element in the schedule
31
+ for entry in soup.find_all("time"):
32
+
33
+ dict_data = {
34
+ "type": entry.find(class_="ScheduleItem").text.strip(),
35
+ "collectionDate": datetime.strptime(
36
+ entry["datetime"],
37
+ "%Y-%m-%d",
38
+ ).strftime("%d/%m/%Y"),
39
+ }
40
+ bindata["bins"].append(dict_data)
41
+
42
+ bindata["bins"].sort(
43
+ key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
44
+ )
45
+
46
+ return bindata
@@ -28,14 +28,12 @@ class CouncilClass(AbstractGetBinDataClass):
28
28
 
29
29
  # Create Selenium webdriver
30
30
  driver = create_webdriver(web_driver, headless, None, __name__)
31
- driver.get(
32
- "https://www.e-lindsey.gov.uk/article/6714/Your-Waste-Collection-Days"
33
- )
31
+ driver.get("https://www.e-lindsey.gov.uk/mywastecollections")
34
32
 
35
33
  # Wait for the postcode field to appear then populate it
36
34
  inputElement_postcode = WebDriverWait(driver, 30).until(
37
35
  EC.presence_of_element_located(
38
- (By.ID, "WASTECOLLECTIONDAYS202324_LOOKUP_ADDRESSLOOKUPPOSTCODE")
36
+ (By.ID, "WASTECOLLECTIONDAYS202425_LOOKUP_ADDRESSLOOKUPPOSTCODE")
39
37
  )
40
38
  )
41
39
  inputElement_postcode.send_keys(user_postcode)
@@ -43,7 +41,7 @@ class CouncilClass(AbstractGetBinDataClass):
43
41
  # Click search button
44
42
  findAddress = WebDriverWait(driver, 10).until(
45
43
  EC.presence_of_element_located(
46
- (By.ID, "WASTECOLLECTIONDAYS202324_LOOKUP_ADDRESSLOOKUPSEARCH")
44
+ (By.ID, "WASTECOLLECTIONDAYS202425_LOOKUP_ADDRESSLOOKUPSEARCH")
47
45
  )
48
46
  )
49
47
  findAddress.click()
@@ -53,7 +51,7 @@ class CouncilClass(AbstractGetBinDataClass):
53
51
  EC.element_to_be_clickable(
54
52
  (
55
53
  By.XPATH,
56
- "//select[@id='WASTECOLLECTIONDAYS202324_LOOKUP_ADDRESSLOOKUPADDRESS']//option[contains(., '"
54
+ "//select[@id='WASTECOLLECTIONDAYS202425_LOOKUP_ADDRESSLOOKUPADDRESS']//option[contains(., '"
57
55
  + user_paon
58
56
  + "')]",
59
57
  )
@@ -63,7 +61,7 @@ class CouncilClass(AbstractGetBinDataClass):
63
61
  # Wait for the submit button to appear, then click it to get the collection dates
64
62
  submit = WebDriverWait(driver, 10).until(
65
63
  EC.presence_of_element_located(
66
- (By.ID, "WASTECOLLECTIONDAYS202324_LOOKUP_FIELD2_NEXT")
64
+ (By.ID, "WASTECOLLECTIONDAYS202425_LOOKUP_FIELD2_NEXT")
67
65
  )
68
66
  )
69
67
  submit.click()
@@ -77,25 +75,25 @@ class CouncilClass(AbstractGetBinDataClass):
77
75
 
78
76
  # Get collections
79
77
  for collection in soup.find_all("div", {"class": "waste-result"}):
80
- ptags = collection.find_all("p")
81
- dict_data = {
82
- "type": collection.find("h3").get_text(strip=True),
83
- "collectionDate": datetime.strptime(
84
- remove_ordinal_indicator_from_date_string(
85
- ptags[1]
86
- .get_text()
87
- .replace("The date of your next collection is", "")
88
- .replace(".", "")
89
- .strip()
90
- ),
91
- "%A %d %B %Y",
92
- ).strftime(date_format),
93
- }
94
- data["bins"].append(dict_data)
78
+ collection_date = None
79
+ for p_tag in collection.find_all("p"):
80
+ if "next collection is" in p_tag.text:
81
+ collection_date = p_tag.find("strong").text
82
+ break
83
+ if collection_date:
84
+ dict_data = {
85
+ "type": collection.find("h3").get_text(strip=True),
86
+ "collectionDate": datetime.strptime(
87
+ remove_ordinal_indicator_from_date_string(collection_date),
88
+ "%A %d %B %Y",
89
+ ).strftime(date_format),
90
+ }
91
+ data["bins"].append(dict_data)
95
92
 
96
93
  data["bins"].sort(
97
94
  key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
98
95
  )
96
+
99
97
  except Exception as e:
100
98
  # Here you can log the exception if needed
101
99
  print(f"An error occurred: {e}")
@@ -38,7 +38,7 @@ class CouncilClass(AbstractGetBinDataClass):
38
38
  for icon in icons:
39
39
  cal_item = icon.find_parent().find_parent()
40
40
  bin_date = datetime.strptime(
41
- cal_item["title"],
41
+ cal_item["title"].replace("today is ", ""),
42
42
  "%A, %d %B %Y",
43
43
  )
44
44
 
@@ -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
@@ -0,0 +1,67 @@
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_paon = kwargs.get("paon")
19
+ user_postcode = kwargs.get("postcode")
20
+ check_paon(user_paon)
21
+ check_postcode(user_postcode)
22
+ bindata = {"bins": []}
23
+
24
+ sess = requests.Session()
25
+
26
+ URI = "https://www.sefton.gov.uk/bins-and-recycling/bins-and-recycling/when-is-my-bin-collection-day/"
27
+
28
+ request = sess.get(URI)
29
+
30
+ soup = BeautifulSoup(request.content, "html.parser")
31
+ hidden = soup.find_all("input", {"type": "hidden"}, limit=2)
32
+ payload = {x["name"]: x["value"] for x in hidden}
33
+ payload["Postcode"] = user_postcode
34
+ payload["Streetname"] = user_paon
35
+ request = sess.post(
36
+ URI,
37
+ data=payload,
38
+ )
39
+ # We should now have the page displaying the select list for addresses, parse again to find the form elements we need.
40
+ soup = BeautifulSoup(request.content, "html.parser")
41
+ hidden = soup.find_all("input", {"type": "hidden"})
42
+ payload = {x["name"]: x["value"] for x in hidden}
43
+ payload["action"] = "Select"
44
+ option_tags = soup.select("select option")
45
+ for option in option_tags:
46
+ if option.text.upper().strip().startswith(user_paon):
47
+ payload["selectedValue"] = option["value"]
48
+ break
49
+ request = sess.post(
50
+ URI,
51
+ data=payload,
52
+ )
53
+ soup = BeautifulSoup(request.content, "html.parser")
54
+ tables = soup.find_all("table")
55
+ if len(tables) > 0:
56
+ for table in tables:
57
+ binType = table.td.text.split()[0]
58
+ binCollectionDate = table.td.findNext("td").findNext("td").text
59
+
60
+ dict_data = {"type": binType, "collectionDate": binCollectionDate}
61
+ bindata["bins"].append(dict_data)
62
+
63
+ bindata["bins"].sort(
64
+ key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
65
+ )
66
+
67
+ return bindata
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uk_bin_collection
3
- Version: 0.109.2
3
+ Version: 0.111.0
4
4
  Summary: Python Lib to collect UK Bin Data
5
5
  Author: Robert Bradley
6
6
  Author-email: robbrad182@gmail.com
@@ -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=mQ5rDFi-l9QHP6AvgNnxADOGtgdybTT24hOoEh7MkRI,78144
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
@@ -30,6 +30,7 @@ uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py,sha256=U1HOr
30
30
  uk_bin_collection/uk_bin_collection/councils/BelfastCityCouncil.py,sha256=SGOv9mm3fByyR3TQDyNcSLeidX_7FlHelkxnh-NUTcY,4327
31
31
  uk_bin_collection/uk_bin_collection/councils/BexleyCouncil.py,sha256=wqqCQZzu_q_pJrxTTlTrGGDgPB5EYgd4RiBy7nKnSHc,5835
32
32
  uk_bin_collection/uk_bin_collection/councils/BirminghamCityCouncil.py,sha256=now2xgpfshYM33UWC18j6xa6BuBydO5Sl7OrDQOo6b0,4687
33
+ uk_bin_collection/uk_bin_collection/councils/BlabyDistrictCouncil.py,sha256=I8LNDk9RIfLjnRfMVGesr7QaNqXznQ1St55hksAQlqA,1859
33
34
  uk_bin_collection/uk_bin_collection/councils/BlackburnCouncil.py,sha256=jHbCK8sL09vdmdP7Xnh8lIrU5AHTnJLEZfOLephPvWg,4090
34
35
  uk_bin_collection/uk_bin_collection/councils/BoltonCouncil.py,sha256=WI68r8jB0IHPUT4CgmZMtng899AAMFTxkyTdPg9yLF8,4117
35
36
  uk_bin_collection/uk_bin_collection/councils/BracknellForestCouncil.py,sha256=Llo1rULaAZ8rChVYZqXFFLo7CN6vbT0ULUJD6ActouY,9015
@@ -38,6 +39,7 @@ uk_bin_collection/uk_bin_collection/councils/BrecklandCouncil.py,sha256=PX6A_pDv
38
39
  uk_bin_collection/uk_bin_collection/councils/BrightonandHoveCityCouncil.py,sha256=k6qt4cds-Ejd97Z-__pw2BYvGVbFdc9SUfF73PPrTNA,5823
39
40
  uk_bin_collection/uk_bin_collection/councils/BristolCityCouncil.py,sha256=kJmmDJz_kQ45DHmG7ocrUpNJonEn0kuXYEDQyZaf9ks,5576
40
41
  uk_bin_collection/uk_bin_collection/councils/BromleyBoroughCouncil.py,sha256=_bAFykZWZkEVUB-QKeVLfWO8plG6nRgn71QF2BUN2rk,4329
42
+ uk_bin_collection/uk_bin_collection/councils/BromsgroveDistrictCouncil.py,sha256=PUfxP8j5Oh9wFHkdjbrJzQli9UzMHZzwrZ2hkThrvhI,1781
41
43
  uk_bin_collection/uk_bin_collection/councils/BroxtoweBoroughCouncil.py,sha256=-Facq-ToQkcWUePpKBwq90LZUFxgUSydNL2sYaLX4yw,4473
42
44
  uk_bin_collection/uk_bin_collection/councils/BuckinghamshireCouncil.py,sha256=_ELVUM5VLp1nwDxRpvpsp6n8SzLJvp_UyMp-i_MXYuo,4383
43
45
  uk_bin_collection/uk_bin_collection/councils/BuryCouncil.py,sha256=H7wAxO1nfxkewVoRRolumq8bBJG04siE3jieFH3RGpQ,2632
@@ -45,6 +47,7 @@ uk_bin_collection/uk_bin_collection/councils/CalderdaleCouncil.py,sha256=OJZcHYl
45
47
  uk_bin_collection/uk_bin_collection/councils/CannockChaseDistrictCouncil.py,sha256=ZamevXN8_Q8mRZOTESWtkb8jVyDXkTczcmhXMAVVSkM,2276
46
48
  uk_bin_collection/uk_bin_collection/councils/CanterburyCityCouncil.py,sha256=2s8OL2H0QlUaNu6gUWcoAKHrRdLuQzfMHjcSZuLYbB0,1771
47
49
  uk_bin_collection/uk_bin_collection/councils/CardiffCouncil.py,sha256=_k3sT_WR-gnjjt3tHQ-L2-keP9sdBV0ZeW7gHDzFPYo,7208
50
+ uk_bin_collection/uk_bin_collection/councils/CarmarthenshireCountyCouncil.py,sha256=viiZprMos_qcD44dki5_RRVZgGE4cH4zSHAzYRKrjHw,1864
48
51
  uk_bin_collection/uk_bin_collection/councils/CastlepointDistrictCouncil.py,sha256=JVPYUIlU2ISgbUSr5AOOXNK6IFQFtQmhZyYIMAOedD4,3858
49
52
  uk_bin_collection/uk_bin_collection/councils/CharnwoodBoroughCouncil.py,sha256=tXfzMetN6wxahuGGRp2mIyCCDSL4F2aG61HhUxw6COQ,2172
50
53
  uk_bin_collection/uk_bin_collection/councils/ChelmsfordCityCouncil.py,sha256=EB88D0MNJwuDZ2GX1ENc5maGYx17mnHTCtNl6s-v11E,5090
@@ -69,10 +72,11 @@ uk_bin_collection/uk_bin_collection/councils/DoverDistrictCouncil.py,sha256=3Zga
69
72
  uk_bin_collection/uk_bin_collection/councils/DudleyCouncil.py,sha256=tDGfBWD5AVEzHt-XowD4qmmDcdlOLKC0oON8jkARRAI,3134
70
73
  uk_bin_collection/uk_bin_collection/councils/DurhamCouncil.py,sha256=6O8bNsQVYQbrCYQE9Rp0c_rtkcXuxR3s9J6jn4MK4_s,1695
71
74
  uk_bin_collection/uk_bin_collection/councils/EalingCouncil.py,sha256=UhNXGi-_6NYZu50988VEvOzmAVunxOoyJ6mz0OEaUz4,1321
75
+ uk_bin_collection/uk_bin_collection/councils/EastAyrshireCouncil.py,sha256=U3Y_cQFR2KG5YZ7pPXeT7ZQJ85NUyx16Dky56IdvXUQ,1489
72
76
  uk_bin_collection/uk_bin_collection/councils/EastCambridgeshireCouncil.py,sha256=aYUVE5QqTxdj8FHhCB4EiFVDJahWJD9Pq0d1upBEvXg,1501
73
77
  uk_bin_collection/uk_bin_collection/councils/EastDevonDC.py,sha256=U0VwSNIldMv5nUoiXtFgjbE0m6Kb-8W2WZQGVCNF_WI,3261
74
78
  uk_bin_collection/uk_bin_collection/councils/EastHertsCouncil.py,sha256=hjIrZXM0qe8xvHfrBqMDyXnq0_h_ySODqTfmOI5ahTc,4071
75
- uk_bin_collection/uk_bin_collection/councils/EastLindseyDistrictCouncil.py,sha256=o_HPSFhb2ybmwv32_7T7CO1f2mGDkYCNPfaM5xz6bUI,4356
79
+ uk_bin_collection/uk_bin_collection/councils/EastLindseyDistrictCouncil.py,sha256=RSOTD1MIXSW27eGf3TixCiJK4HtSJnpfME2CjalDeXs,4326
76
80
  uk_bin_collection/uk_bin_collection/councils/EastRenfrewshireCouncil.py,sha256=5giegMCKQ2JhVDR5M4mevVxIdhZtSW7kbuuoSkj3EGk,4361
77
81
  uk_bin_collection/uk_bin_collection/councils/EastRidingCouncil.py,sha256=oL-NqriLVy_NChGASNh8qTqeakLn4iP_XzoMC6VlPGM,5216
78
82
  uk_bin_collection/uk_bin_collection/councils/EastSuffolkCouncil.py,sha256=qQ0oOfGd0sWcczse_B22YoeL9uj3og8v3UJLt_Sx29c,4353
@@ -90,7 +94,7 @@ uk_bin_collection/uk_bin_collection/councils/FlintshireCountyCouncil.py,sha256=R
90
94
  uk_bin_collection/uk_bin_collection/councils/ForestOfDeanDistrictCouncil.py,sha256=YWT2GM2-bQ3Zh9ps1K14XRZfanuJOlV-zHpOOYMXAXY,4893
91
95
  uk_bin_collection/uk_bin_collection/councils/GatesheadCouncil.py,sha256=SRCgYhYs6rv_8C1UEDVORHZgXxcJkoZBjzdYS4Lu-ew,4531
92
96
  uk_bin_collection/uk_bin_collection/councils/GedlingBoroughCouncil.py,sha256=XzfFMCwclh9zAJgsbaj4jywjdiH0wPaFicaVsLrN3ms,2297
93
- uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py,sha256=i7BympEhCm7D9yR0p5_QQICtWvNcDYNJIWB19SA0g2k,2303
97
+ uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py,sha256=9N5GXR32gXYBl3i44TITiZ7N73rgqXZmkyenI-kVRQI,2328
94
98
  uk_bin_collection/uk_bin_collection/councils/GloucesterCityCouncil.py,sha256=8Wjvmdvg5blHVrREaEnhhWZaWhYVP4v_KdDVPLIUxaU,4889
95
99
  uk_bin_collection/uk_bin_collection/councils/GuildfordCouncil.py,sha256=9pVrmQhZcK2AD8gX8mNvP--L4L9KaY6L3B822VX6fec,5695
96
100
  uk_bin_collection/uk_bin_collection/councils/HaltonBoroughCouncil.py,sha256=gq_CPqi6qM2oNiHhKKF1lZC86fyKL4lPhh_DN9pJZ04,5971
@@ -117,6 +121,7 @@ uk_bin_collection/uk_bin_collection/councils/LondonBoroughHarrow.py,sha256=kzKwb
117
121
  uk_bin_collection/uk_bin_collection/councils/LondonBoroughHounslow.py,sha256=UOeiOxGMvVMm2UFaqjmQpm7vxzqJNSSN8LM9lAUjs2c,3021
118
122
  uk_bin_collection/uk_bin_collection/councils/LondonBoroughLambeth.py,sha256=r9D5lHe5kIRStCd5lRIax16yhb4KTFzzfYEFv1bacWw,2009
119
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
120
125
  uk_bin_collection/uk_bin_collection/councils/LutonBoroughCouncil.py,sha256=vScUi_R8FnBddii2_zLlZBLxuh85mKmCm8nKW3zxky0,2758
121
126
  uk_bin_collection/uk_bin_collection/councils/MaldonDistrictCouncil.py,sha256=PMVt2XFggttPmbWyrBrHJ-W6R_6-0ux1BkY1kj1IKzg,1997
122
127
  uk_bin_collection/uk_bin_collection/councils/MalvernHillsDC.py,sha256=iQG0EkX2npBicvsGKQRYyBGSBvKVUbKvUvvwrC9xV1A,2100
@@ -124,6 +129,7 @@ uk_bin_collection/uk_bin_collection/councils/ManchesterCityCouncil.py,sha256=RY3
124
129
  uk_bin_collection/uk_bin_collection/councils/MansfieldDistrictCouncil.py,sha256=F5AiTxImrnjE1k3ry96bfstOf5XSNBJS_4qqmymmh3w,1386
125
130
  uk_bin_collection/uk_bin_collection/councils/MertonCouncil.py,sha256=3Y2Un4xXo1sCcMsudynODSzocV_mMofWkX2JqONDb5o,1997
126
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
127
133
  uk_bin_collection/uk_bin_collection/councils/MidSussexDistrictCouncil.py,sha256=AZgC9wmDLEjUOtIFvf0ehF5LHturXTH4DkE3ioPSVBA,6254
128
134
  uk_bin_collection/uk_bin_collection/councils/MidlothianCouncil.py,sha256=mM5-itJDNhjsT5UEjSFfWppmfmPFSns4u_1QblewuFU,5605
129
135
  uk_bin_collection/uk_bin_collection/councils/MiltonKeynesCityCouncil.py,sha256=3olsWa77L34vz-c7NgeGK9xmNuR4Ws_oAk5D4UpIkPw,2005
@@ -150,6 +156,7 @@ uk_bin_collection/uk_bin_collection/councils/NorthumberlandCouncil.py,sha256=KEF
150
156
  uk_bin_collection/uk_bin_collection/councils/NorwichCityCouncil.py,sha256=At-9dEcKBUZSrtJ2RncwvMnV0OVU3pE6kxEYbLL-Av8,2437
151
157
  uk_bin_collection/uk_bin_collection/councils/NottinghamCityCouncil.py,sha256=panTCjnsBOQ98-TBO9xVZk_jcT_gjMhx3Gg5oWxBRLo,1254
152
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
153
160
  uk_bin_collection/uk_bin_collection/councils/PerthAndKinrossCouncil.py,sha256=Kos5GzN2co3Ij3tSHOXB9S71Yt78RROCfVRtnh7M1VU,3657
154
161
  uk_bin_collection/uk_bin_collection/councils/PlymouthCouncil.py,sha256=FJqpJ0GJhpjYeyZ9ioZPkKGl-zrqMD3y5iKa07e_i30,3202
155
162
  uk_bin_collection/uk_bin_collection/councils/PortsmouthCityCouncil.py,sha256=xogNgVvwM5FljCziiNLgZ_wzkOnrQkifi1dkPMDRMtg,5588
@@ -166,6 +173,7 @@ uk_bin_collection/uk_bin_collection/councils/RugbyBoroughCouncil.py,sha256=a5ySL
166
173
  uk_bin_collection/uk_bin_collection/councils/RushcliffeBoroughCouncil.py,sha256=wMtiYRirT585vtsEOIyXHugk7aEj3pvyVWBaAePdqtE,4005
167
174
  uk_bin_collection/uk_bin_collection/councils/RushmoorCouncil.py,sha256=ZsGnXjoEaOS6U7fI0w7-uqxayAHdNVKsJi2fqIWEls8,3375
168
175
  uk_bin_collection/uk_bin_collection/councils/SalfordCityCouncil.py,sha256=jJjAH_dM298VIJ4-SEy7agxUe8aFJ_sEPK_ZwmWJ9cE,2506
176
+ uk_bin_collection/uk_bin_collection/councils/SeftonCouncil.py,sha256=XUEz2li0oHrRhdkls5qzlZNZ0GuwSG7r0dwsL-qdoFA,2480
169
177
  uk_bin_collection/uk_bin_collection/councils/SevenoaksDistrictCouncil.py,sha256=qqrrRaSVm9CYAtm0rB2ZnyH_nLwaReuacoUxZpo597k,4260
170
178
  uk_bin_collection/uk_bin_collection/councils/SheffieldCityCouncil.py,sha256=9g9AeiackoWyej9EVlKUzywzAtMuBVD0f93ZryAUha8,2016
171
179
  uk_bin_collection/uk_bin_collection/councils/ShropshireCouncil.py,sha256=6OIEhJmv-zLJiEo8WaJePA7JuhNRGkh2WohFLhzN8Kk,1477
@@ -238,8 +246,8 @@ uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bId
238
246
  uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=EQWRhZ2pEejlvm0fPyOTsOHKvUZmPnxEYO_OWRGKTjs,1158
239
247
  uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
240
248
  uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=YvmHfZqanwrJ8ToGch34x-L-7yPe31nB_x77_Mgl_vo,4545
241
- uk_bin_collection-0.109.2.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
242
- uk_bin_collection-0.109.2.dist-info/METADATA,sha256=m_lO6Kjo1V5QSldCjj3fhgoV38gfqApEO0dQNRf3Pic,17574
243
- uk_bin_collection-0.109.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
244
- uk_bin_collection-0.109.2.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
245
- uk_bin_collection-0.109.2.dist-info/RECORD,,
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,,