uk_bin_collection 0.95.0__py3-none-any.whl → 0.96.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.
@@ -399,6 +399,13 @@
399
399
  "url": "https://www.eastleigh.gov.uk/waste-bins-and-recycling/collection-dates/your-waste-bin-and-recycling-collections?uprn=",
400
400
  "wiki_name": "Eastleigh Borough Council"
401
401
  },
402
+ "ElmbridgeBoroughCouncil": {
403
+ "url": "https://www.elmbridge.gov.uk",
404
+ "wiki_command_url_override": "https://www.elmbridge.gov.uk",
405
+ "uprn": "10013119164",
406
+ "wiki_name": "Elmbridge Borough Council",
407
+ "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
408
+ },
402
409
  "EnfieldCouncil": {
403
410
  "house_number": "111",
404
411
  "postcode": "N13 5AJ",
@@ -509,6 +516,13 @@
509
516
  "wiki_name": "Harrogate Borough Council",
510
517
  "wiki_note": "Pass the UPRN which can be found at https://secure.harrogate.gov.uk/inmyarea URL doesn't need to be passed."
511
518
  },
519
+ "HighlandCouncil": {
520
+ "url": "https://www.highland.gov.uk",
521
+ "wiki_command_url_override": "https://www.highland.gov.uk",
522
+ "uprn": "130072429",
523
+ "wiki_name": "Highland Council",
524
+ "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
525
+ },
512
526
  "HighPeakCouncil": {
513
527
  "house_number": "9 Ellison Street, Glossop",
514
528
  "postcode": "SK13 8BX",
@@ -961,6 +975,13 @@
961
975
  "url": "https://www.scambs.gov.uk/recycling-and-bins/find-your-household-bin-collection-day/",
962
976
  "wiki_name": "South Cambridgeshire Council"
963
977
  },
978
+ "SouthDerbyshireDistrictCouncil": {
979
+ "url": "https://maps.southderbyshire.gov.uk/iShareLIVE.web//getdata.aspx?RequestType=LocalInfo&ms=mapsources/MyHouse&format=JSONP&group=Recycling%20Bins%20and%20Waste|Next%20Bin%20Collections&uid=",
980
+ "wiki_command_url_override": "https://maps.southderbyshire.gov.uk/iShareLIVE.web//getdata.aspx?RequestType=LocalInfo&ms=mapsources/MyHouse&format=JSONP&group=Recycling%20Bins%20and%20Waste|Next%20Bin%20Collections&uid=XXXXXXXX",
981
+ "uprn": "10000820668",
982
+ "wiki_name": "South Derbyshire District Council",
983
+ "wiki_note": "Replace XXXXXXXX with UPRN. You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
984
+ },
964
985
  "SouthGloucestershireCouncil": {
965
986
  "skip_get_url": true,
966
987
  "uprn": "566419",
@@ -1001,6 +1022,13 @@
1001
1022
  "url": "https://www.southtyneside.gov.uk/article/33352/Bin-collection-dates",
1002
1023
  "wiki_name": "South Tyneside Council"
1003
1024
  },
1025
+ "SouthwarkCouncil": {
1026
+ "url": "https://www.southwark.gov.uk/bins/lookup/",
1027
+ "wiki_command_url_override": "https://www.southwark.gov.uk/bins/lookup/XXXXXXXX",
1028
+ "uprn": "200003469271",
1029
+ "wiki_name": "Southwark Council",
1030
+ "wiki_note": "Replace XXXXXXXX with UPRN. You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
1031
+ },
1004
1032
  "StAlbansCityAndDistrictCouncil": {
1005
1033
  "skip_get_url": true,
1006
1034
  "uprn": "100081153583",
@@ -0,0 +1,91 @@
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
+ BASE_URL = "https://elmbridge-self.achieveservice.com"
24
+ INTIAL_URL = f"{BASE_URL}/service/Your_bin_collection_days"
25
+ AUTH_URL = f"{BASE_URL}/authapi/isauthenticated"
26
+ AUTH_TEST = f"{BASE_URL}/apibroker/domain/elmbridge-self.achieveservice.com"
27
+ API_URL = f"{BASE_URL}/apibroker/runLookup"
28
+
29
+ self._session = requests.Session()
30
+ r = self._session.get(INTIAL_URL)
31
+ r.raise_for_status()
32
+ params: dict[str, str | int] = {
33
+ "uri": r.url,
34
+ "hostname": "elmbridge-self.achieveservice.com",
35
+ "withCredentials": "true",
36
+ }
37
+ r = self._session.get(AUTH_URL, params=params)
38
+ r.raise_for_status()
39
+ data = r.json()
40
+ session_key = data["auth-session"]
41
+
42
+ params = {
43
+ "sid": session_key,
44
+ "_": int(datetime.now().timestamp() * 1000),
45
+ }
46
+ r = self._session.get(AUTH_TEST, params=params)
47
+ r.raise_for_status()
48
+
49
+ params: dict[str, int | str] = {
50
+ "id": "663b557cdaece",
51
+ "repeat_against": "",
52
+ "noRetry": "false",
53
+ "getOnlyTokens": "undefined",
54
+ "log_id": "",
55
+ "app_name": "AF-Renderer::Self",
56
+ "_": int(datetime.now().timestamp() * 1000),
57
+ "sid": session_key,
58
+ }
59
+ payload = {
60
+ "formValues": {
61
+ "Section 1": {
62
+ "UPRN": {"value": user_uprn},
63
+ }
64
+ }
65
+ }
66
+ r = self._session.post(API_URL, params=params, json=payload)
67
+ r.raise_for_status()
68
+
69
+ data = r.json()
70
+ collections = list(r.json()["integration"]["transformed"]["rows_data"].values())
71
+
72
+ for collection in collections:
73
+ date = collection["Date"]
74
+ for service in [
75
+ collection["Service1"],
76
+ collection["Service2"],
77
+ collection["Service3"],
78
+ ]:
79
+ if not service:
80
+ continue
81
+ service = service.removesuffix(" Collection Service")
82
+
83
+ dict_data = {
84
+ "type": service,
85
+ "collectionDate": datetime.strptime(
86
+ date, "%d/%m/%Y %H:%M:%S"
87
+ ).strftime("%d/%m/%Y"),
88
+ }
89
+ bindata["bins"].append(dict_data)
90
+
91
+ return bindata
@@ -0,0 +1,88 @@
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://highland-self.achieveservice.com/authapi/isauthenticated?uri=https%3A%2F%2Fhighland-self.achieveservice.com%2Fen%2Fservice%2FCheck_your_household_bin_collection_days&hostname=highland-self.achieveservice.com&withCredentials=true"
24
+
25
+ API_URL = "https://highland-self.achieveservice.com/apibroker/runLookup"
26
+
27
+ data = {
28
+ "formValues": {"Your address": {"propertyuprn": {"value": user_uprn}}},
29
+ }
30
+ headers = {
31
+ "Content-Type": "application/json",
32
+ "Accept": "application/json",
33
+ "User-Agent": "Mozilla/5.0",
34
+ "X-Requested-With": "XMLHttpRequest",
35
+ "Referer": "https://highland-self.achieveservice.com/fillform/?iframe_id=fillform-frame-1&db_id=",
36
+ }
37
+ s = requests.session()
38
+ r = s.get(SESSION_URL)
39
+ r.raise_for_status()
40
+ session_data = r.json()
41
+ sid = session_data["auth-session"]
42
+ params = {
43
+ "id": "660d44a698632",
44
+ "repeat_against": "",
45
+ "noRetry": "false",
46
+ "getOnlyTokens": "undefined",
47
+ "log_id": "",
48
+ "app_name": "AF-Renderer::Self",
49
+ # unix_timestamp
50
+ "_": str(int(time.time() * 1000)),
51
+ "sid": sid,
52
+ }
53
+
54
+ r = s.post(API_URL, json=data, headers=headers, params=params)
55
+ r.raise_for_status()
56
+
57
+ data = r.json()
58
+ rows_data = data["integration"]["transformed"]["rows_data"]["0"]
59
+ if not isinstance(rows_data, dict):
60
+ raise ValueError("Invalid data returned from API")
61
+
62
+ use_new = any(k.endswith("New") and v for k, v in rows_data.items())
63
+ next_date_key = "NextDateNew" if use_new else "NextDateOld"
64
+
65
+ for key, value in rows_data.items():
66
+ if not (key.endswith("NextDate") or key.endswith(next_date_key)):
67
+ continue
68
+
69
+ bin_type = key.split("NextDate")[0]
70
+ if bin_type == "refuse":
71
+ bin_type = "Non-recyclable waste"
72
+ if bin_type == "fibres":
73
+ bin_type = "Paper, card and cardboard recycling"
74
+ if bin_type == "containers":
75
+ bin_type = "Plastics, metals and cartons recycling"
76
+ if bin_type == "garden":
77
+ bin_type = "Garden waste"
78
+ if bin_type == "food":
79
+ bin_type = "Food waste"
80
+
81
+ try:
82
+ date = datetime.strptime(value, "%Y-%m-%d").strftime("%d/%m/%Y")
83
+ except ValueError:
84
+ continue
85
+ dict_data = {"type": bin_type, "collectionDate": date}
86
+ bindata["bins"].append(dict_data)
87
+
88
+ return bindata
@@ -0,0 +1,60 @@
1
+ import requests
2
+
3
+ from uk_bin_collection.uk_bin_collection.common import *
4
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
5
+
6
+
7
+ # import the wonderful Beautiful Soup and the URL grabber
8
+ class CouncilClass(AbstractGetBinDataClass):
9
+ """
10
+ Concrete classes have to implement all abstract operations of the
11
+ base class. They can also override some operations with a default
12
+ implementation.
13
+ """
14
+
15
+ def parse_data(self, page: str, **kwargs) -> dict:
16
+
17
+ user_uprn = kwargs.get("uprn")
18
+ check_uprn(user_uprn)
19
+ data = {"bins": []}
20
+
21
+ baseurl = "https://maps.southderbyshire.gov.uk/iShareLIVE.web//getdata.aspx?RequestType=LocalInfo&ms=mapsources/MyHouse&format=JSONP&group=Recycling%20Bins%20and%20Waste|Next%20Bin%20Collections&uid="
22
+ url = baseurl + user_uprn
23
+
24
+ # Make the web request
25
+ response = requests.get(url).text
26
+
27
+ # Remove the JSONP wrapper using a regular expression
28
+ jsonp_pattern = r"\{.*\}"
29
+ json_match = re.search(jsonp_pattern, response)
30
+
31
+ if json_match:
32
+ # Extract the JSON part
33
+ json_data = json_match.group(0)
34
+
35
+ # Parse the JSON
36
+ parsed_data = json.loads(json_data)
37
+
38
+ # Extract the embedded HTML string
39
+ html_content = parsed_data["Results"]["Next_Bin_Collections"]["_"]
40
+
41
+ # Parse the HTML to extract dates and bin types using regex
42
+ matches = re.findall(
43
+ r"<span.*?>(\d{2} \w+ \d{4})</span>.*?<span.*?>(.*?)</span>",
44
+ html_content,
45
+ re.S,
46
+ )
47
+
48
+ # Output the parsed bin collection details
49
+ for match in matches:
50
+ dict_data = {
51
+ "type": match[1],
52
+ "collectionDate": datetime.strptime(match[0], "%d %B %Y").strftime(
53
+ "%d/%m/%Y"
54
+ ),
55
+ }
56
+ data["bins"].append(dict_data)
57
+ else:
58
+ print("No valid JSON found in the response.")
59
+
60
+ return data
@@ -0,0 +1,136 @@
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
+ data = {"bins": []}
21
+
22
+ baseurl = "https://www.southwark.gov.uk/bins/lookup/"
23
+ url = baseurl + user_uprn
24
+
25
+ headers = {
26
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"
27
+ }
28
+
29
+ # Make the web request
30
+ response = requests.get(url, headers=headers).text
31
+
32
+ soup = BeautifulSoup(response, "html.parser")
33
+
34
+ # Extract recycling collection information
35
+ recycling_section = soup.find(
36
+ "div", {"aria-labelledby": "recyclingCollectionTitle"}
37
+ )
38
+ if recycling_section:
39
+ recycling_title = recycling_section.find(
40
+ "p", {"id": "recyclingCollectionTitle"}
41
+ ).text
42
+ recycling_next_collection = (
43
+ recycling_section.find(text=lambda text: "Next collection" in text)
44
+ .strip()
45
+ .split(": ")[1]
46
+ )
47
+
48
+ dict_data = {
49
+ "type": recycling_title,
50
+ "collectionDate": datetime.strptime(
51
+ recycling_next_collection, "%a, %d %B %Y"
52
+ ).strftime("%d/%m/%Y"),
53
+ }
54
+ data["bins"].append(dict_data)
55
+
56
+ # Extract refuse collection information
57
+ refuse_section = soup.find("div", {"aria-labelledby": "refuseCollectionTitle"})
58
+ if refuse_section:
59
+ refuse_title = refuse_section.find(
60
+ "p", {"id": "refuseCollectionTitle"}
61
+ ).text
62
+ refuse_next_collection = (
63
+ refuse_section.find(text=lambda text: "Next collection" in text)
64
+ .strip()
65
+ .split(": ")[1]
66
+ )
67
+
68
+ dict_data = {
69
+ "type": refuse_title,
70
+ "collectionDate": datetime.strptime(
71
+ refuse_next_collection, "%a, %d %B %Y"
72
+ ).strftime("%d/%m/%Y"),
73
+ }
74
+ data["bins"].append(dict_data)
75
+
76
+ # Extract food waste collection information
77
+ food_section = soup.find("div", {"aria-labelledby": "organicsCollectionTitle"})
78
+ if food_section:
79
+ food_title = food_section.find("p", {"id": "organicsCollectionTitle"}).text
80
+ food_next_collection = (
81
+ food_section.find(text=lambda text: "Next collection" in text)
82
+ .strip()
83
+ .split(": ")[1]
84
+ )
85
+
86
+ dict_data = {
87
+ "type": food_title,
88
+ "collectionDate": datetime.strptime(
89
+ food_next_collection, "%a, %d %B %Y"
90
+ ).strftime("%d/%m/%Y"),
91
+ }
92
+ data["bins"].append(dict_data)
93
+
94
+ comrec_section = soup.find(
95
+ "div", {"aria-labelledby": "recyclingCommunalCollectionTitle"}
96
+ )
97
+ if comrec_section:
98
+ comrec_title = comrec_section.find(
99
+ "p", {"id": "recyclingCommunalCollectionTitle"}
100
+ ).text
101
+ comrec_next_collection = (
102
+ comrec_section.find(text=lambda text: "Next collection" in text)
103
+ .strip()
104
+ .split(": ")[1]
105
+ )
106
+
107
+ dict_data = {
108
+ "type": comrec_title,
109
+ "collectionDate": datetime.strptime(
110
+ comrec_next_collection, "%a, %d %B %Y"
111
+ ).strftime("%d/%m/%Y"),
112
+ }
113
+ data["bins"].append(dict_data)
114
+
115
+ comref_section = soup.find(
116
+ "div", {"aria-labelledby": "refuseCommunalCollectionTitle"}
117
+ )
118
+ if comref_section:
119
+ comref_title = comref_section.find(
120
+ "p", {"id": "refuseCommunalCollectionTitle"}
121
+ ).text
122
+ comref_next_collection = (
123
+ comref_section.find(text=lambda text: "Next collection" in text)
124
+ .strip()
125
+ .split(": ")[1]
126
+ )
127
+
128
+ dict_data = {
129
+ "type": comref_title,
130
+ "collectionDate": datetime.strptime(
131
+ comref_next_collection, "%a, %d %B %Y"
132
+ ).strftime("%d/%m/%Y"),
133
+ }
134
+ data["bins"].append(dict_data)
135
+
136
+ return data
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uk_bin_collection
3
- Version: 0.95.0
3
+ Version: 0.96.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=9YyrjZ9mH77wJ1qkoOPD9p4eiFEF0_J6xE7phELNeIo,63439
5
+ uk_bin_collection/tests/input.json,sha256=heU28tV0vbQ8dbVkpiCpZfcETkiWoxu5wfgGvO_hmdk,65257
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=LrOSt_loA1Mw3vTqaO2LpaDMu7rYJy6k5Kr-EOBln7s,3424
@@ -66,6 +66,7 @@ uk_bin_collection/uk_bin_collection/councils/EastRenfrewshireCouncil.py,sha256=5
66
66
  uk_bin_collection/uk_bin_collection/councils/EastRidingCouncil.py,sha256=CsYdkmL-8Ty-Kz7uNdlnJnhiDMgOPah_swYgSKbaFqA,5218
67
67
  uk_bin_collection/uk_bin_collection/councils/EastSuffolkCouncil.py,sha256=qQ0oOfGd0sWcczse_B22YoeL9uj3og8v3UJLt_Sx29c,4353
68
68
  uk_bin_collection/uk_bin_collection/councils/EastleighBoroughCouncil.py,sha256=V4Vso4DvawFiezKlmXbTlJEK9Sjhz9nA8WeYjwtO2e4,2310
69
+ uk_bin_collection/uk_bin_collection/councils/ElmbridgeBoroughCouncil.py,sha256=TgBOaReHWBbm0avV7HqRf0x7cxDe9cacTUcP9TFFprs,3005
69
70
  uk_bin_collection/uk_bin_collection/councils/EnfieldCouncil.py,sha256=HhKHlLciZKXViqcgkWme-wBUKlGhAs5LIpkKuRETvXM,6119
70
71
  uk_bin_collection/uk_bin_collection/councils/EnvironmentFirst.py,sha256=_9QJYDHpdnYK5R6znvZk1w0F9GnPnI8G4b6I_p26h4U,1695
71
72
  uk_bin_collection/uk_bin_collection/councils/EppingForestDistrictCouncil.py,sha256=cKFllQ4zt6MGkwiz_HedZvw3iL1kRMLA6Ct2spUE5og,2085
@@ -82,6 +83,7 @@ uk_bin_collection/uk_bin_collection/councils/HaltonBoroughCouncil.py,sha256=r8cm
82
83
  uk_bin_collection/uk_bin_collection/councils/HaringeyCouncil.py,sha256=t_6AkAu4wrv8Q0WlDhWh_82I0djl5tk531Pzs-SjWzg,2647
83
84
  uk_bin_collection/uk_bin_collection/councils/HarrogateBoroughCouncil.py,sha256=_g3fP5Nq-OUjgNrfRf4UEyFKzq0x8QK-4enh5RP1efA,2050
84
85
  uk_bin_collection/uk_bin_collection/councils/HighPeakCouncil.py,sha256=oqF8M0lcT3KsrG6W6I6JJX07E6Sc_-_sr7MybfIMab8,4626
86
+ uk_bin_collection/uk_bin_collection/councils/HighlandCouncil.py,sha256=GNxDU65QuZHV5va2IrKtcJ6TQoDdwmV03JvkVqOauP4,3291
85
87
  uk_bin_collection/uk_bin_collection/councils/HounslowCouncil.py,sha256=LXhJ47rujx7k3naz0tFiTT1l5k6gAYcVdekJN1t_HLY,4564
86
88
  uk_bin_collection/uk_bin_collection/councils/HullCityCouncil.py,sha256=UHcesBoctFVcXDYuwfag43KbcJcopkEDzJ-54NxtK0Q,1851
87
89
  uk_bin_collection/uk_bin_collection/councils/HuntingdonDistrictCouncil.py,sha256=dGyhhG6HRjQ2SPeiRwUPTGlk9dPIslagV2k0GjEOn1s,1587
@@ -146,12 +148,14 @@ uk_bin_collection/uk_bin_collection/councils/SolihullCouncil.py,sha256=gbTHjbdV4
146
148
  uk_bin_collection/uk_bin_collection/councils/SomersetCouncil.py,sha256=CZJnkCGn4-yH31HH5_ix-8V2_vsjGuKYxgzAPGZdSAw,8480
147
149
  uk_bin_collection/uk_bin_collection/councils/SouthAyrshireCouncil.py,sha256=03eapeXwxneKI4ccKPSHoviIbhmV1m90I-0WQ_s3KsY,2722
148
150
  uk_bin_collection/uk_bin_collection/councils/SouthCambridgeshireCouncil.py,sha256=xGSMcikxjS4UzqKs0X50LJKmn09C-XAAs98SPhNZgkQ,2308
151
+ uk_bin_collection/uk_bin_collection/councils/SouthDerbyshireDistrictCouncil.py,sha256=irqelQSENPsZLlNtYtpt-Z7GwKUyvhp94kKKVIIDjQg,2087
149
152
  uk_bin_collection/uk_bin_collection/councils/SouthGloucestershireCouncil.py,sha256=ytQot0J7i6DTJo6hb9koTB1UpXLATKVeRU4FBF9kHRo,2412
150
153
  uk_bin_collection/uk_bin_collection/councils/SouthKestevenDistrictCouncil.py,sha256=AgycOW-UIAm5_c8QondfKL0n4wUA4cbaN_Jp0e8g494,5587
151
154
  uk_bin_collection/uk_bin_collection/councils/SouthLanarkshireCouncil.py,sha256=fj-eZI0yrvQVCv8GvhcovZ3b9bV6Xv_ws3IunWjnv4U,3126
152
155
  uk_bin_collection/uk_bin_collection/councils/SouthNorfolkCouncil.py,sha256=ThO-oJ_n7hNRMl_n--rMPWKS6j-hkL_Ab7JBqKaylfg,3971
153
156
  uk_bin_collection/uk_bin_collection/councils/SouthOxfordshireCouncil.py,sha256=zW4bN3hcqNoK_Y0-vPpuZs3K0LTPvApu6_v9K-D7WjE,3879
154
157
  uk_bin_collection/uk_bin_collection/councils/SouthTynesideCouncil.py,sha256=dxXGrJfg_fn2IPTBgq6Duwy0WY8GYLafMuisaCjOnbs,3426
158
+ uk_bin_collection/uk_bin_collection/councils/SouthwarkCouncil.py,sha256=Kc9YrevYO4u1EI1r2LV74cmYCpEo5x2c8-WfFHecPCc,4817
155
159
  uk_bin_collection/uk_bin_collection/councils/StAlbansCityAndDistrictCouncil.py,sha256=mPZz6Za6kTSkrfHnj0OfwtnpRYR1dKvxbuFEKnWsiL8,1451
156
160
  uk_bin_collection/uk_bin_collection/councils/StHelensBC.py,sha256=c7ZM8gnUkKdz9GYIhFLzTtwN0KAoMEKomTWDVbtJIpM,2069
157
161
  uk_bin_collection/uk_bin_collection/councils/StaffordBoroughCouncil.py,sha256=9Qj4HJI7Dbiqb2mVSG2UtkBe27Y7wvQ5SYFTwGzJ5g0,2292
@@ -198,8 +202,8 @@ uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bId
198
202
  uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=4s9ODGPAwPqwXc8SrTX5Wlfmizs3_58iXUtHc4Ir86o,1162
199
203
  uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
200
204
  uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=YvmHfZqanwrJ8ToGch34x-L-7yPe31nB_x77_Mgl_vo,4545
201
- uk_bin_collection-0.95.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
202
- uk_bin_collection-0.95.0.dist-info/METADATA,sha256=Zw1i8zJ0E2Bhgn45ExUd1NCU8D8pgGWsbfShi88vm2Q,16843
203
- uk_bin_collection-0.95.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
204
- uk_bin_collection-0.95.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
205
- uk_bin_collection-0.95.0.dist-info/RECORD,,
205
+ uk_bin_collection-0.96.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
206
+ uk_bin_collection-0.96.0.dist-info/METADATA,sha256=BGnwvmk6ZjWGYrBNl0FBDqMZGRmfAACqkC-V8BDtOBU,16843
207
+ uk_bin_collection-0.96.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
208
+ uk_bin_collection-0.96.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
209
+ uk_bin_collection-0.96.0.dist-info/RECORD,,