uk_bin_collection 0.134.0__py3-none-any.whl → 0.134.2__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- uk_bin_collection/tests/input.json +5 -4
- uk_bin_collection/uk_bin_collection/councils/CheltenhamBoroughCouncil.py +254 -48
- {uk_bin_collection-0.134.0.dist-info → uk_bin_collection-0.134.2.dist-info}/METADATA +1 -1
- {uk_bin_collection-0.134.0.dist-info → uk_bin_collection-0.134.2.dist-info}/RECORD +7 -7
- {uk_bin_collection-0.134.0.dist-info → uk_bin_collection-0.134.2.dist-info}/LICENSE +0 -0
- {uk_bin_collection-0.134.0.dist-info → uk_bin_collection-0.134.2.dist-info}/WHEEL +0 -0
- {uk_bin_collection-0.134.0.dist-info → uk_bin_collection-0.134.2.dist-info}/entry_points.txt +0 -0
@@ -383,12 +383,12 @@
|
|
383
383
|
"wiki_note": "Follow the instructions [here](https://www.chelmsford.gov.uk/myhome/) until you get the page listing your address, then copy the entire address text and use that in the house number field."
|
384
384
|
},
|
385
385
|
"CheltenhamBoroughCouncil": {
|
386
|
-
"
|
387
|
-
"postcode": "
|
386
|
+
"uprn": "100120372027",
|
387
|
+
"postcode": "GL51 3NA",
|
388
388
|
"skip_get_url": true,
|
389
389
|
"url": "https://www.cheltenham.gov.uk",
|
390
390
|
"wiki_name": "Cheltenham Borough Council",
|
391
|
-
"wiki_note": "
|
391
|
+
"wiki_note": "Pass the UPRN. You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search)."
|
392
392
|
},
|
393
393
|
"CheshireEastCouncil": {
|
394
394
|
"url": "https://online.cheshireeast.gov.uk/MyCollectionDay/SearchByAjax/GetBartecJobList?uprn=100012791226&onelineaddress=3%20COBBLERS%20YARD,%20SK9%207DZ&_=1689413260149",
|
@@ -609,6 +609,7 @@
|
|
609
609
|
"house_number": "1",
|
610
610
|
"postcode": "CM20 2FZ",
|
611
611
|
"skip_get_url": true,
|
612
|
+
"web_driver": "http://selenium:4444",
|
612
613
|
"url": "https://www.eastherts.gov.uk",
|
613
614
|
"wiki_name": "East Herts Council",
|
614
615
|
"wiki_note": "Pass the house number and postcode in their respective parameters."
|
@@ -2173,4 +2174,4 @@
|
|
2173
2174
|
"wiki_name": "York Council",
|
2174
2175
|
"wiki_note": "Provide your UPRN."
|
2175
2176
|
}
|
2176
|
-
}
|
2177
|
+
}
|
@@ -1,18 +1,18 @@
|
|
1
|
-
import re
|
2
|
-
import time
|
1
|
+
# import re
|
3
2
|
|
4
3
|
import requests
|
5
|
-
from bs4 import BeautifulSoup
|
6
|
-
from selenium.webdriver.common.by import By
|
7
|
-
from selenium.webdriver.support import expected_conditions as EC
|
8
|
-
from selenium.webdriver.support.ui import Select
|
9
|
-
from selenium.webdriver.support.wait import WebDriverWait
|
10
4
|
|
11
|
-
from uk_bin_collection.uk_bin_collection.common import
|
5
|
+
from uk_bin_collection.uk_bin_collection.common import (
|
6
|
+
check_postcode,
|
7
|
+
check_uprn,
|
8
|
+
datetime,
|
9
|
+
get_dates_every_x_days,
|
10
|
+
json,
|
11
|
+
timedelta,
|
12
|
+
)
|
12
13
|
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
|
13
14
|
|
14
15
|
|
15
|
-
# import the wonderful Beautiful Soup and the URL grabber
|
16
16
|
class CouncilClass(AbstractGetBinDataClass):
|
17
17
|
"""
|
18
18
|
Concrete classes have to implement all abstract operations of the
|
@@ -20,42 +20,193 @@ class CouncilClass(AbstractGetBinDataClass):
|
|
20
20
|
implementation.
|
21
21
|
"""
|
22
22
|
|
23
|
-
def parse_data(self, page: str, **kwargs) -> dict:
|
23
|
+
def parse_data(self, page: str, **kwargs: str) -> dict[str, list[dict[str, str]]]:
|
24
|
+
if (postcode := kwargs.get("postcode")) is None:
|
25
|
+
raise KeyError("Missing: postcode")
|
26
|
+
if (uprn := kwargs.get("uprn")) is None:
|
27
|
+
raise KeyError("Missing: uprn")
|
28
|
+
check_postcode(postcode)
|
29
|
+
check_uprn(uprn)
|
30
|
+
bindata: dict[str, list[dict[str, str]]] = {"bins": []}
|
31
|
+
location_x: int = 0
|
32
|
+
location_y: int = 0
|
33
|
+
location_usrn: str = ""
|
24
34
|
|
25
|
-
|
26
|
-
|
27
|
-
|
35
|
+
# Ensure any cookies set are maintained in a requests session
|
36
|
+
s = requests.session()
|
37
|
+
|
38
|
+
# Ask for a new SessionId from the server
|
39
|
+
session_id_url = "https://maps.cheltenham.gov.uk/map/Aurora.svc/"\
|
40
|
+
"RequestSession?userName=guest+CBC&password=&"\
|
41
|
+
"script=%5CAurora%5CCBC+Waste+Streets.AuroraScript%24"
|
42
|
+
session_id_response = s.get(session_id_url)
|
43
|
+
session_id_response.raise_for_status()
|
44
|
+
session_id = session_id_response.json().get("Session").get("SessionId")
|
45
|
+
|
46
|
+
# Ask what tasks we can do within the session
|
47
|
+
tasks_url = f"https://maps.cheltenham.gov.uk/map/Aurora.svc/"\
|
48
|
+
f"GetWorkflow?sessionId={session_id}&workflowId=wastestreet"
|
49
|
+
tasks_response = s.get(tasks_url)
|
50
|
+
tasks_response.raise_for_status()
|
51
|
+
# JSON response contained a BOM marker
|
52
|
+
tasks = json.loads(tasks_response.text[1:])
|
53
|
+
retrieve_results_task_id, initialise_map_task_id, drilldown_task_id = None, None, None
|
54
|
+
# Pull out the ID's of the tasks we will need
|
55
|
+
for task in tasks.get("Tasks"):
|
56
|
+
if task.get("$type") == "StatMap.Aurora.FetchResultSetTask, StatMapService":
|
57
|
+
retrieve_results_task_id = task.get("Id")
|
58
|
+
elif task.get("$type") == "StatMap.Aurora.SaveStateTask, StatMapService":
|
59
|
+
initialise_map_task_id = task.get("Id")
|
60
|
+
elif task.get("$type") == "StatMap.Aurora.DrillDownTask, StatMapService":
|
61
|
+
drilldown_task_id = task.get("Id")
|
62
|
+
if not all([retrieve_results_task_id, initialise_map_task_id, drilldown_task_id]):
|
63
|
+
raise ValueError("Not all task ID's found")
|
64
|
+
|
65
|
+
# Find the X / Y coordinates for the requested postcode
|
66
|
+
postcode_search_url = "https://maps.cheltenham.gov.uk/map/Aurora.svc/FindLocation?"\
|
67
|
+
f"sessionId={session_id}&address={postcode}&limit=1000"
|
68
|
+
postcode_search_response = s.get(postcode_search_url)
|
69
|
+
postcode_search_response.raise_for_status()
|
70
|
+
if len(locations_list := postcode_search_response.json().get("Locations")) == 0:
|
71
|
+
raise ValueError("Address locations empty")
|
72
|
+
for location in locations_list:
|
73
|
+
location_search_url = "https://maps.cheltenham.gov.uk/map/Aurora.svc/FindLocation?"\
|
74
|
+
f"sessionId={session_id}&locationId={location.get('Id')}"
|
75
|
+
location_search_response = s.get(location_search_url)
|
76
|
+
location_search_response.raise_for_status()
|
77
|
+
if not (location_list := location_search_response.json().get("Locations")):
|
78
|
+
raise KeyError("Locations wasn't present in results")
|
79
|
+
if not (location_detail := location_list[0].get("Details")):
|
80
|
+
raise KeyError("Details wasn't present in location")
|
81
|
+
location_uprn = [detail.get(
|
82
|
+
"Value") for detail in location_detail if detail.get("Name") == "UPRN"][0]
|
83
|
+
if str(location_uprn) == uprn:
|
84
|
+
location_usrn = str([detail.get(
|
85
|
+
"Value") for detail in location_detail if detail.get("Name") == "USRN"][0])
|
86
|
+
location_x = location_list[0].get("X")
|
87
|
+
location_y = location_list[0].get("Y")
|
88
|
+
break
|
89
|
+
|
90
|
+
# Needed to initialise the server to allow follow on call
|
91
|
+
open_map_url = "https://maps.cheltenham.gov.uk/map/Aurora.svc/OpenScriptMap?"\
|
92
|
+
f"sessionId={session_id}"
|
93
|
+
if res := s.get(open_map_url):
|
94
|
+
res.raise_for_status()
|
95
|
+
|
96
|
+
# Needed to initialise the server to allow follow on call
|
97
|
+
save_state_map_url = "https://maps.cheltenham.gov.uk/map/Aurora.svc/ExecuteTaskJob?"\
|
98
|
+
f"sessionId={session_id}&taskId={initialise_map_task_id}&job="\
|
99
|
+
"%7BTask%3A+%7B+%24type%3A+%27StatMap.Aurora.SaveStateTask%2C"\
|
100
|
+
"+StatMapService%27+%7D%7D"
|
101
|
+
if res := s.get(save_state_map_url):
|
102
|
+
res.raise_for_status()
|
103
|
+
|
104
|
+
# Start search for address given by x / y coord
|
105
|
+
drilldown_map_url = "https://maps.cheltenham.gov.uk/map/Aurora.svc/ExecuteTaskJob?"\
|
106
|
+
f"sessionId={session_id}&taskId={drilldown_task_id}&job=%7B%22"\
|
107
|
+
f"QueryX%22%3A{location_x}%2C%22QueryY%22%3A{location_y}%2C%22"\
|
108
|
+
"Task%22%3A%7B%22Type%22%3A%22StatMap.Aurora.DrillDownTask%2C"\
|
109
|
+
"+StatMapService%22%7D%7D"
|
110
|
+
if res := s.get(drilldown_map_url):
|
111
|
+
res.raise_for_status()
|
112
|
+
|
113
|
+
# Get results from search for address given by x / y coord
|
114
|
+
address_details_url = "https://maps.cheltenham.gov.uk/map/Aurora.svc/ExecuteTaskJob?"\
|
115
|
+
f"sessionId={session_id}&taskId={retrieve_results_task_id}"\
|
116
|
+
f"&job=%7B%22QueryX%22%3A{location_x}%2C%22QueryY%22%3A"\
|
117
|
+
f"{location_y}%2C%22Task%22%3A%7B%22Type%22%3A%22"\
|
118
|
+
"StatMap.Aurora.FetchResultSetTask%2C+StatMapService"\
|
119
|
+
"%22%2C%22ResultSetName%22%3A%22inspection%22%7D%7D"
|
120
|
+
address_details_response = s.get(address_details_url)
|
121
|
+
address_details_response.raise_for_status()
|
122
|
+
# JSON response contained a BOM marker, skip first character
|
123
|
+
address_details = json.loads(address_details_response.text[1:])
|
124
|
+
if not (task_results := address_details.get("TaskResult")):
|
125
|
+
raise KeyError("TaskResult wasn't present in results")
|
126
|
+
if not (distance_export_set := task_results.get("DistanceOrderedSet")):
|
127
|
+
raise KeyError("DistanceOrderedSet wasn't present in TaskResult")
|
128
|
+
if not (result_set := distance_export_set.get("ResultSet")):
|
129
|
+
raise KeyError("ResultSet wasn't present in DistanceOrderedSet")
|
130
|
+
if not (result_tables := result_set.get("Tables")):
|
131
|
+
raise KeyError("Tables wasn't present in ResultSet")
|
132
|
+
result = result_tables[0]
|
133
|
+
column_names: dict[int, str] = {}
|
134
|
+
result_dict: dict[str, str | int] = {}
|
135
|
+
for column in result.get("ColumnDefinitions"):
|
136
|
+
column_names[column.get("ColumnIndex")] = column.get("ColumnName")
|
137
|
+
for r in result.get("Records"):
|
138
|
+
result_dict: dict[str, str | int] = {}
|
139
|
+
for idx, column_value in enumerate(r):
|
140
|
+
if not (column_name := column_names.get(idx)):
|
141
|
+
raise IndexError("Column index out of range")
|
142
|
+
result_dict[column_name.upper()] = column_value
|
143
|
+
# Validate the street against the USRN. Some locations can return multiple results.
|
144
|
+
# Break on first match of USRN
|
145
|
+
# TODO: Need to select the correct option out of all available options
|
146
|
+
if location_usrn == str(result_dict.get("USRN")):
|
147
|
+
break
|
148
|
+
|
149
|
+
refuse_week, recycling_week, garden_week = 0, 0, 0
|
150
|
+
# After we've got the correct result, pull out the week number each bin type is taken on
|
151
|
+
if (refuse_week_raw := result_dict.get("New_Refuse_Week".upper())) is not None:
|
152
|
+
refuse_week = int(refuse_week_raw)
|
153
|
+
if (recycling_week_raw := result_dict.get("New_Recycling_Week".upper())) is not None:
|
154
|
+
recycling_week = int(recycling_week_raw)
|
155
|
+
if (garden_week_raw := result_dict.get("Garden_Bin_Week".upper())) is not None:
|
156
|
+
garden_week = int(garden_week_raw)
|
157
|
+
|
158
|
+
if not all([refuse_week, recycling_week, garden_week]):
|
159
|
+
raise KeyError("Not all week numbers found")
|
28
160
|
|
29
161
|
days_of_week = [
|
30
|
-
"
|
31
|
-
"
|
32
|
-
"
|
33
|
-
"
|
34
|
-
"
|
35
|
-
"
|
36
|
-
"
|
162
|
+
"MON",
|
163
|
+
"TUE",
|
164
|
+
"WED",
|
165
|
+
"THU",
|
166
|
+
"FRI",
|
167
|
+
"SAT",
|
168
|
+
"SUN",
|
37
169
|
]
|
38
170
|
|
39
|
-
|
171
|
+
refuse_day_offset = days_of_week.index(
|
172
|
+
str(result_dict.get("New_Refuse_Day_internal".upper())).upper())
|
173
|
+
recycling_day_offset = days_of_week.index(
|
174
|
+
str(result_dict.get("New_Recycling_Day".upper())).upper())
|
175
|
+
garden_day_offset = days_of_week.index(
|
176
|
+
str(result_dict.get("New_Garden_Day".upper())).upper())
|
177
|
+
food_day_offset = days_of_week.index(
|
178
|
+
str(result_dict.get("New_Food_Day".upper())).upper())
|
40
179
|
|
41
|
-
|
42
|
-
|
180
|
+
# Initialise WEEK-1/WEEK-2 based on known details
|
181
|
+
week_1_epoch = datetime(2025, 1, 13)
|
43
182
|
|
44
|
-
|
45
|
-
|
46
|
-
recyclingstartDate = datetime(2024, 11, 18)
|
47
|
-
else:
|
48
|
-
refusestartDate = datetime(2024, 11, 18)
|
49
|
-
recyclingstartDate = datetime(2024, 11, 25)
|
183
|
+
# Start of this week
|
184
|
+
this_week = datetime.now() - timedelta(days=datetime.now().weekday())
|
50
185
|
|
51
|
-
|
52
|
-
|
53
|
-
|
186
|
+
# If there's an even number of weeks between the week-1
|
187
|
+
# epoch and this week, then this week is of type week-1
|
188
|
+
if (((this_week - week_1_epoch).days // 7)) % 2 == 0:
|
189
|
+
week = {
|
190
|
+
1: this_week,
|
191
|
+
2: this_week + timedelta(days=7)
|
192
|
+
}
|
193
|
+
else:
|
194
|
+
week = {
|
195
|
+
1: this_week - timedelta(days=7),
|
196
|
+
2: this_week
|
197
|
+
}
|
54
198
|
|
55
|
-
|
199
|
+
refuse_dates: list[str] = get_dates_every_x_days(
|
200
|
+
week[refuse_week], 14, 28)
|
201
|
+
recycling_dates: list[str] = get_dates_every_x_days(
|
202
|
+
week[recycling_week], 14, 28)
|
203
|
+
garden_dates: list[str] = get_dates_every_x_days(
|
204
|
+
week[garden_week], 14, 28)
|
56
205
|
|
206
|
+
for refuse_date in refuse_dates:
|
57
207
|
collection_date = (
|
58
|
-
datetime.strptime(
|
208
|
+
datetime.strptime(refuse_date, "%d/%m/%Y") +
|
209
|
+
timedelta(days=refuse_day_offset)
|
59
210
|
).strftime("%d/%m/%Y")
|
60
211
|
|
61
212
|
dict_data = {
|
@@ -64,11 +215,11 @@ class CouncilClass(AbstractGetBinDataClass):
|
|
64
215
|
}
|
65
216
|
bindata["bins"].append(dict_data)
|
66
217
|
|
67
|
-
for
|
218
|
+
for recycling_date in recycling_dates:
|
68
219
|
|
69
220
|
collection_date = (
|
70
|
-
datetime.strptime(
|
71
|
-
|
221
|
+
datetime.strptime(recycling_date, "%d/%m/%Y") +
|
222
|
+
timedelta(days=recycling_day_offset)
|
72
223
|
).strftime("%d/%m/%Y")
|
73
224
|
|
74
225
|
dict_data = {
|
@@ -77,26 +228,81 @@ class CouncilClass(AbstractGetBinDataClass):
|
|
77
228
|
}
|
78
229
|
bindata["bins"].append(dict_data)
|
79
230
|
|
80
|
-
|
81
|
-
"type": "Garden Waste Bin",
|
82
|
-
"collectionDate": collection_date,
|
83
|
-
}
|
84
|
-
bindata["bins"].append(dict_data)
|
85
|
-
|
86
|
-
for food_date in food_dates:
|
231
|
+
for garden_date in garden_dates:
|
87
232
|
|
88
233
|
collection_date = (
|
89
|
-
datetime.strptime(
|
234
|
+
datetime.strptime(garden_date, "%d/%m/%Y") +
|
235
|
+
timedelta(days=garden_day_offset)
|
90
236
|
).strftime("%d/%m/%Y")
|
91
237
|
|
92
238
|
dict_data = {
|
93
|
-
"type": "
|
239
|
+
"type": "Garden Waste Bin",
|
94
240
|
"collectionDate": collection_date,
|
95
241
|
}
|
96
242
|
bindata["bins"].append(dict_data)
|
97
243
|
|
244
|
+
if ((food_waste_week := str(result_dict.get("FOOD_WASTE_WEEK_EXTERNAL", "")).upper())
|
245
|
+
== "weekly".upper()):
|
246
|
+
food_dates: list[str] = get_dates_every_x_days(week[1], 7, 56)
|
247
|
+
|
248
|
+
for food_date in food_dates:
|
249
|
+
|
250
|
+
collection_date = (
|
251
|
+
datetime.strptime(food_date, "%d/%m/%Y") +
|
252
|
+
timedelta(days=food_day_offset)
|
253
|
+
).strftime("%d/%m/%Y")
|
254
|
+
|
255
|
+
dict_data = {
|
256
|
+
"type": "Food Waste Bin",
|
257
|
+
"collectionDate": collection_date,
|
258
|
+
}
|
259
|
+
bindata["bins"].append(dict_data)
|
260
|
+
# Sometimes the food bin is collected on different days between
|
261
|
+
# week-1 and week-2
|
262
|
+
else:
|
263
|
+
first_week: str | int
|
264
|
+
second_week_detail: str
|
265
|
+
first_week, _, second_week_detail = food_waste_week.partition("&")
|
266
|
+
first_week = int(first_week.strip())
|
267
|
+
|
268
|
+
second_week_day, _, second_week_number = second_week_detail.partition(
|
269
|
+
"WEEK")
|
270
|
+
second_week_number = int(second_week_number.strip())
|
271
|
+
second_week_day: str = second_week_day.strip()[:3]
|
272
|
+
|
273
|
+
food_dates_first: list[str] = get_dates_every_x_days(
|
274
|
+
week[first_week], 14, 28)
|
275
|
+
food_dates_second: list[str] = get_dates_every_x_days(
|
276
|
+
week[second_week_number], 14, 28)
|
277
|
+
second_week_offset = days_of_week.index(second_week_day)
|
278
|
+
|
279
|
+
for food_date in food_dates_first:
|
280
|
+
|
281
|
+
collection_date = (
|
282
|
+
datetime.strptime(food_date, "%d/%m/%Y") +
|
283
|
+
timedelta(days=food_day_offset)
|
284
|
+
).strftime("%d/%m/%Y")
|
285
|
+
|
286
|
+
dict_data = {
|
287
|
+
"type": "Food Waste Bin",
|
288
|
+
"collectionDate": collection_date,
|
289
|
+
}
|
290
|
+
bindata["bins"].append(dict_data)
|
291
|
+
for food_date in food_dates_second:
|
292
|
+
|
293
|
+
collection_date = (
|
294
|
+
datetime.strptime(food_date, "%d/%m/%Y") +
|
295
|
+
timedelta(days=second_week_offset)
|
296
|
+
).strftime("%d/%m/%Y")
|
297
|
+
|
298
|
+
dict_data = {
|
299
|
+
"type": "Food Waste Bin",
|
300
|
+
"collectionDate": collection_date,
|
301
|
+
}
|
302
|
+
bindata["bins"].append(dict_data)
|
303
|
+
|
98
304
|
bindata["bins"].sort(
|
99
|
-
key=lambda x: datetime.strptime(
|
305
|
+
key=lambda x: datetime.strptime(
|
306
|
+
x.get("collectionDate", ""), "%d/%m/%Y")
|
100
307
|
)
|
101
|
-
|
102
308
|
return bindata
|
@@ -2,7 +2,7 @@ uk_bin_collection/README.rst,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
|
|
2
2
|
uk_bin_collection/tests/council_feature_input_parity.py,sha256=DO6Mk4ImYgM5ZCZ-cutwz5RoYYWZRLYx2tr6zIs_9Rc,3843
|
3
3
|
uk_bin_collection/tests/features/environment.py,sha256=VQZjJdJI_kZn08M0j5cUgvKT4k3iTw8icJge1DGOkoA,127
|
4
4
|
uk_bin_collection/tests/features/validate_council_outputs.feature,sha256=SJK-Vc737hrf03tssxxbeg_JIvAH-ddB8f6gU1LTbuQ,251
|
5
|
-
uk_bin_collection/tests/input.json,sha256=
|
5
|
+
uk_bin_collection/tests/input.json,sha256=93b85jhY57G2qIx1RZh-DL_J3kia3UJZ_oo9d-Sq_OI,114121
|
6
6
|
uk_bin_collection/tests/output.schema,sha256=ZwKQBwYyTDEM4G2hJwfLUVM-5v1vKRvRK9W9SS1sd18,1086
|
7
7
|
uk_bin_collection/tests/step_defs/step_helpers/file_handler.py,sha256=Ygzi4V0S1MIHqbdstUlIqtRIwnynvhu4UtpweJ6-5N8,1474
|
8
8
|
uk_bin_collection/tests/step_defs/test_validate_council.py,sha256=VZ0a81sioJULD7syAYHjvK_-nT_Rd36tUyzPetSA0gk,3475
|
@@ -62,7 +62,7 @@ uk_bin_collection/uk_bin_collection/councils/CarmarthenshireCountyCouncil.py,sha
|
|
62
62
|
uk_bin_collection/uk_bin_collection/councils/CastlepointDistrictCouncil.py,sha256=JVPYUIlU2ISgbUSr5AOOXNK6IFQFtQmhZyYIMAOedD4,3858
|
63
63
|
uk_bin_collection/uk_bin_collection/councils/CharnwoodBoroughCouncil.py,sha256=tXfzMetN6wxahuGGRp2mIyCCDSL4F2aG61HhUxw6COQ,2172
|
64
64
|
uk_bin_collection/uk_bin_collection/councils/ChelmsfordCityCouncil.py,sha256=EB88D0MNJwuDZ2GX1ENc5maGYx17mnHTCtNl6s-v11E,5090
|
65
|
-
uk_bin_collection/uk_bin_collection/councils/CheltenhamBoroughCouncil.py,sha256=
|
65
|
+
uk_bin_collection/uk_bin_collection/councils/CheltenhamBoroughCouncil.py,sha256=fo9n2AuD8a174h3YMa9awa3S4YO2XU1KaInQ4ULz6s4,13686
|
66
66
|
uk_bin_collection/uk_bin_collection/councils/CheshireEastCouncil.py,sha256=K95UaS67nxGSFzLoyqMSZcLmfhwjDImVXznMZC_bFa4,1680
|
67
67
|
uk_bin_collection/uk_bin_collection/councils/CheshireWestAndChesterCouncil.py,sha256=5mKZf22NgdyBY-SqV0c2q8b8IJobkoZrsfGEVUcxUyM,3544
|
68
68
|
uk_bin_collection/uk_bin_collection/councils/ChesterfieldBoroughCouncil.py,sha256=mZiM8Ugm_OP0JkC5pLaQmi4i79mAp4SNNrcIdsREjHw,7198
|
@@ -307,8 +307,8 @@ uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bId
|
|
307
307
|
uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=EQWRhZ2pEejlvm0fPyOTsOHKvUZmPnxEYO_OWRGKTjs,1158
|
308
308
|
uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
|
309
309
|
uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=YvmHfZqanwrJ8ToGch34x-L-7yPe31nB_x77_Mgl_vo,4545
|
310
|
-
uk_bin_collection-0.134.
|
311
|
-
uk_bin_collection-0.134.
|
312
|
-
uk_bin_collection-0.134.
|
313
|
-
uk_bin_collection-0.134.
|
314
|
-
uk_bin_collection-0.134.
|
310
|
+
uk_bin_collection-0.134.2.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
|
311
|
+
uk_bin_collection-0.134.2.dist-info/METADATA,sha256=AJh8NQGTC8kAz_sSl8NK8gd1ksOeXucIsEIyX11Eazg,19741
|
312
|
+
uk_bin_collection-0.134.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
313
|
+
uk_bin_collection-0.134.2.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
|
314
|
+
uk_bin_collection-0.134.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{uk_bin_collection-0.134.0.dist-info → uk_bin_collection-0.134.2.dist-info}/entry_points.txt
RENAMED
File without changes
|