uk_bin_collection 0.79.0__py3-none-any.whl → 0.80.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.
Files changed (33) hide show
  1. uk_bin_collection/tests/input.json +39 -1
  2. uk_bin_collection/uk_bin_collection/common.py +23 -1
  3. uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py +2 -1
  4. uk_bin_collection/uk_bin_collection/councils/BirminghamCityCouncil.py +2 -1
  5. uk_bin_collection/uk_bin_collection/councils/BracknellForestCouncil.py +4 -4
  6. uk_bin_collection/uk_bin_collection/councils/BristolCityCouncil.py +2 -1
  7. uk_bin_collection/uk_bin_collection/councils/CrawleyBoroughCouncil.py +1 -1
  8. uk_bin_collection/uk_bin_collection/councils/CroydonCouncil.py +5 -4
  9. uk_bin_collection/uk_bin_collection/councils/DartfordBoroughCouncil.py +7 -9
  10. uk_bin_collection/uk_bin_collection/councils/EastCambridgeshireCouncil.py +2 -1
  11. uk_bin_collection/uk_bin_collection/councils/LancasterCityCouncil.py +6 -4
  12. uk_bin_collection/uk_bin_collection/councils/LisburnCastlereaghCityCouncil.py +1 -0
  13. uk_bin_collection/uk_bin_collection/councils/ManchesterCityCouncil.py +2 -1
  14. uk_bin_collection/uk_bin_collection/councils/NewForestCouncil.py +146 -0
  15. uk_bin_collection/uk_bin_collection/councils/NewportCityCouncil.py +1 -0
  16. uk_bin_collection/uk_bin_collection/councils/NorthTynesideCouncil.py +2 -1
  17. uk_bin_collection/uk_bin_collection/councils/SomersetCouncil.py +1 -0
  18. uk_bin_collection/uk_bin_collection/councils/SouthCambridgeshireCouncil.py +1 -0
  19. uk_bin_collection/uk_bin_collection/councils/StHelensBC.py +2 -1
  20. uk_bin_collection/uk_bin_collection/councils/StaffordBoroughCouncil.py +69 -0
  21. uk_bin_collection/uk_bin_collection/councils/SwanseaCouncil.py +70 -0
  22. uk_bin_collection/uk_bin_collection/councils/TestValleyBoroughCouncil.py +1 -0
  23. uk_bin_collection/uk_bin_collection/councils/ThreeRiversDistrictCouncil.py +140 -0
  24. uk_bin_collection/uk_bin_collection/councils/UttlesfordDistrictCouncil.py +117 -0
  25. uk_bin_collection/uk_bin_collection/councils/WaverleyBoroughCouncil.py +2 -1
  26. uk_bin_collection/uk_bin_collection/councils/WiganBoroughCouncil.py +2 -1
  27. uk_bin_collection/uk_bin_collection/councils/WindsorAndMaidenheadCouncil.py +2 -1
  28. uk_bin_collection/uk_bin_collection/councils/WokingBoroughCouncil.py +3 -1
  29. {uk_bin_collection-0.79.0.dist-info → uk_bin_collection-0.80.0.dist-info}/METADATA +1 -1
  30. {uk_bin_collection-0.79.0.dist-info → uk_bin_collection-0.80.0.dist-info}/RECORD +33 -28
  31. {uk_bin_collection-0.79.0.dist-info → uk_bin_collection-0.80.0.dist-info}/LICENSE +0 -0
  32. {uk_bin_collection-0.79.0.dist-info → uk_bin_collection-0.80.0.dist-info}/WHEEL +0 -0
  33. {uk_bin_collection-0.79.0.dist-info → uk_bin_collection-0.80.0.dist-info}/entry_points.txt +0 -0
@@ -263,9 +263,9 @@
263
263
  "wiki_name": "Croydon Council"
264
264
  },
265
265
  "DartfordBoroughCouncil": {
266
+ "uprn": "010094157511",
266
267
  "url": "https://windmz.dartford.gov.uk/ufs/WS_CHECK_COLLECTIONS.eb?UPRN=010094157511",
267
268
  "wiki_name": "DartfordBoroughCouncil",
268
- "uprn": "010094157511",
269
269
  "wiki_note": "Use https://uprn.uk/ to find your UPRN "
270
270
  },
271
271
  "DerbyshireDalesDistrictCouncil": {
@@ -602,6 +602,14 @@
602
602
  "web_driver": "http://selenium:4444",
603
603
  "wiki_name": "Neath Port Talbot Council"
604
604
  },
605
+ "NewForestCouncil": {
606
+ "postcode": "SO41 0GJ",
607
+ "skip_get_url": true,
608
+ "uprn": "100060482345",
609
+ "url": "https://forms.newforest.gov.uk/id/FIND_MY_COLLECTION",
610
+ "web_driver": "http://selenium:4444",
611
+ "wiki_name": "New Forest Council"
612
+ },
605
613
  "NewarkAndSherwoodDC": {
606
614
  "url": "http://app.newark-sherwooddc.gov.uk/bincollection/calendar?pid=200004258529",
607
615
  "wiki_command_url_override": "http://app.newark-sherwooddc.gov.uk/bincollection/calendar?pid=XXXXXXXX",
@@ -909,6 +917,12 @@
909
917
  "url": "https://www.sthelens.gov.uk/",
910
918
  "wiki_name": "St Helens Borough Council"
911
919
  },
920
+ "StaffordBoroughCouncil": {
921
+ "uprn": "100032203010",
922
+ "url": "https://www.staffordbc.gov.uk/address/100032203010",
923
+ "wiki_name": "StaffordBoroughCouncil",
924
+ "wiki_note": "The URL needs to be https://www.staffordbc.gov.uk/address/<Your_UPRN>"
925
+ },
912
926
  "StaffordshireMoorlandsDistrictCouncil": {
913
927
  "postcode": "ST8 6HN",
914
928
  "skip_get_url": true,
@@ -959,6 +973,13 @@
959
973
  "url": "https://swale.gov.uk/bins-littering-and-the-environment/bins/collection-days",
960
974
  "wiki_name": "Swale Borough Council"
961
975
  },
976
+ "SwanseaCouncil": {
977
+ "postcode": "SA43PQ",
978
+ "skip_get_url": true,
979
+ "uprn": "100100324821",
980
+ "url": "https://www1.swansea.gov.uk/recyclingsearch/",
981
+ "wiki_name": "SwanseaCouncil"
982
+ },
962
983
  "TamesideMBCouncil": {
963
984
  "skip_get_url": true,
964
985
  "uprn": "100012835362",
@@ -992,6 +1013,14 @@
992
1013
  "url": "https://testvalley.gov.uk/wasteandrecycling/when-are-my-bins-collected",
993
1014
  "wiki_name": "Test Valley Borough Council"
994
1015
  },
1016
+ "ThreeRiversDistrictCouncil": {
1017
+ "postcode": "WD3 7AZ",
1018
+ "skip_get_url": true,
1019
+ "uprn": "100080913662",
1020
+ "url": "https://my.threerivers.gov.uk/en/AchieveForms/?mode=fill&consentMessage=yes&form_uri=sandbox-publish://AF-Process-52df96e3-992a-4b39-bba3-06cfaabcb42b/AF-Stage-01ee28aa-1584-442c-8d1f-119b6e27114a/definition.json&process=1&process_uri=sandbox-processes://AF-Process-52df96e3-992a-4b39-bba3-06cfaabcb42b&process_id=AF-Process-52df96e3-992a-4b39-bba3-06cfaabcb42b&noLoginPrompt=1",
1021
+ "web_driver": "http://selenium:4444",
1022
+ "wiki_name": "Three Rivers District Council"
1023
+ },
995
1024
  "TonbridgeAndMallingBC": {
996
1025
  "postcode": "ME19 4JS",
997
1026
  "skip_get_url": true,
@@ -1011,6 +1040,15 @@
1011
1040
  "url": "https://collections-torridge.azurewebsites.net/WebService2.asmx",
1012
1041
  "wiki_name": "Torridge District Council"
1013
1042
  },
1043
+ "UttlesfordDistrictCouncil": {
1044
+ "url": "https://bins.uttlesford.gov.uk/",
1045
+ "wiki_name": "UttlesfordDistrictCouncil",
1046
+ "skip_get_url": true,
1047
+ "postcode": "CM23 5QF",
1048
+ "uprn": "100090643434",
1049
+ "house_number": "72, Birchanger Lane",
1050
+ "web_driver": "http://selenium:4444"
1051
+ },
1014
1052
  "ValeofGlamorganCouncil": {
1015
1053
  "skip_get_url": true,
1016
1054
  "uprn": "64029020",
@@ -5,7 +5,7 @@ import os
5
5
  import pandas as pd
6
6
  import re
7
7
  import requests
8
- from datetime import datetime
8
+ from datetime import datetime, timedelta
9
9
  from dateutil.parser import parse
10
10
  from enum import Enum
11
11
  from selenium import webdriver
@@ -242,6 +242,28 @@ def save_data(file_path, data):
242
242
  json.dump(data, file, sort_keys=True, indent=4)
243
243
 
244
244
 
245
+ def get_next_day_of_week(day_name):
246
+ days_of_week = [
247
+ "Monday",
248
+ "Tuesday",
249
+ "Wednesday",
250
+ "Thursday",
251
+ "Friday",
252
+ "Saturday",
253
+ "Sunday",
254
+ ]
255
+ today = datetime.now()
256
+ today_idx = today.weekday() # Monday is 0 and Sunday is 6
257
+ target_idx = days_of_week.index(day_name)
258
+
259
+ days_until_target = (target_idx - today_idx) % 7
260
+ if days_until_target == 0:
261
+ days_until_target = 7 # Ensure it's the next instance of the day, not today if today is that day
262
+
263
+ next_day = today + timedelta(days=days_until_target)
264
+ return next_day.strftime(date_format)
265
+
266
+
245
267
  def contains_date(string, fuzzy=False) -> bool:
246
268
  """
247
269
  Return whether the string can be interpreted as a date.
@@ -2,6 +2,7 @@ from datetime import datetime
2
2
 
3
3
  import requests
4
4
  from bs4 import BeautifulSoup
5
+
5
6
  from uk_bin_collection.uk_bin_collection.common import *
6
7
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
7
8
 
@@ -22,7 +23,7 @@ class CouncilClass(AbstractGetBinDataClass):
22
23
 
23
24
  # Start a new session to walk through the form
24
25
  requests.packages.urllib3.disable_warnings()
25
- s = requests.session()
26
+ s = requests.Session()
26
27
 
27
28
  headers = {
28
29
  "Origin": "https://www.centralbedfordshire.gov.uk",
@@ -1,5 +1,6 @@
1
- from dateutil.relativedelta import relativedelta
2
1
  from bs4 import BeautifulSoup
2
+ from dateutil.relativedelta import relativedelta
3
+
3
4
  from uk_bin_collection.uk_bin_collection.common import *
4
5
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
5
6
 
@@ -64,7 +64,7 @@ def get_csrf_token(s: requests.session, base_url: str) -> str:
64
64
  """
65
65
  Gets a CSRF token
66
66
  :rtype: str
67
- :param s: requests.session() to use
67
+ :param s: requests.Session() to use
68
68
  :param base_url: Base URL to use
69
69
  :return: CSRF token
70
70
  """
@@ -95,7 +95,7 @@ def get_address_id(
95
95
  """
96
96
  Gets the address ID
97
97
  :rtype: str
98
- :param s: requests.session() to use
98
+ :param s: requests.Session() to use
99
99
  :param base_url: Base URL to use
100
100
  :param csrf_token: CSRF token to use
101
101
  :param postcode: Postcode to use
@@ -156,7 +156,7 @@ def get_collection_data(
156
156
  """
157
157
  Gets the collection data
158
158
  :rtype: str
159
- :param s: requests.session() to use
159
+ :param s: requests.Session() to use
160
160
  :param base_url: Base URL to use
161
161
  :param csrf_token: CSRF token to use
162
162
  :param address_id: Address id to use
@@ -203,7 +203,7 @@ class CouncilClass(AbstractGetBinDataClass):
203
203
 
204
204
  def parse_data(self, page: str, **kwargs) -> dict:
205
205
  requests.packages.urllib3.disable_warnings()
206
- s = requests.session()
206
+ s = requests.Session()
207
207
  base_url = "https://selfservice.mybfc.bracknell-forest.gov.uk"
208
208
  paon = kwargs.get("paon")
209
209
  postcode = kwargs.get("postcode")
@@ -2,6 +2,7 @@ import ast
2
2
 
3
3
  import requests
4
4
  from bs4 import BeautifulSoup
5
+
5
6
  from uk_bin_collection.uk_bin_collection.common import *
6
7
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
7
8
 
@@ -19,7 +20,7 @@ class CouncilClass(AbstractGetBinDataClass):
19
20
  check_uprn(user_uprn)
20
21
 
21
22
  requests.packages.urllib3.disable_warnings()
22
- s = requests.session()
23
+ s = requests.Session()
23
24
 
24
25
  service_type_headers = {
25
26
  "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,"
@@ -35,7 +35,7 @@ class CouncilClass(AbstractGetBinDataClass):
35
35
 
36
36
  data = {"bins": []}
37
37
 
38
- titles = [title.text for title in soup.select(".title")]
38
+ titles = [title.text for title in soup.select(".block-title")]
39
39
  collection_tag = soup.body.find_all(
40
40
  "div", {"class": "col-md-6 col-sm-6 col-xs-6"}, string="Next collection"
41
41
  )
@@ -1,6 +1,7 @@
1
1
  import time
2
2
 
3
3
  from bs4 import BeautifulSoup
4
+
4
5
  from uk_bin_collection.uk_bin_collection.common import *
5
6
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
6
7
 
@@ -75,7 +76,7 @@ def get_csrf_token(s: requests.session, base_url: str) -> str:
75
76
  """
76
77
  Gets a CSRF token
77
78
  :rtype: str
78
- :param s: requests.session() to use
79
+ :param s: requests.Session() to use
79
80
  :param base_url: Base URL to use
80
81
  :return: CSRF token
81
82
  """
@@ -106,7 +107,7 @@ def get_address_id(
106
107
  """
107
108
  Gets the address ID
108
109
  :rtype: str
109
- :param s: requests.session() to use
110
+ :param s: requests.Session() to use
110
111
  :param base_url: Base URL to use
111
112
  :param csrf_token: CSRF token to use
112
113
  :param postcode: Postcode to use
@@ -171,7 +172,7 @@ def get_collection_data(
171
172
  """
172
173
  Gets the collection data
173
174
  :rtype: str
174
- :param s: requests.session() to use
175
+ :param s: requests.Session() to use
175
176
  :param base_url: Base URL to use
176
177
  :param csrf_token: CSRF token to use
177
178
  :param address_id: Address id to use
@@ -240,7 +241,7 @@ class CouncilClass(AbstractGetBinDataClass):
240
241
 
241
242
  def parse_data(self, page: str, **kwargs) -> dict:
242
243
  requests.packages.urllib3.disable_warnings()
243
- s = requests.session()
244
+ s = requests.Session()
244
245
  base_url = "https://service.croydon.gov.uk"
245
246
  paon = kwargs.get("paon")
246
247
  postcode = kwargs.get("postcode")
@@ -17,27 +17,25 @@ class CouncilClass(AbstractGetBinDataClass):
17
17
  soup.prettify()
18
18
 
19
19
  # Extract data
20
- bin_data = {
21
- "bins": []
22
- }
20
+ bin_data = {"bins": []}
23
21
 
24
22
  # Find the table containing the bin collection data
25
- table = soup.find('table', {'class': 'eb-EVDNdR1G-tableContent'})
23
+ table = soup.find("table", {"class": "eb-EVDNdR1G-tableContent"})
26
24
 
27
25
  if table:
28
- rows = table.find_all('tr', class_='eb-EVDNdR1G-tableRow')
29
-
26
+ rows = table.find_all("tr", class_="eb-EVDNdR1G-tableRow")
27
+
30
28
  for row in rows:
31
- columns = row.find_all('td')
29
+ columns = row.find_all("td")
32
30
  if len(columns) >= 4:
33
31
  collection_type = columns[1].get_text(strip=True)
34
32
  collection_date = columns[3].get_text(strip=True)
35
-
33
+
36
34
  # Validate collection_date format
37
35
  if re.match(r"\d{2}/\d{2}/\d{4}", collection_date):
38
36
  bin_entry = {
39
37
  "type": collection_type,
40
- "collectionDate": collection_date
38
+ "collectionDate": collection_date,
41
39
  }
42
40
  bin_data["bins"].append(bin_entry)
43
41
 
@@ -1,4 +1,5 @@
1
1
  from bs4 import BeautifulSoup
2
+
2
3
  from uk_bin_collection.uk_bin_collection.common import *
3
4
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
4
5
 
@@ -21,7 +22,7 @@ class CouncilClass(AbstractGetBinDataClass):
21
22
 
22
23
  # Make Request
23
24
  requests.packages.urllib3.disable_warnings()
24
- s = requests.session()
25
+ s = requests.Session()
25
26
  page = s.get(url)
26
27
 
27
28
  # Make a BS4 object
@@ -1,8 +1,10 @@
1
- from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
2
- from uk_bin_collection.uk_bin_collection.common import *
3
- from bs4 import BeautifulSoup
4
1
  from datetime import datetime
2
+
5
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
6
8
 
7
9
 
8
10
  class CouncilClass(AbstractGetBinDataClass):
@@ -19,7 +21,7 @@ class CouncilClass(AbstractGetBinDataClass):
19
21
  # start session
20
22
  # note: this ignores the given url
21
23
  base_url = "https://lcc-wrp.whitespacews.com"
22
- session = requests.session()
24
+ session = requests.Session()
23
25
  response = session.get(base_url + "/#!")
24
26
  links = [
25
27
  a["href"]
@@ -3,6 +3,7 @@ from datetime import date, datetime
3
3
 
4
4
  import requests
5
5
  from bs4 import BeautifulSoup
6
+
6
7
  from uk_bin_collection.uk_bin_collection.common import *
7
8
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
8
9
 
@@ -2,6 +2,7 @@ from datetime import datetime
2
2
 
3
3
  import requests
4
4
  from bs4 import BeautifulSoup
5
+
5
6
  from uk_bin_collection.uk_bin_collection.common import *
6
7
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
7
8
 
@@ -20,7 +21,7 @@ class CouncilClass(AbstractGetBinDataClass):
20
21
 
21
22
  # Start a new session to walk through the form
22
23
  requests.packages.urllib3.disable_warnings()
23
- s = requests.session()
24
+ s = requests.Session()
24
25
 
25
26
  # There's a cookie that makes the whole thing valid when you search for a postcode,
26
27
  # but postcode and UPRN is a hassle imo, so this makes a request for the session to get a cookie
@@ -0,0 +1,146 @@
1
+ import logging
2
+ import pickle
3
+ import time
4
+
5
+ import requests
6
+ from bs4 import BeautifulSoup
7
+ from selenium import webdriver
8
+ from selenium.webdriver.common.by import By
9
+ from selenium.webdriver.common.keys import Keys
10
+ from selenium.webdriver.support import expected_conditions as EC
11
+ from selenium.webdriver.support.ui import Select
12
+ from selenium.webdriver.support.wait import WebDriverWait
13
+ from uk_bin_collection.uk_bin_collection.common import *
14
+
15
+ from uk_bin_collection.uk_bin_collection.common import *
16
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
17
+
18
+ # Set up logging
19
+ logging.basicConfig(
20
+ level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
21
+ )
22
+
23
+
24
+ class CouncilClass(AbstractGetBinDataClass):
25
+
26
+ def parse_data(self, page: str, **kwargs) -> dict:
27
+ driver = None
28
+ try:
29
+ data = {"bins": []}
30
+ collections = []
31
+ user_uprn = kwargs.get("uprn")
32
+ user_postcode = kwargs.get("postcode")
33
+ web_driver = kwargs.get("web_driver")
34
+ headless = kwargs.get("headless")
35
+ check_postcode(user_postcode)
36
+ url = "https://forms.newforest.gov.uk/ufs/FIND_MY_COLLECTION.eb"
37
+
38
+ # Get session cookies using requests
39
+
40
+ user_agent = """general.useragent.override", "userAgent=Mozilla/5.0
41
+ (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like
42
+ Gecko) CriOS/101.0.4951.44 Mobile/15E148 Safari/604.1"""
43
+
44
+ # Create Selenium webdriver
45
+ driver = create_webdriver(web_driver, headless, user_agent, __name__)
46
+
47
+ # Navigate to the page first
48
+ driver.get(url)
49
+ driver.refresh() # important otherwise it results in too many redirects
50
+
51
+ wait = WebDriverWait(driver, 60)
52
+
53
+ logging.info("Entering postcode")
54
+ input_element_postcode = wait.until(
55
+ EC.presence_of_element_located((By.XPATH, '//input[@id="CTID-1-_-A"]'))
56
+ )
57
+
58
+ input_element_postcode.send_keys(user_postcode)
59
+
60
+ logging.info("Searching for postcode")
61
+ input_element_postcode_btn = wait.until(
62
+ EC.element_to_be_clickable((By.XPATH, '//input[@type="submit"]'))
63
+ )
64
+
65
+ input_element_postcode_btn.click()
66
+
67
+ logging.info("Waiting for address dropdown")
68
+ input_element_postcode_dropdown = wait.until(
69
+ EC.presence_of_element_located((By.XPATH, '//select[@id="CTID-6-_-A"]'))
70
+ )
71
+
72
+ logging.info("Selecting address")
73
+ drop_down_values = Select(input_element_postcode_dropdown)
74
+ option_element = wait.until(
75
+ EC.presence_of_element_located(
76
+ (By.CSS_SELECTOR, f'option[value="{str(user_uprn)}"]')
77
+ )
78
+ )
79
+
80
+ driver.execute_script("arguments[0].scrollIntoView();", option_element)
81
+ drop_down_values.select_by_value(str(user_uprn))
82
+
83
+ input_element_address_btn = wait.until(
84
+ EC.element_to_be_clickable((By.XPATH, '//input[@value="Submit"]'))
85
+ )
86
+
87
+ input_element_address_btn.click()
88
+
89
+ logging.info("Waiting for bin collection page")
90
+ h4_element = wait.until(
91
+ EC.presence_of_element_located(
92
+ (By.XPATH, "//h1[contains(text(), 'Collections days for')]")
93
+ )
94
+ )
95
+
96
+ logging.info("Extracting bin collection data")
97
+ soup = BeautifulSoup(driver.page_source, features="html.parser")
98
+ bins = []
99
+
100
+ # Rubbish and recycling
101
+ rubbish_recycling = soup.find(
102
+ "span", class_="CTID-77-_ eb-77-Override-textControl"
103
+ )
104
+ if rubbish_recycling:
105
+ match = re.search(r"collected weekly on (\w+)", rubbish_recycling.text)
106
+ if match:
107
+ day_name = match.group(1)
108
+ next_collection = get_next_day_of_week(day_name)
109
+ bins.append(
110
+ {
111
+ "type": "Rubbish and recycling",
112
+ "collectionDate": next_collection,
113
+ }
114
+ )
115
+
116
+ # Glass collection
117
+ glass_collection = soup.find("span", class_="CTID-78-_ eb-78-textControl")
118
+ if glass_collection:
119
+ match = re.search(
120
+ r"next collection is\s+(\d{2}/\d{2}/\d{4})", glass_collection.text
121
+ )
122
+ if match:
123
+ bins.append(
124
+ {"type": "Glass collection", "collectionDate": match.group(1)}
125
+ )
126
+
127
+ # Garden waste
128
+ garden_waste = soup.find("span", class_="CTID-17-_ eb-17-textControl")
129
+ if garden_waste:
130
+ match = re.search(
131
+ r"next collection is\s+(\d{2}/\d{2}/\d{4})", garden_waste.text
132
+ )
133
+ if match:
134
+ bins.append(
135
+ {"type": "Garden waste", "collectionDate": match.group(1)}
136
+ )
137
+
138
+ return {"bins": bins}
139
+
140
+ except Exception as e:
141
+ logging.error(f"An error occurred: {e}")
142
+ raise
143
+
144
+ finally:
145
+ if driver:
146
+ driver.quit()
@@ -1,4 +1,5 @@
1
1
  from bs4 import BeautifulSoup
2
+
2
3
  from uk_bin_collection.uk_bin_collection.common import *
3
4
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
4
5
 
@@ -3,6 +3,7 @@ from datetime import *
3
3
 
4
4
  import requests
5
5
  from bs4 import BeautifulSoup
6
+
6
7
  from uk_bin_collection.uk_bin_collection.common import *
7
8
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
8
9
 
@@ -24,7 +25,7 @@ class CouncilClass(AbstractGetBinDataClass):
24
25
  check_postcode(user_postcode)
25
26
 
26
27
  # Get form data
27
- s = requests.session()
28
+ s = requests.Session()
28
29
  cookies = {
29
30
  "ntc-cookie-policy": "1",
30
31
  "SSESS6ec6d5d2d471c0357053d5993a839bce": "qBdR7XhmSMd5_PDBIqG0It2R0Fq67igrejRY-WOcskE",
@@ -1,4 +1,5 @@
1
1
  from bs4 import BeautifulSoup
2
+
2
3
  from uk_bin_collection.uk_bin_collection.common import *
3
4
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
4
5
 
@@ -1,5 +1,6 @@
1
1
  import requests
2
2
  from bs4 import BeautifulSoup
3
+
3
4
  from uk_bin_collection.uk_bin_collection.common import *
4
5
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
5
6
 
@@ -1,4 +1,5 @@
1
1
  from bs4 import BeautifulSoup
2
+
2
3
  from uk_bin_collection.uk_bin_collection.common import *
3
4
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
4
5
 
@@ -21,7 +22,7 @@ class CouncilClass(AbstractGetBinDataClass):
21
22
 
22
23
  # Make Request
23
24
  requests.packages.urllib3.disable_warnings()
24
- s = requests.session()
25
+ s = requests.Session()
25
26
  page = s.get(url)
26
27
 
27
28
  # Make a BS4 object
@@ -0,0 +1,69 @@
1
+ from bs4 import BeautifulSoup
2
+ from uk_bin_collection.uk_bin_collection.common import *
3
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
4
+
5
+
6
+ # import the wonderful Beautiful Soup and the URL grabber
7
+ class CouncilClass(AbstractGetBinDataClass):
8
+ """
9
+ Concrete classes have to implement all abstract operations of the
10
+ base class. They can also override some operations with a default
11
+ implementation.
12
+ """
13
+
14
+ def parse_date(self, date_str):
15
+ months = {
16
+ "Jan": "01",
17
+ "Feb": "02",
18
+ "Mar": "03",
19
+ "Apr": "04",
20
+ "May": "05",
21
+ "Jun": "06",
22
+ "Jul": "07",
23
+ "Aug": "08",
24
+ "Sep": "09",
25
+ "Oct": "10",
26
+ "Nov": "11",
27
+ "Dec": "12",
28
+ }
29
+ day, date, month_abbr, year = date_str.split()
30
+ month = months[month_abbr]
31
+ return f"{date}/{month}/{year}"
32
+
33
+ def parse_data(self, page: str, **kwargs) -> dict:
34
+ # Make a BS4 object
35
+ soup = BeautifulSoup(page.text, features="html.parser")
36
+ soup.prettify()
37
+
38
+ # Initialize the bin data structure
39
+ bin_data = {"bins": []}
40
+
41
+ # Find the table with collection dates
42
+ table = soup.find("table", class_="my-area")
43
+
44
+ # Extract the rows containing the bin collection information
45
+ rows = table.find_all("tr")
46
+
47
+ # Loop through the rows and extract bin data
48
+ for row in rows:
49
+ cells = row.find_all("td")
50
+ if len(cells) == 2:
51
+ bin_type = cells[0].get_text(strip=True)
52
+ collection_date = cells[1].get_text(strip=True)
53
+
54
+ if "Next refuse" in bin_type:
55
+ bin_data["bins"].append(
56
+ {
57
+ "type": "refuse",
58
+ "collectionDate": self.parse_date(collection_date),
59
+ }
60
+ )
61
+ elif "Next recycling" in bin_type:
62
+ bin_data["bins"].append(
63
+ {
64
+ "type": "recycling",
65
+ "collectionDate": self.parse_date(collection_date),
66
+ }
67
+ )
68
+
69
+ return bin_data
@@ -0,0 +1,70 @@
1
+ import logging
2
+ from datetime import datetime
3
+
4
+ import requests
5
+ from bs4 import BeautifulSoup
6
+
7
+ from uk_bin_collection.uk_bin_collection.common import *
8
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
9
+
10
+ HEADERS = {
11
+ "user-agent": "Mozilla/5.0",
12
+ }
13
+
14
+
15
+ class CouncilClass(AbstractGetBinDataClass):
16
+ """
17
+ Concrete class implementing all abstract operations of the base class.
18
+ """
19
+
20
+ def get_session_variable(self, soup, id) -> str:
21
+ """Extract ASP.NET variable from the HTML."""
22
+ element = soup.find("input", {"id": id})
23
+ if element:
24
+ return element.get("value")
25
+ else:
26
+ raise ValueError(f"Unable to find element with id: {id}")
27
+
28
+ def parse_data(self, page: str, **kwargs) -> dict:
29
+ # Create a session to handle cookies and headers
30
+ session = requests.Session()
31
+ session.headers.update(HEADERS)
32
+ user_uprn = kwargs.get("uprn")
33
+ user_postcode = kwargs.get("postcode")
34
+ URL = "https://www1.swansea.gov.uk/recyclingsearch/"
35
+
36
+ # Get initial ASP.NET variables
37
+ response = session.get(URL)
38
+ response.raise_for_status()
39
+
40
+ soup = BeautifulSoup(response.text, "html.parser")
41
+
42
+ data = {
43
+ "__VIEWSTATE": self.get_session_variable(soup, "__VIEWSTATE"),
44
+ "__VIEWSTATEGENERATOR": self.get_session_variable(
45
+ soup, "__VIEWSTATEGENERATOR"
46
+ ),
47
+ "__VIEWSTATEENCRYPTED": "",
48
+ "__EVENTVALIDATION": self.get_session_variable(soup, "__EVENTVALIDATION"),
49
+ "txtRoadName": user_uprn,
50
+ "txtPostCode": user_postcode,
51
+ "btnSearch": "Search",
52
+ }
53
+
54
+ # Get the collection calendar
55
+ response = session.post(URL, data=data)
56
+ response.raise_for_status()
57
+
58
+ soup = BeautifulSoup(response.text, "html.parser")
59
+
60
+ next_refuse_date = soup.find("span", {"id": "lblNextRefuse"}).text.strip()
61
+ next_recycling_date = soup.find("span", {"id": "lblNextRecycling"}).text.strip()
62
+
63
+ bin_data = {
64
+ "bins": [
65
+ {"type": "Pink Week", "collectionDate": next_refuse_date},
66
+ {"type": "Green Week", "collectionDate": next_recycling_date},
67
+ ]
68
+ }
69
+
70
+ return bin_data
@@ -1,4 +1,5 @@
1
1
  from bs4 import BeautifulSoup
2
+
2
3
  from uk_bin_collection.uk_bin_collection.common import *
3
4
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
4
5
 
@@ -0,0 +1,140 @@
1
+ import logging
2
+ import time
3
+
4
+ from bs4 import BeautifulSoup
5
+ from selenium.webdriver.common.by import By
6
+ from selenium.webdriver.support import expected_conditions as EC
7
+ from selenium.webdriver.support.ui import Select
8
+ from selenium.webdriver.support.wait import WebDriverWait
9
+
10
+ from uk_bin_collection.uk_bin_collection.common import *
11
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
12
+
13
+ # Set up logging
14
+ logging.basicConfig(
15
+ level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
16
+ )
17
+
18
+
19
+ class CouncilClass(AbstractGetBinDataClass):
20
+ def parse_data(self, page: str, **kwargs) -> dict:
21
+ driver = None
22
+ try:
23
+ data = {"bins": []}
24
+ collections = []
25
+ user_uprn = kwargs.get("uprn")
26
+ user_postcode = kwargs.get("postcode")
27
+ web_driver = kwargs.get("web_driver")
28
+ headless = kwargs.get("headless")
29
+ check_postcode(user_postcode)
30
+
31
+ # Create Selenium webdriver
32
+ driver = create_webdriver(web_driver, headless, None, __name__)
33
+ if headless:
34
+ driver.set_window_size(1920, 1080)
35
+
36
+ driver.get(
37
+ "https://my.threerivers.gov.uk/en/AchieveForms/?mode=fill&consentMessage=yes&form_uri=sandbox-publish://AF-Process-52df96e3-992a-4b39-bba3-06cfaabcb42b/AF-Stage-01ee28aa-1584-442c-8d1f-119b6e27114a/definition.json&process=1&process_uri=sandbox-processes://AF-Process-52df96e3-992a-4b39-bba3-06cfaabcb42b&process_id=AF-Process-52df96e3-992a-4b39-bba3-06cfaabcb42b&noLoginPrompt=1"
38
+ )
39
+ wait = WebDriverWait(driver, 60)
40
+
41
+ def click_element(by, value):
42
+ element = wait.until(EC.element_to_be_clickable((by, value)))
43
+ driver.execute_script("arguments[0].scrollIntoView();", element)
44
+ element.click()
45
+
46
+ click_element(By.XPATH, "//button[contains(text(), 'Continue')]")
47
+
48
+ logging.info("Switching to iframe")
49
+ iframe_presence = wait.until(
50
+ EC.presence_of_element_located((By.ID, "fillform-frame-1"))
51
+ )
52
+ driver.switch_to.frame(iframe_presence)
53
+
54
+ logging.info("Entering postcode")
55
+ input_element_postcode = wait.until(
56
+ EC.presence_of_element_located(
57
+ (By.XPATH, '//input[@id="postcode_search"]')
58
+ )
59
+ )
60
+ input_element_postcode.send_keys(user_postcode)
61
+
62
+ logging.info("Selecting address")
63
+ dropdown = wait.until(EC.element_to_be_clickable((By.ID, "chooseAddress")))
64
+ dropdown_options = wait.until(
65
+ EC.presence_of_element_located((By.CLASS_NAME, "lookup-option"))
66
+ )
67
+ drop_down_values = Select(dropdown)
68
+ option_element = wait.until(
69
+ EC.presence_of_element_located(
70
+ (By.CSS_SELECTOR, f'option.lookup-option[value="{str(user_uprn)}"]')
71
+ )
72
+ )
73
+
74
+ driver.execute_script("arguments[0].scrollIntoView();", option_element)
75
+ drop_down_values.select_by_value(str(user_uprn))
76
+
77
+ option_element = wait.until(
78
+ EC.presence_of_element_located(
79
+ (By.XPATH, '//div[@class="fieldContent"][1]')
80
+ )
81
+ )
82
+
83
+ time.sleep(2)
84
+
85
+ click_element(By.XPATH, "//button/span[contains(text(), 'Next')]")
86
+
87
+ logging.info("Waiting for bin schedule")
88
+ bin_results = wait.until(
89
+ EC.presence_of_element_located(
90
+ (By.XPATH, "//div[@data-field-name='subCollectionCalendar']//table")
91
+ )
92
+ )
93
+
94
+ logging.info("Extracting bin collection data")
95
+ soup = BeautifulSoup(driver.page_source, features="html.parser")
96
+ bin_cards = soup.find_all(
97
+ "div", {"data-field-name": "subCollectionCalendar"}
98
+ )
99
+
100
+ bins = []
101
+
102
+ for bin_card in bin_cards:
103
+ # Try to find the table within the bin_card
104
+ table = bin_card.find(
105
+ "table",
106
+ {
107
+ "class": "repeatable-table table table-responsive table-hover table-condensed"
108
+ },
109
+ )
110
+
111
+ if table:
112
+ print("Table found")
113
+ rows = table.select("tr.repeatable-value")
114
+ for row in rows:
115
+ cols = row.find_all("td", class_="value")
116
+ if len(cols) >= 3: # Ensure there are enough columns
117
+ bin_type = cols[1].find_all("span")[-1].text.strip()
118
+ collection_date = (
119
+ cols[2]
120
+ .find_all("span")[-1]
121
+ .text.strip()
122
+ .replace("-", "/")
123
+ )
124
+ bins.append(
125
+ {"type": bin_type, "collectionDate": collection_date}
126
+ )
127
+ else:
128
+ print("Table not found within bin_card")
129
+
130
+ bin_data = {"bins": bins}
131
+ logging.info("Data extraction complete")
132
+ return bin_data
133
+
134
+ except Exception as e:
135
+ logging.error(f"An error occurred: {e}")
136
+ raise
137
+
138
+ finally:
139
+ if driver:
140
+ driver.quit()
@@ -0,0 +1,117 @@
1
+ import logging
2
+ import pickle
3
+ import time
4
+
5
+ import requests
6
+ from bs4 import BeautifulSoup
7
+ from selenium import webdriver
8
+ from selenium.webdriver.common.by import By
9
+ from selenium.webdriver.common.keys import Keys
10
+ from selenium.webdriver.support import expected_conditions as EC
11
+ from selenium.webdriver.support.ui import Select
12
+ from selenium.webdriver.support.wait import WebDriverWait
13
+ from uk_bin_collection.uk_bin_collection.common import *
14
+
15
+ from uk_bin_collection.uk_bin_collection.common import *
16
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
17
+
18
+ # Set up logging
19
+ logging.basicConfig(
20
+ level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
21
+ )
22
+
23
+
24
+ class CouncilClass(AbstractGetBinDataClass):
25
+
26
+ def parse_data(self, page: str, **kwargs) -> dict:
27
+ driver = None
28
+ try:
29
+ user_paon = kwargs.get("paon")
30
+ user_postcode = kwargs.get("postcode")
31
+ web_driver = kwargs.get("web_driver")
32
+ headless = kwargs.get("headless")
33
+ check_postcode(user_postcode)
34
+ url = "https://bins.uttlesford.gov.uk/"
35
+
36
+ # Get session cookies using requests
37
+
38
+ user_agent = """general.useragent.override", "userAgent=Mozilla/5.0
39
+ (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like
40
+ Gecko) CriOS/101.0.4951.44 Mobile/15E148 Safari/604.1"""
41
+
42
+ # Create Selenium webdriver
43
+ driver = create_webdriver(web_driver, headless, user_agent, __name__)
44
+
45
+ # Navigate to the page first
46
+ driver.get(url)
47
+
48
+ wait = WebDriverWait(driver, 60)
49
+
50
+ logging.info("Entering postcode")
51
+ input_element_postcode = wait.until(
52
+ EC.presence_of_element_located((By.XPATH, '//input[@id="postcode"]'))
53
+ )
54
+
55
+ input_element_postcode.send_keys(user_postcode)
56
+ input_element_postcode.send_keys(Keys.ENTER)
57
+
58
+ logging.info("Searching for postcode")
59
+ input_element_postcode_dd = wait.until(
60
+ EC.element_to_be_clickable((By.XPATH, '//select[@id="housenn"]'))
61
+ )
62
+
63
+ logging.info("Selecting address")
64
+ drop_down_values = Select(input_element_postcode_dd)
65
+
66
+ drop_down_values.select_by_visible_text(str(user_paon))
67
+
68
+ input_element_address_btn = wait.until(
69
+ EC.element_to_be_clickable(
70
+ (By.XPATH, '//input[@alt="View your waste collection days"]')
71
+ )
72
+ )
73
+
74
+ input_element_address_btn.click()
75
+
76
+ logging.info("Waiting for bin collection page")
77
+ h3_element = wait.until(
78
+ EC.presence_of_element_located(
79
+ (By.XPATH, "//h3[contains(text(), 'Future Collection Dates')]")
80
+ )
81
+ )
82
+
83
+ logging.info("Extracting bin collection data")
84
+ soup = BeautifulSoup(driver.page_source, features="html.parser")
85
+
86
+ bins = []
87
+ rows = soup.select("div.wrap table tbody tr")
88
+
89
+ for row in rows:
90
+ cols = row.find_all("td")
91
+ if len(cols) == 2:
92
+ bin_types = [img["alt"] for img in cols[0].find_all("img")]
93
+ collection_date_str = cols[1].text
94
+ collection_date = datetime.strptime(
95
+ collection_date_str, "%A %dth %B"
96
+ )
97
+ collection_date = collection_date.replace(
98
+ year=2024
99
+ ) # Assuming the year is 2024
100
+ collection_date_str = collection_date.strftime("%d/%m/%Y")
101
+
102
+ for bin_type in bin_types:
103
+ bins.append(
104
+ {"type": bin_type, "collectionDate": collection_date_str}
105
+ )
106
+
107
+ bin_data = {"bins": bins}
108
+
109
+ return bin_data
110
+
111
+ except Exception as e:
112
+ logging.error(f"An error occurred: {e}")
113
+ raise
114
+
115
+ finally:
116
+ if driver:
117
+ driver.quit()
@@ -2,6 +2,7 @@ from datetime import date, datetime
2
2
 
3
3
  import requests
4
4
  from bs4 import BeautifulSoup
5
+
5
6
  from uk_bin_collection.uk_bin_collection.common import *
6
7
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
7
8
 
@@ -24,7 +25,7 @@ class CouncilClass(AbstractGetBinDataClass):
24
25
  # WBC use a url parameter called "Track" that's generated when you start a form session.
25
26
  # So first off, open the page, find the page link and copy it with the Track
26
27
  start_url = "https://wav-wrp.whitespacews.com/"
27
- s = requests.session()
28
+ s = requests.Session()
28
29
  response = s.get(start_url)
29
30
  soup = BeautifulSoup(response.content, features="html.parser")
30
31
  soup.prettify()
@@ -2,6 +2,7 @@ from datetime import datetime
2
2
 
3
3
  import requests
4
4
  from bs4 import BeautifulSoup
5
+
5
6
  from uk_bin_collection.uk_bin_collection.common import *
6
7
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
7
8
 
@@ -27,7 +28,7 @@ class CouncilClass(AbstractGetBinDataClass):
27
28
 
28
29
  # Start a new session to walk through the form
29
30
  requests.packages.urllib3.disable_warnings()
30
- s = requests.session()
31
+ s = requests.Session()
31
32
 
32
33
  # Get our initial session running
33
34
  response = s.get("https://apps.wigan.gov.uk/MyNeighbourhood/")
@@ -3,6 +3,7 @@ from urllib.parse import urlparse
3
3
 
4
4
  import requests
5
5
  from bs4 import BeautifulSoup
6
+
6
7
  from uk_bin_collection.uk_bin_collection.common import *
7
8
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
8
9
 
@@ -25,7 +26,7 @@ class CouncilClass(AbstractGetBinDataClass):
25
26
  data = {"bins": []}
26
27
 
27
28
  requests.packages.urllib3.disable_warnings()
28
- s = requests.session()
29
+ s = requests.Session()
29
30
  # Form start
30
31
  headers = {
31
32
  "authority": "my.rbwm.gov.uk",
@@ -1,5 +1,7 @@
1
- from bs4 import BeautifulSoup
2
1
  import urllib
2
+
3
+ from bs4 import BeautifulSoup
4
+
3
5
  from uk_bin_collection.uk_bin_collection.common import *
4
6
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
5
7
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uk_bin_collection
3
- Version: 0.79.0
3
+ Version: 0.80.0
4
4
  Summary: Python Lib to collect UK Bin Data
5
5
  Author: Robert Bradley
6
6
  Author-email: robbrad182@gmail.com
@@ -2,14 +2,14 @@ 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=eVZzMAByRNVnh8dc0G4QjErrElo5SkJiX0fujKVsw5g,57171
5
+ uk_bin_collection/tests/input.json,sha256=-t4WOCeYWUchkdm32IFhOJbufu0rP9vjwlzR43KLw3U,58920
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=zDLF5UUBp2n5S3ZlJod7AmYHt92TYQMMhHbX1keNn8U,3424
9
9
  uk_bin_collection/tests/test_collect_data.py,sha256=C5w1qfz_1CU37_T7UPdBk3nisMLobIeVHNl6EXrgfrQ,3316
10
10
  uk_bin_collection/tests/test_common_functions.py,sha256=IvTNmuFKm9u5j2A9PumMB6eScQS165sPknFakc0l-eg,11190
11
11
  uk_bin_collection/uk_bin_collection/collect_data.py,sha256=txdtYoPgWDHLPohGz_Wu9OLXOr8TpXyuIGn0WnsFbZQ,4383
12
- uk_bin_collection/uk_bin_collection/common.py,sha256=eo1hGsVMeWLBmb1EZG_1J1Z6TMZhxRkdOuzMdGoA7UU,9200
12
+ uk_bin_collection/uk_bin_collection/common.py,sha256=ZvylERlKexeHtqBRb2_fZhYxC8aoEpUtcGo0dzJnWUo,9837
13
13
  uk_bin_collection/uk_bin_collection/councils/AdurAndWorthingCouncils.py,sha256=ppbrmm-MzB1wOulK--CU_0j4P-djNf3ozMhHnmQFqLo,1511
14
14
  uk_bin_collection/uk_bin_collection/councils/ArunCouncil.py,sha256=yfhthv9nuogP19VOZ3TYQrq51qqjiCZcSel4sXhiKjs,4012
15
15
  uk_bin_collection/uk_bin_collection/councils/AylesburyValeCouncil.py,sha256=LouqjspEMt1TkOGqWHs2zkxwOETIy3n7p64uKIlAgUg,2401
@@ -19,15 +19,15 @@ uk_bin_collection/uk_bin_collection/councils/BarnsleyMBCouncil.py,sha256=MgF_7Xy
19
19
  uk_bin_collection/uk_bin_collection/councils/BasingstokeCouncil.py,sha256=VPWGljnH4C3q8qs5ZmCtqjNjgWQvviALzjk00q3EZeQ,2632
20
20
  uk_bin_collection/uk_bin_collection/councils/BathAndNorthEastSomersetCouncil.py,sha256=N_TPiIv8VBzN3rY0p3JtLlxSEru-6k1wW4UNIhN5X1M,3709
21
21
  uk_bin_collection/uk_bin_collection/councils/BedfordBoroughCouncil.py,sha256=CvGB7w9HMn7XyEtwfd9MWZE_HlZ75pDcaKMsQJz0xhk,1669
22
- uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py,sha256=MbjOgQDJRSVXe1OW_0QuDosk9TIvoibIS29WwYxVTC8,2548
22
+ uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py,sha256=U1HOr9YLMAlFoZysfw5n04E0bVuCliO5Yj1FMiiwcHA,2549
23
23
  uk_bin_collection/uk_bin_collection/councils/BexleyCouncil.py,sha256=9MrbpfR17R6DYjDrItQL3CPF7ie1SJkaoNbwQumPgIQ,5399
24
- uk_bin_collection/uk_bin_collection/councils/BirminghamCityCouncil.py,sha256=wIJgp7gjUL2zVALZNEz0YapDpvAXmriOswE03EqH49o,4130
24
+ uk_bin_collection/uk_bin_collection/councils/BirminghamCityCouncil.py,sha256=x1LZiPn2C6JMHnj-R9cyrtUMnFb5o-kKtZK4sNuf6hY,4131
25
25
  uk_bin_collection/uk_bin_collection/councils/BlackburnCouncil.py,sha256=jHbCK8sL09vdmdP7Xnh8lIrU5AHTnJLEZfOLephPvWg,4090
26
26
  uk_bin_collection/uk_bin_collection/councils/BoltonCouncil.py,sha256=MrSzfK3EukRVasgP1nxAqg3lTkZzlAkDLJ2Nu5dJJ-0,4023
27
- uk_bin_collection/uk_bin_collection/councils/BracknellForestCouncil.py,sha256=35P9f4j6LpteYMaUhpE-NdfzupTRg0wEQyojH1n-OUw,9015
27
+ uk_bin_collection/uk_bin_collection/councils/BracknellForestCouncil.py,sha256=Llo1rULaAZ8rChVYZqXFFLo7CN6vbT0ULUJD6ActouY,9015
28
28
  uk_bin_collection/uk_bin_collection/councils/BradfordMDC.py,sha256=9EDTdhbGb8BQ5PLEw9eiWZ3BrS0TtoFpYOHQU44wc2k,4308
29
29
  uk_bin_collection/uk_bin_collection/councils/BrightonandHoveCityCouncil.py,sha256=k6qt4cds-Ejd97Z-__pw2BYvGVbFdc9SUfF73PPrTNA,5823
30
- uk_bin_collection/uk_bin_collection/councils/BristolCityCouncil.py,sha256=VT7k0AzcWL_h6E7Yr84NXs-FJ7qbYed7giR4HClHYE0,5575
30
+ uk_bin_collection/uk_bin_collection/councils/BristolCityCouncil.py,sha256=kJmmDJz_kQ45DHmG7ocrUpNJonEn0kuXYEDQyZaf9ks,5576
31
31
  uk_bin_collection/uk_bin_collection/councils/BromleyBoroughCouncil.py,sha256=h92cM4SQwqFrBd9snnZuRgFjnftyZEoS7XfG3OUWa4k,4758
32
32
  uk_bin_collection/uk_bin_collection/councils/BroxtoweBoroughCouncil.py,sha256=-Facq-ToQkcWUePpKBwq90LZUFxgUSydNL2sYaLX4yw,4473
33
33
  uk_bin_collection/uk_bin_collection/councils/BuckinghamshireCouncil.py,sha256=rMc3lwu8UivbUZBiRedDhT8nBQQ83tvinc0QtmFjJNI,3184
@@ -43,15 +43,15 @@ uk_bin_collection/uk_bin_collection/councils/CheshireWestAndChesterCouncil.py,sh
43
43
  uk_bin_collection/uk_bin_collection/councils/ChichesterDistrictCouncil.py,sha256=HxrLcJves7ZsE8FbooymeecTUmScY4R7Oi71vwCePPo,4118
44
44
  uk_bin_collection/uk_bin_collection/councils/ChorleyCouncil.py,sha256=M7HjuUaFq8aSnOf_9m1QS4MmPPMmPhF3mLHSrfDPtV0,5194
45
45
  uk_bin_collection/uk_bin_collection/councils/ConwyCountyBorough.py,sha256=el75qv2QyfWZBU09tJLvD8vLQZ9pCg73u1NBFs6ybo8,1034
46
- uk_bin_collection/uk_bin_collection/councils/CrawleyBoroughCouncil.py,sha256=rZIRiXp0rOkc20M9DpgxuhbykACip7LNjpn6ytDsnwk,2361
47
- uk_bin_collection/uk_bin_collection/councils/CroydonCouncil.py,sha256=vaMbSKPmKZ2xzXuviTbENhAS20qzlIvdM3EpdHb505M,11593
48
- uk_bin_collection/uk_bin_collection/councils/DartfordBoroughCouncil.py,sha256=Tb4h0UBbVPo7nNFIzU3yj0aZsAuXnDPot3ORr2lnpv4,1603
46
+ uk_bin_collection/uk_bin_collection/councils/CrawleyBoroughCouncil.py,sha256=_BEKZAjlS5Ad5DjyxqAEFSLn8F-KYox0zmn4BXaAD6A,2367
47
+ uk_bin_collection/uk_bin_collection/councils/CroydonCouncil.py,sha256=QJH27plySbbmoNcLNUXq-hUiFmZ5zBlRS5mzOJgWSK8,11594
48
+ uk_bin_collection/uk_bin_collection/councils/DartfordBoroughCouncil.py,sha256=SPirUUoweMwX5Txtsr0ocdcFtKxCQ9LhzTTJN20tM4w,1550
49
49
  uk_bin_collection/uk_bin_collection/councils/DerbyshireDalesDistrictCouncil.py,sha256=MQC1-jXezXczrxTcvPQvkpGgyyAbzSKlX38WsmftHak,4007
50
50
  uk_bin_collection/uk_bin_collection/councils/DoncasterCouncil.py,sha256=b7pxoToXu6dBBYXsXmlwfPXE8BjHxt0hjCOBNlNgvX8,3118
51
51
  uk_bin_collection/uk_bin_collection/councils/DorsetCouncil.py,sha256=sdSR5ryOSWHtK_0OKJ75LGOvMiUAnQCc3uwT3xfqZ_0,2304
52
52
  uk_bin_collection/uk_bin_collection/councils/DoverDistrictCouncil.py,sha256=3Zgap6kaVpDXtRfBKEL1Ms6eb0iFIipYKNtOq3Hrdd4,1891
53
53
  uk_bin_collection/uk_bin_collection/councils/DurhamCouncil.py,sha256=6O8bNsQVYQbrCYQE9Rp0c_rtkcXuxR3s9J6jn4MK4_s,1695
54
- uk_bin_collection/uk_bin_collection/councils/EastCambridgeshireCouncil.py,sha256=_iSifwbdSFhnuhdf4U42xMQjkWJUalTytKPV-QGSNYU,1500
54
+ uk_bin_collection/uk_bin_collection/councils/EastCambridgeshireCouncil.py,sha256=aYUVE5QqTxdj8FHhCB4EiFVDJahWJD9Pq0d1upBEvXg,1501
55
55
  uk_bin_collection/uk_bin_collection/councils/EastDevonDC.py,sha256=U0VwSNIldMv5nUoiXtFgjbE0m6Kb-8W2WZQGVCNF_WI,3261
56
56
  uk_bin_collection/uk_bin_collection/councils/EastLindseyDistrictCouncil.py,sha256=o_HPSFhb2ybmwv32_7T7CO1f2mGDkYCNPfaM5xz6bUI,4356
57
57
  uk_bin_collection/uk_bin_collection/councils/EastRidingCouncil.py,sha256=CsYdkmL-8Ty-Kz7uNdlnJnhiDMgOPah_swYgSKbaFqA,5218
@@ -77,15 +77,15 @@ uk_bin_collection/uk_bin_collection/councils/HuntingdonDistrictCouncil.py,sha256
77
77
  uk_bin_collection/uk_bin_collection/councils/KingstonUponThamesCouncil.py,sha256=iZ7njIxccCGBhUUWWd9Azh7cxUAKaofebCm3lo-TuxA,3543
78
78
  uk_bin_collection/uk_bin_collection/councils/KirkleesCouncil.py,sha256=gtAtM6FappSZ0-BKid7_pnSrnqPPjHn_UYWqMg9wQlM,4499
79
79
  uk_bin_collection/uk_bin_collection/councils/KnowsleyMBCouncil.py,sha256=VdlWDESoHfr_X0r8-UMaLMUQhKZOa2BnpVPkX-1u3EQ,5605
80
- uk_bin_collection/uk_bin_collection/councils/LancasterCityCouncil.py,sha256=_wOByXM_IN1jSkeQq76kdPXkndDEO49_gqQiRSe74do,2535
80
+ uk_bin_collection/uk_bin_collection/councils/LancasterCityCouncil.py,sha256=FmHT6oyD4BwWuhxA80PHnGA7HPrLuyjP_54Cg8hT6k4,2537
81
81
  uk_bin_collection/uk_bin_collection/councils/LeedsCityCouncil.py,sha256=iSZApZ9oSfSatQ6dAxmykSfti91jGuY6n2BwEkVMOiU,5144
82
- uk_bin_collection/uk_bin_collection/councils/LisburnCastlereaghCityCouncil.py,sha256=SChaWQkoOpwQ9W27vK3RMHGEyfz36UQQRbT7qJrRtxQ,3308
82
+ uk_bin_collection/uk_bin_collection/councils/LisburnCastlereaghCityCouncil.py,sha256=vSOzdEwp9ZeUhed7E3eVv9ReD-2XgbSkpyAbVnfc-Gk,3309
83
83
  uk_bin_collection/uk_bin_collection/councils/LiverpoolCityCouncil.py,sha256=n17OqZrCGrPrnxGUfHc-RGkb4oJ9Bx6uUWiLdzxfQlY,2587
84
84
  uk_bin_collection/uk_bin_collection/councils/LondonBoroughHounslow.py,sha256=UOeiOxGMvVMm2UFaqjmQpm7vxzqJNSSN8LM9lAUjs2c,3021
85
85
  uk_bin_collection/uk_bin_collection/councils/LondonBoroughRedbridge.py,sha256=A_6Sis5hsF53Th04KeadHRasGbpAm6aoaWJ6X8eC4Y8,6604
86
86
  uk_bin_collection/uk_bin_collection/councils/MaldonDistrictCouncil.py,sha256=PMVt2XFggttPmbWyrBrHJ-W6R_6-0ux1BkY1kj1IKzg,1997
87
87
  uk_bin_collection/uk_bin_collection/councils/MalvernHillsDC.py,sha256=iQG0EkX2npBicvsGKQRYyBGSBvKVUbKvUvvwrC9xV1A,2100
88
- uk_bin_collection/uk_bin_collection/councils/ManchesterCityCouncil.py,sha256=ZgBMja1jvuj1nWmHHAvrf0FH3_HuysPR7eEved1C_hY,4919
88
+ uk_bin_collection/uk_bin_collection/councils/ManchesterCityCouncil.py,sha256=RFXC4bRDYZgeFIzfsOWZXoBEWV7mNiM0HejhcPsP3a0,4920
89
89
  uk_bin_collection/uk_bin_collection/councils/MansfieldDistrictCouncil.py,sha256=F5AiTxImrnjE1k3ry96bfstOf5XSNBJS_4qqmymmh3w,1386
90
90
  uk_bin_collection/uk_bin_collection/councils/MertonCouncil.py,sha256=3Y2Un4xXo1sCcMsudynODSzocV_mMofWkX2JqONDb5o,1997
91
91
  uk_bin_collection/uk_bin_collection/councils/MidAndEastAntrimBoroughCouncil.py,sha256=oOWwU5FSgGej2Mv7FQ66N-EzS5nZgmGsd0WnfLWUc1I,5238
@@ -93,10 +93,11 @@ uk_bin_collection/uk_bin_collection/councils/MidSussexDistrictCouncil.py,sha256=
93
93
  uk_bin_collection/uk_bin_collection/councils/MiltonKeynesCityCouncil.py,sha256=3olsWa77L34vz-c7NgeGK9xmNuR4Ws_oAk5D4UpIkPw,2005
94
94
  uk_bin_collection/uk_bin_collection/councils/MoleValleyDistrictCouncil.py,sha256=54-autRRGAM4pBxlqmUE6g825rmUF-gRqrcgHL_lkIk,3994
95
95
  uk_bin_collection/uk_bin_collection/councils/NeathPortTalbotCouncil.py,sha256=2DJ0gK385CWTdJzWyDdmNBTTrwX6F5YbIXg7di2oXDQ,5506
96
+ uk_bin_collection/uk_bin_collection/councils/NewForestCouncil.py,sha256=ylTn9KmWITtaO9_Z8kJCN2w2ALfhrfGt3SeJ78lgw7M,5391
96
97
  uk_bin_collection/uk_bin_collection/councils/NewarkAndSherwoodDC.py,sha256=lAleYfCGUWCKOi7Ye_cjgfpI3pWwTcFctlYmh0hjebM,2140
97
98
  uk_bin_collection/uk_bin_collection/councils/NewcastleCityCouncil.py,sha256=eJMX10CG9QO7FRhHSmUDL-jO_44qoK3_1ztNTAXhkbw,2085
98
99
  uk_bin_collection/uk_bin_collection/councils/NewhamCouncil.py,sha256=klFqr2Km1BuQ4wERmjbXZzOvN1N0jnVmhTGRSVzVOaU,2086
99
- uk_bin_collection/uk_bin_collection/councils/NewportCityCouncil.py,sha256=dPeDmxNT1QT6C_V30PZFHypqQrvppzE3qF12a5gF94E,8479
100
+ uk_bin_collection/uk_bin_collection/councils/NewportCityCouncil.py,sha256=dAcl5P97bttl2xCPvxof1a18kmqOrMmiElgtn3Ej7zs,8480
100
101
  uk_bin_collection/uk_bin_collection/councils/NorthEastDerbyshireDistrictCouncil.py,sha256=bps_uCFAeUHQla7AE5lZOv6sUkUz1fb6zduZdAcYMuw,4651
101
102
  uk_bin_collection/uk_bin_collection/councils/NorthEastLincs.py,sha256=fYf438VZIaOaqPSwdTTWVjFTdrI0jGfFsxVzOc-QdkA,1817
102
103
  uk_bin_collection/uk_bin_collection/councils/NorthKestevenDistrictCouncil.py,sha256=vYOCerJXr9LTP6F2wm4vpYNYbQaWNZ6yfHEQ33N_hTw,1681
@@ -105,7 +106,7 @@ uk_bin_collection/uk_bin_collection/councils/NorthLincolnshireCouncil.py,sha256=
105
106
  uk_bin_collection/uk_bin_collection/councils/NorthNorfolkDistrictCouncil.py,sha256=VV_zqVZYv8ekXcUHhrBlTX_W5qLYE9IA3mT2xmrZqoI,4315
106
107
  uk_bin_collection/uk_bin_collection/councils/NorthNorthamptonshireCouncil.py,sha256=kcMN-5GBjYDM9F1BKfHoYeydub8SuDxHamJbSvJRZ68,2337
107
108
  uk_bin_collection/uk_bin_collection/councils/NorthSomersetCouncil.py,sha256=EbFVnPYZIOkru5_Y75kjljM3Cr3HIJgP-SU6hxgf6tk,2754
108
- uk_bin_collection/uk_bin_collection/councils/NorthTynesideCouncil.py,sha256=h2VzxJot0JjHX5IacfRBvZTxEBu5bdAlw_4CYnSXztM,11352
109
+ uk_bin_collection/uk_bin_collection/councils/NorthTynesideCouncil.py,sha256=waH6_PyJaiEF-v9HR3C_aUdiPTcdHlxfAuuuKBsvkII,11353
109
110
  uk_bin_collection/uk_bin_collection/councils/NorthWestLeicestershire.py,sha256=gJj0dyQc5QUefqusKGk2LLXfWbG5tlEXUOh8KAPh3RI,4584
110
111
  uk_bin_collection/uk_bin_collection/councils/NorthYorkshire.py,sha256=2wTrr3VrZDp9-YtDPmWd649gXeWH4hbm2-Hw8Vau5Xs,1933
111
112
  uk_bin_collection/uk_bin_collection/councils/NorthumberlandCouncil.py,sha256=KEFsxEvQ159fkuFo-fza67YCnnCZ5ElwE80zTrqDEWI,4990
@@ -127,9 +128,9 @@ uk_bin_collection/uk_bin_collection/councils/SevenoaksDistrictCouncil.py,sha256=
127
128
  uk_bin_collection/uk_bin_collection/councils/SheffieldCityCouncil.py,sha256=9g9AeiackoWyej9EVlKUzywzAtMuBVD0f93ZryAUha8,2016
128
129
  uk_bin_collection/uk_bin_collection/councils/ShropshireCouncil.py,sha256=6OIEhJmv-zLJiEo8WaJePA7JuhNRGkh2WohFLhzN8Kk,1477
129
130
  uk_bin_collection/uk_bin_collection/councils/SolihullCouncil.py,sha256=gbTHjbdV46evGfLfF8rxVMQIgNZD-XPHgZeuyje7kGY,1609
130
- uk_bin_collection/uk_bin_collection/councils/SomersetCouncil.py,sha256=zsbpknHcIWK1MVW0FreIcaEienbWs3c5q32KKGQl1IE,8479
131
+ uk_bin_collection/uk_bin_collection/councils/SomersetCouncil.py,sha256=CZJnkCGn4-yH31HH5_ix-8V2_vsjGuKYxgzAPGZdSAw,8480
131
132
  uk_bin_collection/uk_bin_collection/councils/SouthAyrshireCouncil.py,sha256=03eapeXwxneKI4ccKPSHoviIbhmV1m90I-0WQ_s3KsY,2722
132
- uk_bin_collection/uk_bin_collection/councils/SouthCambridgeshireCouncil.py,sha256=2DvHgy5EuopGyY4EV8us8B4BN82qt1N8RWMJszjenHc,2307
133
+ uk_bin_collection/uk_bin_collection/councils/SouthCambridgeshireCouncil.py,sha256=xGSMcikxjS4UzqKs0X50LJKmn09C-XAAs98SPhNZgkQ,2308
133
134
  uk_bin_collection/uk_bin_collection/councils/SouthGloucestershireCouncil.py,sha256=ytQot0J7i6DTJo6hb9koTB1UpXLATKVeRU4FBF9kHRo,2412
134
135
  uk_bin_collection/uk_bin_collection/councils/SouthKestevenDistrictCouncil.py,sha256=AgycOW-UIAm5_c8QondfKL0n4wUA4cbaN_Jp0e8g494,5587
135
136
  uk_bin_collection/uk_bin_collection/councils/SouthLanarkshireCouncil.py,sha256=fj-eZI0yrvQVCv8GvhcovZ3b9bV6Xv_ws3IunWjnv4U,3126
@@ -137,7 +138,8 @@ uk_bin_collection/uk_bin_collection/councils/SouthNorfolkCouncil.py,sha256=ThO-o
137
138
  uk_bin_collection/uk_bin_collection/councils/SouthOxfordshireCouncil.py,sha256=zW4bN3hcqNoK_Y0-vPpuZs3K0LTPvApu6_v9K-D7WjE,3879
138
139
  uk_bin_collection/uk_bin_collection/councils/SouthTynesideCouncil.py,sha256=dxXGrJfg_fn2IPTBgq6Duwy0WY8GYLafMuisaCjOnbs,3426
139
140
  uk_bin_collection/uk_bin_collection/councils/StAlbansCityAndDistrictCouncil.py,sha256=mPZz6Za6kTSkrfHnj0OfwtnpRYR1dKvxbuFEKnWsiL8,1451
140
- uk_bin_collection/uk_bin_collection/councils/StHelensBC.py,sha256=E3kxbreq1BAOegT7T85Mz88rBvAsxcPNn96nSJDETbI,2068
141
+ uk_bin_collection/uk_bin_collection/councils/StHelensBC.py,sha256=c7ZM8gnUkKdz9GYIhFLzTtwN0KAoMEKomTWDVbtJIpM,2069
142
+ uk_bin_collection/uk_bin_collection/councils/StaffordBoroughCouncil.py,sha256=9Qj4HJI7Dbiqb2mVSG2UtkBe27Y7wvQ5SYFTwGzJ5g0,2292
141
143
  uk_bin_collection/uk_bin_collection/councils/StaffordshireMoorlandsDistrictCouncil.py,sha256=_N8Cg26EbTaKp0RsWvQuELVcZDHbT2BlD2LW8qhkS_Q,4361
142
144
  uk_bin_collection/uk_bin_collection/councils/StockportBoroughCouncil.py,sha256=v0HmioNVRoU1-9OnLJl2V3M5pVR1aVu1BgOLHFR1Sf4,1429
143
145
  uk_bin_collection/uk_bin_collection/councils/StokeOnTrentCityCouncil.py,sha256=KM0EgWeO7mk8lkozX0RCTfMchXdjrfBqIjCiOtB09aM,2884
@@ -145,20 +147,23 @@ uk_bin_collection/uk_bin_collection/councils/StratfordUponAvonCouncil.py,sha256=
145
147
  uk_bin_collection/uk_bin_collection/councils/StroudDistrictCouncil.py,sha256=9bYWppi7ViLGHL4VEg--nFn28MLYJYbiEntull1uZxU,3561
146
148
  uk_bin_collection/uk_bin_collection/councils/SunderlandCityCouncil.py,sha256=4DnKyyu56_AwuchD6_oL1dvpDStMvkkxQtYN79rUKOs,3825
147
149
  uk_bin_collection/uk_bin_collection/councils/SwaleBoroughCouncil.py,sha256=CCAjclhkCxwf_MkdrIif7MZpLfV5SPy7hyM7BE0TRPc,2048
150
+ uk_bin_collection/uk_bin_collection/councils/SwanseaCouncil.py,sha256=nmVPoPhnFgVi--vczX2i4Sf3bqM5RWJuwfhioRUr5XE,2303
148
151
  uk_bin_collection/uk_bin_collection/councils/TamesideMBCouncil.py,sha256=k2TAAZG7n2S1BWVyxbE_-4-lZuzhOimCNz4yimUCOGk,1995
149
152
  uk_bin_collection/uk_bin_collection/councils/TandridgeDistrictCouncil.py,sha256=KLVvM2NNq_DQylVe5dwO2l7qPahLHg08jJGLCv1MBQ4,2324
150
153
  uk_bin_collection/uk_bin_collection/councils/TelfordAndWrekinCouncil.py,sha256=p1ZS5R4EGxbEWlRBrkGXgKwE_lkyBT-R60yKFFhVObc,1844
151
154
  uk_bin_collection/uk_bin_collection/councils/TendringDistrictCouncil.py,sha256=DJbYI8m6lIISDrK5h8V5Jo-9kGG7kr9dz7GD8St4nc8,4274
152
- uk_bin_collection/uk_bin_collection/councils/TestValleyBoroughCouncil.py,sha256=ohbndldGHqx6AXKaJLNYWpSK4umKaBU6YaWlgYhR1HI,8479
155
+ uk_bin_collection/uk_bin_collection/councils/TestValleyBoroughCouncil.py,sha256=Dtfkyrwt795W7gqFJxVGRR8t3R5WMNQZwTWJckLpZWE,8480
156
+ uk_bin_collection/uk_bin_collection/councils/ThreeRiversDistrictCouncil.py,sha256=oZSW0Y5QHdqVy2fLys4sdB13tHgeNLha9WCUqG_R-gU,5527
153
157
  uk_bin_collection/uk_bin_collection/councils/TonbridgeAndMallingBC.py,sha256=UlgnHDoi8ecav2H5-HqKNDpqW1J3RN-c___5c08_Q7I,4859
154
158
  uk_bin_collection/uk_bin_collection/councils/TorbayCouncil.py,sha256=JW_BS7wkfxFsmx6taQtPAQWdBp1AfLrxs0XRQ2XZcSw,2029
155
159
  uk_bin_collection/uk_bin_collection/councils/TorridgeDistrictCouncil.py,sha256=6gOO02pYU0cbj3LAHiBVNG4zkFMyIGbkE2jAye3KcGM,6386
160
+ uk_bin_collection/uk_bin_collection/councils/UttlesfordDistrictCouncil.py,sha256=8CvO-WgdKdvyaOf3TYc4XwME8ogAXojgB40oyGRL8Dw,4129
156
161
  uk_bin_collection/uk_bin_collection/councils/ValeofGlamorganCouncil.py,sha256=Phgb_ECiUOOkqOx6OsfsTHMCW5VQfRmOC2zgYIQhuZA,5044
157
162
  uk_bin_collection/uk_bin_collection/councils/ValeofWhiteHorseCouncil.py,sha256=5nZLbU5YVKNsJ2X_wuybrNLFAzjVAxkazu-bYP4IGXw,4292
158
163
  uk_bin_collection/uk_bin_collection/councils/WakefieldCityCouncil.py,sha256=9zW4C0WKbsDLCKvFyVYFpyvp20JbrWc4G0HzadqF8WQ,4466
159
164
  uk_bin_collection/uk_bin_collection/councils/WalthamForest.py,sha256=P7MMw0EhpRmDbbnHb25tY5_yvYuZUFwJ1br4TOv24sY,4997
160
165
  uk_bin_collection/uk_bin_collection/councils/WarwickDistrictCouncil.py,sha256=3WQrAxzYzKoV4LyOqNTp9xINVsNi1xW9t8etducGeag,1146
161
- uk_bin_collection/uk_bin_collection/councils/WaverleyBoroughCouncil.py,sha256=nhGbhcGyeULLWhpkwRC1anZbQOmZxMhC-VRHIj2ZJlY,4661
166
+ uk_bin_collection/uk_bin_collection/councils/WaverleyBoroughCouncil.py,sha256=tp9l7vdgSGRzNNG0pDfnNuFj4D2bpRJUJmAiTJ6bM0g,4662
162
167
  uk_bin_collection/uk_bin_collection/councils/WealdenDistrictCouncil.py,sha256=SvSSaLkx7iJjzypAwKkaJwegXkSsIQtUOS2V605kz1A,3368
163
168
  uk_bin_collection/uk_bin_collection/councils/WelhatCouncil.py,sha256=ikUft37dYNJghfe-_6Fskiq1JihqpLmLNj38QkKSUUA,2316
164
169
  uk_bin_collection/uk_bin_collection/councils/WestBerkshireCouncil.py,sha256=r90AIUdPgo85VuuvN_NeCDUy3NEJXdO4Ntt93yKo6qI,5110
@@ -166,17 +171,17 @@ uk_bin_collection/uk_bin_collection/councils/WestLindseyDistrictCouncil.py,sha25
166
171
  uk_bin_collection/uk_bin_collection/councils/WestLothianCouncil.py,sha256=dq0jimtARvRkZiGbVFrXXZgY-BODtz3uYZ5UKn0bf64,4114
167
172
  uk_bin_collection/uk_bin_collection/councils/WestNorthamptonshireCouncil.py,sha256=F1GeJUGND4DN_HuM6N0Elpeb0DAMm9_KeqG6qtIgZf4,1079
168
173
  uk_bin_collection/uk_bin_collection/councils/WestSuffolkCouncil.py,sha256=HMFWxM7VMhBuC7iubNGbZYEoCVWi--gRHDJMVdPPFOM,2633
169
- uk_bin_collection/uk_bin_collection/councils/WiganBoroughCouncil.py,sha256=YEbpbjkparhah4ahl6WZzI0mMHNrbKzdC6kA5gDQCUA,3745
174
+ uk_bin_collection/uk_bin_collection/councils/WiganBoroughCouncil.py,sha256=3gqFA4-BVx_In6QOu3KUNqPN4Fkn9iMlZTeopMK9p6A,3746
170
175
  uk_bin_collection/uk_bin_collection/councils/WiltshireCouncil.py,sha256=it2Oh5Kmq3lD30gAZgk2bzZPNCtJcFHyQO1NgOQtfvU,5653
171
- uk_bin_collection/uk_bin_collection/councils/WindsorAndMaidenheadCouncil.py,sha256=triYeI4IIHF6_XMokF6BGAZkx_lPAXeGyuS9DEr5UxY,5553
172
- uk_bin_collection/uk_bin_collection/councils/WokingBoroughCouncil.py,sha256=EUfFU1lNvV0Ry5CpdE2rBJ2zRfsPfi9hg0ux3wYAmzw,5202
176
+ uk_bin_collection/uk_bin_collection/councils/WindsorAndMaidenheadCouncil.py,sha256=yG5iu294q138Bvk-0IPd4pJDFsOQPDmtU5XXytxnAnA,5554
177
+ uk_bin_collection/uk_bin_collection/councils/WokingBoroughCouncil.py,sha256=hYC3LRaLM_enYs8KhSgwUB4HhnPOhmYuPDeaREysY9E,5204
173
178
  uk_bin_collection/uk_bin_collection/councils/WyreCouncil.py,sha256=zDDa7n4K_zm5PgDL08A26gD9yOOsOhuexI3x2seaBF4,3511
174
179
  uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bIdsvmoSzBjJAvTTi6yPfJa8xjJx1ys2w,1490
175
180
  uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=4s9ODGPAwPqwXc8SrTX5Wlfmizs3_58iXUtHc4Ir86o,1162
176
181
  uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
177
182
  uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=9qppF2oPkhmOoK8-ZkRIU1M6vhBh-yUCWAZEEd07iLk,5414
178
- uk_bin_collection-0.79.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
179
- uk_bin_collection-0.79.0.dist-info/METADATA,sha256=lKq0D1bGtiEW-AmeaGgM17-J2ZGVMjw0iCnioCKgNb8,12594
180
- uk_bin_collection-0.79.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
181
- uk_bin_collection-0.79.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
182
- uk_bin_collection-0.79.0.dist-info/RECORD,,
183
+ uk_bin_collection-0.80.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
184
+ uk_bin_collection-0.80.0.dist-info/METADATA,sha256=k2g8TXLix_QcBSmaj0nFopo0X_ZkiOWk7GBtY_WjmFs,12594
185
+ uk_bin_collection-0.80.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
186
+ uk_bin_collection-0.80.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
187
+ uk_bin_collection-0.80.0.dist-info/RECORD,,