uk_bin_collection 0.80.0__py3-none-any.whl → 0.81.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.
@@ -1041,13 +1041,13 @@
1041
1041
  "wiki_name": "Torridge District Council"
1042
1042
  },
1043
1043
  "UttlesfordDistrictCouncil": {
1044
- "url": "https://bins.uttlesford.gov.uk/",
1045
- "wiki_name": "UttlesfordDistrictCouncil",
1046
- "skip_get_url": true,
1044
+ "house_number": "72, Birchanger Lane",
1047
1045
  "postcode": "CM23 5QF",
1046
+ "skip_get_url": true,
1048
1047
  "uprn": "100090643434",
1049
- "house_number": "72, Birchanger Lane",
1050
- "web_driver": "http://selenium:4444"
1048
+ "url": "https://bins.uttlesford.gov.uk/",
1049
+ "web_driver": "http://selenium:4444",
1050
+ "wiki_name": "UttlesfordDistrictCouncil"
1051
1051
  },
1052
1052
  "ValeofGlamorganCouncil": {
1053
1053
  "skip_get_url": true,
@@ -1175,6 +1175,14 @@
1175
1175
  "wiki_name": "Woking Borough Council/Joint Waste Solutions",
1176
1176
  "wiki_note": "Works with all collection areas that use Joint Waste Solutions. Just use the correct URL."
1177
1177
  },
1178
+ "WychavonDistrictCouncil": {
1179
+ "url": "https://selfservice.wychavon.gov.uk/wdcroundlookup/wdc_search.jsp",
1180
+ "wiki_name": "WychavonDistrictCouncil",
1181
+ "web_driver": "http://selenium:4444",
1182
+ "skip_get_url": true,
1183
+ "postcode": "WR3 7RU",
1184
+ "uprn": "100120716273"
1185
+ },
1178
1186
  "WyreCouncil": {
1179
1187
  "postcode": "FY6 8HG",
1180
1188
  "skip_get_url": true,
@@ -1,7 +1,14 @@
1
+ from typing import Dict, List, Any, Optional
1
2
  from bs4 import BeautifulSoup
2
3
  from dateutil.relativedelta import relativedelta
3
-
4
- from uk_bin_collection.uk_bin_collection.common import *
4
+ import requests
5
+ import logging
6
+ import re
7
+ from datetime import datetime
8
+ from uk_bin_collection.common import *
9
+ from dateutil.parser import parse
10
+
11
+ from uk_bin_collection.uk_bin_collection.common import check_uprn, check_postcode
5
12
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
6
13
 
7
14
 
@@ -24,7 +31,7 @@ class CouncilClass(AbstractGetBinDataClass):
24
31
  implementation.
25
32
  """
26
33
 
27
- def get_data(self, url) -> str:
34
+ def get_data(self, url: str) -> str:
28
35
  """This method makes the request to the council
29
36
 
30
37
  Keyword arguments:
@@ -45,21 +52,27 @@ class CouncilClass(AbstractGetBinDataClass):
45
52
  full_page = session.get(url)
46
53
  return full_page
47
54
  except requests.exceptions.HTTPError as errh:
48
- _LOGGER.error(f"Http Error: {errh}")
55
+ logging.error(f"Http Error: {errh}")
49
56
  raise
50
57
  except requests.exceptions.ConnectionError as errc:
51
- _LOGGER.error(f"Error Connecting: {errc}")
58
+ logging.error(f"Error Connecting: {errc}")
52
59
  raise
53
60
  except requests.exceptions.Timeout as errt:
54
- _LOGGER.error(f"Timeout Error: {errt}")
61
+ logging.error(f"Timeout Error: {errt}")
55
62
  raise
56
63
  except requests.exceptions.RequestException as err:
57
- _LOGGER.error(f"Oops: Something Else {err}")
64
+ logging.error(f"Oops: Something Else {err}")
58
65
  raise
59
66
 
60
- def parse_data(self, page: str, **kwargs) -> dict:
61
- uprn = kwargs.get("uprn")
62
- postcode = kwargs.get("postcode")
67
+ def parse_data(self, page: str, **kwargs: Any) -> Dict[str, List[Dict[str, str]]]:
68
+ uprn: Optional[str] = kwargs.get("uprn")
69
+ postcode: Optional[str] = kwargs.get("postcode")
70
+
71
+ if uprn is None:
72
+ raise ValueError("UPRN is required and must be a non-empty string.")
73
+ if postcode is None:
74
+ raise ValueError("Postcode is required and must be a non-empty string.")
75
+
63
76
  check_uprn(uprn)
64
77
  check_postcode(postcode)
65
78
 
@@ -85,7 +98,7 @@ class CouncilClass(AbstractGetBinDataClass):
85
98
  rows = soup.find("table").find_all("tr")
86
99
 
87
100
  # Form a JSON wrapper
88
- data = {"bins": []}
101
+ data: Dict[str, List[Dict[str, str]]] = {"bins": []}
89
102
 
90
103
  # Loops the Rows
91
104
  for row in rows:
@@ -94,13 +107,13 @@ class CouncilClass(AbstractGetBinDataClass):
94
107
  bin_type = cells[0].get_text(strip=True)
95
108
  collection_next = cells[1].get_text(strip=True)
96
109
 
97
- collection_date = re.findall("\(.*?\)", collection_next)
110
+ collection_date = re.findall(r"\(.*?\)", collection_next)
98
111
 
99
112
  if len(collection_date) != 1:
100
113
  continue
101
114
 
102
115
  collection_date_obj = parse(
103
- re.sub("[()]", "", collection_date[0])
116
+ re.sub(r"[()]", "", collection_date[0])
104
117
  ).date()
105
118
 
106
119
  # since we only have the next collection day, if the parsed date is in the past,
@@ -1,17 +1,14 @@
1
1
  # This script pulls (in one hit) the data from Bromley Council Bins Data
2
2
  import datetime
3
- import time
4
3
  from datetime import datetime
5
4
 
6
5
  from bs4 import BeautifulSoup
7
6
  from dateutil.relativedelta import relativedelta
8
7
  from selenium.webdriver.common.by import By
9
- from selenium.webdriver.common.keys import Keys
10
8
  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
9
+ from selenium.webdriver.support.ui import WebDriverWait
13
10
 
14
- from uk_bin_collection.uk_bin_collection.common import *
11
+ from uk_bin_collection.uk_bin_collection.common import create_webdriver
15
12
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
16
13
 
17
14
 
@@ -28,7 +25,6 @@ class CouncilClass(AbstractGetBinDataClass):
28
25
  driver = None
29
26
  try:
30
27
  bin_data_dict = {"bins": []}
31
- collections = []
32
28
  web_driver = kwargs.get("web_driver")
33
29
  headless = kwargs.get("headless")
34
30
 
@@ -39,18 +35,14 @@ class CouncilClass(AbstractGetBinDataClass):
39
35
  driver.get(kwargs.get("url"))
40
36
 
41
37
  wait = WebDriverWait(driver, 30)
42
- results = wait.until(
38
+ wait.until(
43
39
  EC.presence_of_element_located((By.CLASS_NAME, "waste-service-image"))
44
40
  )
45
- # Search for the specific bins in the table using BS
46
- # Parse the HTML content
47
- # Find all elements with the class 'container-name' to extract bin types
41
+
48
42
  # Parse the HTML content
49
43
  soup = BeautifulSoup(driver.page_source, "html.parser")
50
- soup.prettify
51
44
 
52
45
  # Find all elements with class 'govuk-summary-list'
53
- bin_info = []
54
46
  waste_services = soup.find_all(
55
47
  "h3", class_="govuk-heading-m waste-service-name"
56
48
  )
@@ -58,7 +50,7 @@ class CouncilClass(AbstractGetBinDataClass):
58
50
  for service in waste_services:
59
51
  service_title = service.get_text(strip=True)
60
52
  next_collection = service.find_next_sibling().find(
61
- "dt", text="Next collection"
53
+ "dt", string="Next collection"
62
54
  )
63
55
 
64
56
  if next_collection:
@@ -69,8 +61,7 @@ class CouncilClass(AbstractGetBinDataClass):
69
61
  next_collection_date_parse = next_collection_date.split(",")[
70
62
  1
71
63
  ].strip()
72
- day = next_collection_date_parse.split()[0]
73
- month = next_collection_date_parse.split()[1]
64
+ day, month = next_collection_date_parse.split()[:2]
74
65
 
75
66
  # Remove the suffix (e.g., 'th', 'nd', 'rd', 'st') from the day
76
67
  if day.endswith(("th", "nd", "rd", "st")):
@@ -1,11 +1,11 @@
1
1
  import time
2
-
3
2
  import pandas as pd
4
3
  from selenium.webdriver.common.by import By
5
4
  from selenium.webdriver.common.keys import Keys
6
5
  from selenium.webdriver.support.ui import Select
6
+ from io import StringIO
7
7
 
8
- from uk_bin_collection.uk_bin_collection.common import *
8
+ from uk_bin_collection.uk_bin_collection.common import create_webdriver
9
9
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
10
10
 
11
11
 
@@ -16,7 +16,7 @@ class CouncilClass(AbstractGetBinDataClass):
16
16
  implementation.
17
17
  """
18
18
 
19
- def get_data(self, df) -> dict:
19
+ def get_data(self, df: pd.DataFrame) -> dict:
20
20
  # Create dictionary of data to be returned
21
21
  data = {"bins": []}
22
22
 
@@ -69,7 +69,7 @@ class CouncilClass(AbstractGetBinDataClass):
69
69
  time.sleep(4)
70
70
 
71
71
  # Submit address information and wait
72
- inputElement_bn = driver.find_element(
72
+ driver.find_element(
73
73
  By.ID, "COPYOFECHOCOLLECTIONDATES_ADDRESSSELECTION_NAV1_NEXT"
74
74
  ).click()
75
75
 
@@ -79,8 +79,10 @@ class CouncilClass(AbstractGetBinDataClass):
79
79
  table = driver.find_element(
80
80
  By.ID, "COPYOFECHOCOLLECTIONDATES_PAGE1_DATES2"
81
81
  ).get_attribute("outerHTML")
82
- df = pd.read_html(table, header=[1])
83
- df = df[0]
82
+
83
+ # Wrap the HTML table in a StringIO object to address the warning
84
+ table_io = StringIO(table)
85
+ df = pd.read_html(table_io, header=[1])[0]
84
86
 
85
87
  # Parse data into dict
86
88
  data = self.get_data(df)
@@ -1,6 +1,10 @@
1
1
  from bs4 import BeautifulSoup
2
+ import requests
3
+ import logging
4
+ import re
5
+ from typing import Dict, List, Any, Optional
2
6
 
3
- from uk_bin_collection.uk_bin_collection.common import *
7
+ from uk_bin_collection.uk_bin_collection.common import check_uprn
4
8
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
5
9
 
6
10
 
@@ -11,10 +15,14 @@ class CouncilClass(AbstractGetBinDataClass):
11
15
  implementation.
12
16
  """
13
17
 
14
- def parse_data(self, page: str, **kwargs) -> dict:
15
- data = {"bins": []}
18
+ def parse_data(self, page: str, **kwargs: Any) -> Dict[str, List[Dict[str, str]]]:
19
+ data: Dict[str, List[Dict[str, str]]] = {"bins": []}
20
+
21
+ uprn: Optional[str] = kwargs.get("uprn")
22
+
23
+ if uprn is None:
24
+ raise ValueError("UPRN is required and must be a non-empty string.")
16
25
 
17
- uprn = kwargs.get("uprn")
18
26
  check_uprn(uprn) # Assuming check_uprn() raises an exception if UPRN is invalid
19
27
 
20
28
  try:
@@ -42,7 +50,7 @@ class CouncilClass(AbstractGetBinDataClass):
42
50
 
43
51
  if service_name_element and next_service_element:
44
52
  service = service_name_element.text
45
- next_collection = next_service_element.find(text=date_regex)
53
+ next_collection = next_service_element.find(string=date_regex)
46
54
 
47
55
  if next_collection:
48
56
  dict_data = {
@@ -29,7 +29,7 @@ class CouncilClass(AbstractGetBinDataClass):
29
29
  start = BeautifulSoup(req.text, features="html.parser")
30
30
  start.prettify()
31
31
  base_link = start.select(
32
- "#menu-content > div > div:nth-child(1) > p.govuk-body.govuk-\!-margin-bottom-0.colorblue.lineheight15 > a"
32
+ "#menu-content > div > div:nth-child(1) > p.govuk-body.govuk-\\!-margin-bottom-0.colorblue.lineheight15 > a"
33
33
  )[0].attrs.get("href")
34
34
 
35
35
  # We need to reorder the query parts from the unique URL, so split them up to make it easier
@@ -0,0 +1,156 @@
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://selfservice.wychavon.gov.uk/wdcroundlookup/wdc_search.jsp"
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
+
50
+ wait = WebDriverWait(driver, 60)
51
+
52
+ logging.info("Accepting cookies")
53
+
54
+ try:
55
+ logging.info("Cookies")
56
+ cookie_window = wait.until(
57
+ EC.presence_of_element_located(
58
+ (By.XPATH, '//div[@id="ccc-content"]')
59
+ )
60
+ )
61
+ time.sleep(2)
62
+ accept_cookies = WebDriverWait(driver, timeout=10).until(
63
+ EC.presence_of_element_located(
64
+ (By.XPATH, '//button[@id="ccc-recommended-settings"]')
65
+ )
66
+ )
67
+ accept_cookies.send_keys(Keys.ENTER)
68
+ accept_cookies.click()
69
+ accept_cookies_close = WebDriverWait(driver, timeout=10).until(
70
+ EC.presence_of_element_located(
71
+ (By.XPATH, '//button[@id="ccc-close"]')
72
+ )
73
+ )
74
+ accept_cookies_close.send_keys(Keys.ENTER)
75
+ accept_cookies_close.click()
76
+ except:
77
+ print(
78
+ "Accept cookies banner not found or clickable within the specified time."
79
+ )
80
+ pass
81
+
82
+ logging.info("Entering postcode")
83
+ input_element_postcode = wait.until(
84
+ EC.presence_of_element_located((By.XPATH, '//input[@id="alAddrtxt"]'))
85
+ )
86
+
87
+ input_element_postcode.send_keys(user_postcode)
88
+
89
+ logging.info("Searching for postcode")
90
+ input_element_postcode_btn = wait.until(
91
+ EC.element_to_be_clickable((By.XPATH, '//button[@id="alAddrbtn"]'))
92
+ )
93
+
94
+ input_element_postcode_btn.click()
95
+
96
+ logging.info("Waiting for address dropdown")
97
+ input_element_postcode_dropdown = wait.until(
98
+ EC.presence_of_element_located((By.XPATH, '//select[@id="alAddrsel"]'))
99
+ )
100
+
101
+ logging.info("Selecting address")
102
+ drop_down_values = Select(input_element_postcode_dropdown)
103
+ option_element = wait.until(
104
+ EC.presence_of_element_located(
105
+ (By.CSS_SELECTOR, f'option[value="{str(user_uprn)}"]')
106
+ )
107
+ )
108
+
109
+ driver.execute_script("arguments[0].scrollIntoView();", option_element)
110
+ drop_down_values.select_by_value(str(user_uprn))
111
+
112
+ input_element_address_btn = wait.until(
113
+ EC.element_to_be_clickable((By.XPATH, '//input[@id="btnSubmit"]'))
114
+ )
115
+
116
+ input_element_address_btn.click()
117
+
118
+ logging.info("Waiting for bin collection page")
119
+ strong_element = wait.until(
120
+ EC.presence_of_element_located(
121
+ (By.XPATH, "//strong[contains(text(), 'Upcoming collections')]")
122
+ )
123
+ )
124
+
125
+ logging.info("Extracting bin collection data")
126
+ soup = BeautifulSoup(driver.page_source, features="html.parser")
127
+ bins = []
128
+
129
+ rows = soup.select("table tbody tr")
130
+ for row in rows:
131
+ bin_type = row.select_one("td:nth-of-type(2)").contents[0].strip()
132
+ date_elements = row.select("td:nth-of-type(3) strong")
133
+ if date_elements:
134
+ dates = [date.get_text(strip=True) for date in date_elements]
135
+ else:
136
+ dates = ["Not applicable"]
137
+
138
+ for date in dates:
139
+ if date != "Not applicable":
140
+ # Format the date to dd/mm/yyyy
141
+ formatted_date = re.search(r"\d{2}/\d{2}/\d{4}", date).group(0)
142
+ bins.append(
143
+ {"type": bin_type, "collectionDate": formatted_date}
144
+ )
145
+
146
+ bin_data = {"bins": bins}
147
+
148
+ return bin_data
149
+
150
+ except Exception as e:
151
+ logging.error(f"An error occurred: {e}")
152
+ raise
153
+
154
+ finally:
155
+ if driver:
156
+ driver.quit()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uk_bin_collection
3
- Version: 0.80.0
3
+ Version: 0.81.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=-t4WOCeYWUchkdm32IFhOJbufu0rP9vjwlzR43KLw3U,58920
5
+ uk_bin_collection/tests/input.json,sha256=tsLMMV6SegrudMLCU-F99uuUl3-RGY-dsG39rjeijhA,59231
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
@@ -21,16 +21,16 @@ uk_bin_collection/uk_bin_collection/councils/BathAndNorthEastSomersetCouncil.py,
21
21
  uk_bin_collection/uk_bin_collection/councils/BedfordBoroughCouncil.py,sha256=CvGB7w9HMn7XyEtwfd9MWZE_HlZ75pDcaKMsQJz0xhk,1669
22
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=x1LZiPn2C6JMHnj-R9cyrtUMnFb5o-kKtZK4sNuf6hY,4131
24
+ uk_bin_collection/uk_bin_collection/councils/BirminghamCityCouncil.py,sha256=yrO9dnSMdqVTcrzqXXfexFxSuESW01VPxXNAl0_lNOU,4669
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
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
30
  uk_bin_collection/uk_bin_collection/councils/BristolCityCouncil.py,sha256=kJmmDJz_kQ45DHmG7ocrUpNJonEn0kuXYEDQyZaf9ks,5576
31
- uk_bin_collection/uk_bin_collection/councils/BromleyBoroughCouncil.py,sha256=h92cM4SQwqFrBd9snnZuRgFjnftyZEoS7XfG3OUWa4k,4758
31
+ uk_bin_collection/uk_bin_collection/councils/BromleyBoroughCouncil.py,sha256=_bAFykZWZkEVUB-QKeVLfWO8plG6nRgn71QF2BUN2rk,4329
32
32
  uk_bin_collection/uk_bin_collection/councils/BroxtoweBoroughCouncil.py,sha256=-Facq-ToQkcWUePpKBwq90LZUFxgUSydNL2sYaLX4yw,4473
33
- uk_bin_collection/uk_bin_collection/councils/BuckinghamshireCouncil.py,sha256=rMc3lwu8UivbUZBiRedDhT8nBQQ83tvinc0QtmFjJNI,3184
33
+ uk_bin_collection/uk_bin_collection/councils/BuckinghamshireCouncil.py,sha256=-EAj7-CCb1kWEglITePOsSCUknJRU9hnuS5sysCf19w,3319
34
34
  uk_bin_collection/uk_bin_collection/councils/BuryCouncil.py,sha256=H7wAxO1nfxkewVoRRolumq8bBJG04siE3jieFH3RGpQ,2632
35
35
  uk_bin_collection/uk_bin_collection/councils/CalderdaleCouncil.py,sha256=OJZcHYlvZDzmBpjjPPm3J8CRK9Twc49vRj7O9c5fyQ4,4971
36
36
  uk_bin_collection/uk_bin_collection/councils/CannockChaseDistrictCouncil.py,sha256=ZamevXN8_Q8mRZOTESWtkb8jVyDXkTczcmhXMAVVSkM,2276
@@ -68,7 +68,7 @@ uk_bin_collection/uk_bin_collection/councils/GedlingBoroughCouncil.py,sha256=3Dp
68
68
  uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py,sha256=IOgM8Wl-LpO1T-F9uU1FlVfPaEObpvsdP7S2h03Mycc,2528
69
69
  uk_bin_collection/uk_bin_collection/councils/GuildfordCouncil.py,sha256=9pVrmQhZcK2AD8gX8mNvP--L4L9KaY6L3B822VX6fec,5695
70
70
  uk_bin_collection/uk_bin_collection/councils/HaltonBoroughCouncil.py,sha256=r8cmtWhMJg-XG63ZHxidKKW7i4yQNrZSSMSCkBwrqjI,5837
71
- uk_bin_collection/uk_bin_collection/councils/HaringeyCouncil.py,sha256=Fk3NRQUl_DHXXlEZ0C-mDW9d4TBomVC9m50WRVOC8Go,2362
71
+ uk_bin_collection/uk_bin_collection/councils/HaringeyCouncil.py,sha256=t_6AkAu4wrv8Q0WlDhWh_82I0djl5tk531Pzs-SjWzg,2647
72
72
  uk_bin_collection/uk_bin_collection/councils/HarrogateBoroughCouncil.py,sha256=_g3fP5Nq-OUjgNrfRf4UEyFKzq0x8QK-4enh5RP1efA,2050
73
73
  uk_bin_collection/uk_bin_collection/councils/HighPeakCouncil.py,sha256=oybn_cbzjBTEPLH-Ya6WaoRTvMHxLV6a0zXCX-AhOjY,4815
74
74
  uk_bin_collection/uk_bin_collection/councils/HounslowCouncil.py,sha256=LXhJ47rujx7k3naz0tFiTT1l5k6gAYcVdekJN1t_HLY,4564
@@ -174,14 +174,15 @@ uk_bin_collection/uk_bin_collection/councils/WestSuffolkCouncil.py,sha256=HMFWxM
174
174
  uk_bin_collection/uk_bin_collection/councils/WiganBoroughCouncil.py,sha256=3gqFA4-BVx_In6QOu3KUNqPN4Fkn9iMlZTeopMK9p6A,3746
175
175
  uk_bin_collection/uk_bin_collection/councils/WiltshireCouncil.py,sha256=it2Oh5Kmq3lD30gAZgk2bzZPNCtJcFHyQO1NgOQtfvU,5653
176
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
177
+ uk_bin_collection/uk_bin_collection/councils/WokingBoroughCouncil.py,sha256=37igH9g0xe4XIhRhcJ-ZJBU8MxTp5yzgpadWbdE33Yg,5205
178
+ uk_bin_collection/uk_bin_collection/councils/WychavonDistrictCouncil.py,sha256=YuZdzEW0CZLwusm1VQcGRIKXAab_UDFLaCnN60itt_E,5776
178
179
  uk_bin_collection/uk_bin_collection/councils/WyreCouncil.py,sha256=zDDa7n4K_zm5PgDL08A26gD9yOOsOhuexI3x2seaBF4,3511
179
180
  uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bIdsvmoSzBjJAvTTi6yPfJa8xjJx1ys2w,1490
180
181
  uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=4s9ODGPAwPqwXc8SrTX5Wlfmizs3_58iXUtHc4Ir86o,1162
181
182
  uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
182
183
  uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=9qppF2oPkhmOoK8-ZkRIU1M6vhBh-yUCWAZEEd07iLk,5414
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,,
184
+ uk_bin_collection-0.81.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
185
+ uk_bin_collection-0.81.0.dist-info/METADATA,sha256=FY2xzwnZMQ0FiEomvCzrJHbqIVc1RuPvo9dPwPxexR4,12594
186
+ uk_bin_collection-0.81.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
187
+ uk_bin_collection-0.81.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
188
+ uk_bin_collection-0.81.0.dist-info/RECORD,,