We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Problems with awido_de
Hello,

i have a problem with the awido_de calander :(


Log:
```
2023-01-09 20:43:52.963 ERROR (SyncWorker_4) [waste_collection_schedule.source_shell] fetch failed for source AWIDO Online:
File "/config/custom_components/waste_collection_schedule/waste_collection_schedule/source_shell.py", line 134, in fetch
File "/config/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py", line 108, in fetch

```

configuration.yaml
```
waste_collection_schedule:
  sources:
    - name: awido_de
      args:
        customer: "bgl"
        city: "Laufen"
        street: "XXX Str."
        housenumber: 1
```

Setup:
```
Home Assistant 2023.1.2
Frontend 20230104.0 - latest
Installation: Docker
Waste Collection Schedule 1.33.0
```

Any ideas?

Regards,
Christian

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py`
Content:
```
1 import datetime
2 import logging
3 
4 import requests
5 from waste_collection_schedule import Collection  # type: ignore[attr-defined]
6 
7 TITLE = "AWIDO Online"
8 DESCRIPTION = "Source for AWIDO waste collection."
9 URL = "https://www.awido-online.de/"
10 
11 
12 def EXTRA_INFO():
13     return [{"title": s["title"], "url": s["url"]} for s in SERVICE_MAP]
14 
15 
16 SERVICE_MAP = [
17     {
18         "title": "Abfallwirtschaft Rems-Murr",
19         "url": "https://www.abfallwirtschaft-rems-murr.de/",
20         "service_id": "rmk",
21     },
22     {
23         "title": "Landkreis Schweinfurt",
24         "url": "https://www.landkreis-schweinfurt.de",
25         "service_id": "lra-schweinfurt",
26     },
27     {
28         "title": "Landkreis Gotha",
29         "url": "https://www.landkreis-gotha.de/",
30         "service_id": "gotha",
31     },
32     {
33         "title": "Zweckverband Abfallwirtschaft Saale-Orla",
34         "url": "https://www.zaso-online.de/",
35         "service_id": "zaso",
36     },
37     {
38         "title": "Gemeinde Unterhaching",
39         "url": "https://www.unterhaching.de/",
40         "service_id": "unterhaching",
41     },
42     {
43         "title": "Stadt Kaufbeuren",
44         "url": "https://www.kaufbeuren.de/",
45         "service_id": "kaufbeuren",
46     },
47     {
48         "title": "Landkreis Berchtesgadener Land",
49         "url": "https://www.lra-bgl.de/",
50         "service_id": "bgl",
51     },
52     {
53         "title": "Pullach im Isartal",
54         "url": "https://www.pullach.de/",
55         "service_id": "pullach",
56     },
57     {
58         "title": "AWB Landkreis Fürstenfeldbruck",
59         "url": "https://www.awb-ffb.de/",
60         "service_id": "ffb",
61     },
62     {
63         "title": "Stadt Unterschleißheim",
64         "url": "https://www.unterschleissheim.de/",
65         "service_id": "unterschleissheim",
66     },
67     {
68         "title": "Landkreis Tirschenreuth",
69         "url": "https://www.kreis-tir.de/",
70         "service_id": "kreis-tir",
71     },
72     {
73         "title": "Landkreis Rosenheim",
74         "url": "https://www.abfall.landkreis-rosenheim.de/",
75         "service_id": "rosenheim",
76     },
77     {
78         "title": "Landkreis Tübingen",
79         "url": "https://www.abfall-kreis-tuebingen.de/",
80         "service_id": "tuebingen",
81     },
82     {
83         "title": "Landkreis Kronach",
84         "url": "https://www.landkreis-kronach.de/",
85         "service_id": "kronach",
86     },
87     {
88         "title": "Landkreis Erding",
89         "url": "https://www.landkreis-erding.de/",
90         "service_id": "erding",
91     },
92     {
93         "title": "Zweckverband München-Südost",
94         "url": "https://www.zvmso.de/",
95         "service_id": "zv-muc-so",
96     },
97     {
98         "title": "Landkreis Coburg",
99         "url": "https://www.landkreis-coburg.de/",
100         "service_id": "coburg",
101     },
102     {
103         "title": "Landkreis Ansbach",
104         "url": "https://www.landkreis-ansbach.de/",
105         "service_id": "ansbach",
106     },
107     {
108         "title": "AWB Landkreis Bad Dürkheim",
109         "url": "http://awb.kreis-bad-duerkheim.de/",
110         "service_id": "awb-duerkheim",
111     },
112     {
113         "title": "Landratsamt Aichach-Friedberg",
114         "url": "https://lra-aic-fdb.de/",
115         "service_id": "aic-fdb",
116     },
117     {
118         "title": "WGV Recycling GmbH",
119         "url": "https://wgv-quarzbichl.de/",
120         "service_id": "wgv",
121     },
122     {
123         "title": "Neustadt a.d. Waldnaab",
124         "url": "https://www.neustadt.de/",
125         "service_id": "neustadt",
126     },
127     {
128         "title": "Landkreis Kelheim",
129         "url": "https://www.landkreis-kelheim.de/",
130         "service_id": "kelheim",
131     },
132     {
133         "title": "Landkreis Günzburg",
134         "url": "https://kaw.landkreis-guenzburg.de/",
135         "service_id": "kaw-guenzburg",
136     },
137     {
138         "title": "Stadt Memmingen",
139         "url": "https://umwelt.memmingen.de/",
140         "service_id": "memmingen",
141     },
142     {
143         "title": "Landkreis Südliche Weinstraße",
144         "url": "https://www.suedliche-weinstrasse.de/",
145         "service_id": "eww-suew",
146     },
147     {
148         "title": "Landratsamt Dachau",
149         "url": "https://www.landratsamt-dachau.de/",
150         "service_id": "lra-dah",
151     },
152     {
153         "title": "Landkreisbetriebe Neuburg-Schrobenhausen",
154         "url": "https://www.landkreisbetriebe.de/",
155         "service_id": "landkreisbetriebe",
156     },
157     {
158         "title": "Abfallwirtschaftsbetrieb Landkreis Altenkirchen",
159         "url": "https://www.awb-ak.de/",
160         "service_id": "awb-ak",
161     },
162     {
163         "title": "Abfallwirtschaft Lahn-Dill-Kreises",
164         "url": "https://www.awld.de/",
165         "service_id": "awld",
166     },
167     {
168         "title": "Abfallwirtschafts-Zweckverband des Landkreises Hersfeld-Rotenburg",
169         "url": "https://www.azv-hef-rof.de/",
170         "service_id": "azv-hef-rof",
171     },
172     {
173         "title": "Abfall-Wirtschafts-Verband Nordschwaben",
174         "url": "https://www.awv-nordschwaben.de/",
175         "service_id": "awv-nordschwaben",
176     },
177 ]
178 TEST_CASES = {
179     "Schorndorf, Miedelsbacher Straße 30 /1": {
180         "customer": "rmk",
181         "city": "Schorndorf",
182         "street": "Miedelsbacher Straße",
183         "housenumber": "30 /1",
184     },
185     "Altomünster, Maisbrunn": {
186         "customer": "lra-dah",
187         "city": "Altomünster",
188         "street": "Maisbrunn",
189     },
190     "SOK-Alsmannsdorf": {"customer": "zaso", "city": "SOK-Alsmannsdorf"},
191     "Kaufbeuren, Rehgrund": {
192         "customer": "kaufbeuren",
193         "city": "Kaufbeuren",
194         "street": "Rehgrund",
195     },
196     "Tübingen, Dettenhausen": {"customer": "tuebingen", "city": "Dettenhausen"},
197 }
198 
199 _LOGGER = logging.getLogger(__name__)
200 
201 
202 class Source:
203     def __init__(self, customer, city, street=None, housenumber=None):
204         self._customer = customer
205         self._city = city
206         self._street = street
207         self._housenumber = housenumber
208 
209     def fetch(self):
210         # Retrieve list of places
211         r = requests.get(
212             f"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getPlaces/client={self._customer}"
213         )
214         r.raise_for_status()
215         places = r.json()
216 
217         # create city to key map from retrieved places
218         city_to_oid = {place["value"].strip(): place["key"] for (place) in places}
219 
220         if self._city not in city_to_oid:
221             raise Exception(f"city not found: {self._city}")
222 
223         oid = city_to_oid[self._city]
224 
225         if self._street is None:
226             # test if we have to use city also as street name
227             self._street = self._city
228             r = requests.get(
229                 f"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{oid}",
230                 params={"client": self._customer},
231             )
232             r.raise_for_status()
233             streets = r.json()
234 
235             # create street to key map from retrieved places
236             street_to_oid = {
237                 street["value"].strip(): street["key"] for (street) in streets
238             }
239 
240             if self._street in street_to_oid:
241                 oid = street_to_oid[self._street]
242 
243         else:
244             # street specified
245             r = requests.get(
246                 f"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{oid}",
247                 params={"client": self._customer},
248             )
249             r.raise_for_status()
250             streets = r.json()
251 
252             # create street to key map from retrieved places
253             street_to_oid = {
254                 street["value"].strip(): street["key"] for (street) in streets
255             }
256 
257             if self._street not in street_to_oid:
258                 raise Exception(f"street not found: {self._street}")
259 
260             oid = street_to_oid[self._street]
261 
262             if self._housenumber is not None:
263                 r = requests.get(
264                     f"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getStreetAddons/{oid}",
265                     params={"client": self._customer},
266                 )
267                 r.raise_for_status()
268                 hsnbrs = r.json()
269 
270                 # create housenumber to key map from retrieved places
271                 hsnbr_to_oid = {
272                     hsnbr["value"].strip(): hsnbr["key"] for (hsnbr) in hsnbrs
273                 }
274 
275                 if self._housenumber not in hsnbr_to_oid:
276                     raise Exception(f"housenumber not found: {self._housenumber}")
277 
278                 oid = hsnbr_to_oid[self._housenumber]
279 
280         # get calendar data
281         r = requests.get(
282             f"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getData/{oid}",
283             params={"fractions": "", "client": self._customer},
284         )
285         r.raise_for_status()
286         cal_json = r.json()
287 
288         # map fraction code to fraction name
289         fractions = {fract["snm"]: fract["nm"] for (fract) in cal_json["fracts"]}
290 
291         # calendar also contains public holidays. In this case, 'ad' is None
292         calendar = [item for item in cal_json["calendar"] if item["ad"] is not None]
293 
294         entries = []
295         for calitem in calendar:
296             date = datetime.datetime.strptime(calitem["dt"], "%Y%m%d").date()
297 
298             # add all fractions for this date
299             for fracitem in calitem["fr"]:
300                 waste_type = fractions[fracitem]
301                 entries.append(Collection(date, waste_type))
302 
303         return entries
304
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py
--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py
+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py
@@ -194,6 +194,12 @@
         "street": "Rehgrund",
     },
     "Tübingen, Dettenhausen": {"customer": "tuebingen", "city": "Dettenhausen"},
+    "Berchtesgadener Land": {
+        "customer": "bgl",
+        "city": "Laufen",
+        "street": "Ahornweg",
+        "housenumber": 1,
+    },
 }
 
 _LOGGER = logging.getLogger(__name__)
@@ -204,7 +210,7 @@
         self._customer = customer
         self._city = city
         self._street = street
-        self._housenumber = housenumber
+        self._housenumber = None if housenumber is None else str(housenumber)
 
     def fetch(self):
         # Retrieve list of places

{"golden_diff": "diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py\n--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py\n+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py\n@@ -194,6 +194,12 @@\n         \"street\": \"Rehgrund\",\n     },\n     \"T\u00fcbingen, Dettenhausen\": {\"customer\": \"tuebingen\", \"city\": \"Dettenhausen\"},\n+    \"Berchtesgadener Land\": {\n+        \"customer\": \"bgl\",\n+        \"city\": \"Laufen\",\n+        \"street\": \"Ahornweg\",\n+        \"housenumber\": 1,\n+    },\n }\n \n _LOGGER = logging.getLogger(__name__)\n@@ -204,7 +210,7 @@\n         self._customer = customer\n         self._city = city\n         self._street = street\n-        self._housenumber = housenumber\n+        self._housenumber = None if housenumber is None else str(housenumber)\n \n     def fetch(self):\n         # Retrieve list of places\n", "issue": "Problems with awido_de\nHello,\r\n\r\ni have a problem with the awido_de calander :(\r\n\r\n\r\nLog:\r\n```\r\n2023-01-09 20:43:52.963 ERROR (SyncWorker_4) [waste_collection_schedule.source_shell] fetch failed for source AWIDO Online:\r\nFile \"/config/custom_components/waste_collection_schedule/waste_collection_schedule/source_shell.py\", line 134, in fetch\r\nFile \"/config/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py\", line 108, in fetch\r\n\r\n```\r\n\r\nconfiguration.yaml\r\n```\r\nwaste_collection_schedule:\r\n  sources:\r\n    - name: awido_de\r\n      args:\r\n        customer: \"bgl\"\r\n        city: \"Laufen\"\r\n        street: \"XXX Str.\"\r\n        housenumber: 1\r\n```\r\n\r\nSetup:\r\n```\r\nHome Assistant 2023.1.2\r\nFrontend 20230104.0 - latest\r\nInstallation: Docker\r\nWaste Collection Schedule 1.33.0\r\n```\r\n\r\nAny ideas?\r\n\r\nRegards,\r\nChristian\n", "before_files": [{"content": "import datetime\nimport logging\n\nimport requests\nfrom waste_collection_schedule import Collection  # type: ignore[attr-defined]\n\nTITLE = \"AWIDO Online\"\nDESCRIPTION = \"Source for AWIDO waste collection.\"\nURL = \"https://www.awido-online.de/\"\n\n\ndef EXTRA_INFO():\n    return [{\"title\": s[\"title\"], \"url\": s[\"url\"]} for s in SERVICE_MAP]\n\n\nSERVICE_MAP = [\n    {\n        \"title\": \"Abfallwirtschaft Rems-Murr\",\n        \"url\": \"https://www.abfallwirtschaft-rems-murr.de/\",\n        \"service_id\": \"rmk\",\n    },\n    {\n        \"title\": \"Landkreis Schweinfurt\",\n        \"url\": \"https://www.landkreis-schweinfurt.de\",\n        \"service_id\": \"lra-schweinfurt\",\n    },\n    {\n        \"title\": \"Landkreis Gotha\",\n        \"url\": \"https://www.landkreis-gotha.de/\",\n        \"service_id\": \"gotha\",\n    },\n    {\n        \"title\": \"Zweckverband Abfallwirtschaft Saale-Orla\",\n        \"url\": \"https://www.zaso-online.de/\",\n        \"service_id\": \"zaso\",\n    },\n    {\n        \"title\": \"Gemeinde Unterhaching\",\n        \"url\": \"https://www.unterhaching.de/\",\n        \"service_id\": \"unterhaching\",\n    },\n    {\n        \"title\": \"Stadt Kaufbeuren\",\n        \"url\": \"https://www.kaufbeuren.de/\",\n        \"service_id\": \"kaufbeuren\",\n    },\n    {\n        \"title\": \"Landkreis Berchtesgadener Land\",\n        \"url\": \"https://www.lra-bgl.de/\",\n        \"service_id\": \"bgl\",\n    },\n    {\n        \"title\": \"Pullach im Isartal\",\n        \"url\": \"https://www.pullach.de/\",\n        \"service_id\": \"pullach\",\n    },\n    {\n        \"title\": \"AWB Landkreis F\u00fcrstenfeldbruck\",\n        \"url\": \"https://www.awb-ffb.de/\",\n        \"service_id\": \"ffb\",\n    },\n    {\n        \"title\": \"Stadt Unterschlei\u00dfheim\",\n        \"url\": \"https://www.unterschleissheim.de/\",\n        \"service_id\": \"unterschleissheim\",\n    },\n    {\n        \"title\": \"Landkreis Tirschenreuth\",\n        \"url\": \"https://www.kreis-tir.de/\",\n        \"service_id\": \"kreis-tir\",\n    },\n    {\n        \"title\": \"Landkreis Rosenheim\",\n        \"url\": \"https://www.abfall.landkreis-rosenheim.de/\",\n        \"service_id\": \"rosenheim\",\n    },\n    {\n        \"title\": \"Landkreis T\u00fcbingen\",\n        \"url\": \"https://www.abfall-kreis-tuebingen.de/\",\n        \"service_id\": \"tuebingen\",\n    },\n    {\n        \"title\": \"Landkreis Kronach\",\n        \"url\": \"https://www.landkreis-kronach.de/\",\n        \"service_id\": \"kronach\",\n    },\n    {\n        \"title\": \"Landkreis Erding\",\n        \"url\": \"https://www.landkreis-erding.de/\",\n        \"service_id\": \"erding\",\n    },\n    {\n        \"title\": \"Zweckverband M\u00fcnchen-S\u00fcdost\",\n        \"url\": \"https://www.zvmso.de/\",\n        \"service_id\": \"zv-muc-so\",\n    },\n    {\n        \"title\": \"Landkreis Coburg\",\n        \"url\": \"https://www.landkreis-coburg.de/\",\n        \"service_id\": \"coburg\",\n    },\n    {\n        \"title\": \"Landkreis Ansbach\",\n        \"url\": \"https://www.landkreis-ansbach.de/\",\n        \"service_id\": \"ansbach\",\n    },\n    {\n        \"title\": \"AWB Landkreis Bad D\u00fcrkheim\",\n        \"url\": \"http://awb.kreis-bad-duerkheim.de/\",\n        \"service_id\": \"awb-duerkheim\",\n    },\n    {\n        \"title\": \"Landratsamt Aichach-Friedberg\",\n        \"url\": \"https://lra-aic-fdb.de/\",\n        \"service_id\": \"aic-fdb\",\n    },\n    {\n        \"title\": \"WGV Recycling GmbH\",\n        \"url\": \"https://wgv-quarzbichl.de/\",\n        \"service_id\": \"wgv\",\n    },\n    {\n        \"title\": \"Neustadt a.d. Waldnaab\",\n        \"url\": \"https://www.neustadt.de/\",\n        \"service_id\": \"neustadt\",\n    },\n    {\n        \"title\": \"Landkreis Kelheim\",\n        \"url\": \"https://www.landkreis-kelheim.de/\",\n        \"service_id\": \"kelheim\",\n    },\n    {\n        \"title\": \"Landkreis G\u00fcnzburg\",\n        \"url\": \"https://kaw.landkreis-guenzburg.de/\",\n        \"service_id\": \"kaw-guenzburg\",\n    },\n    {\n        \"title\": \"Stadt Memmingen\",\n        \"url\": \"https://umwelt.memmingen.de/\",\n        \"service_id\": \"memmingen\",\n    },\n    {\n        \"title\": \"Landkreis S\u00fcdliche Weinstra\u00dfe\",\n        \"url\": \"https://www.suedliche-weinstrasse.de/\",\n        \"service_id\": \"eww-suew\",\n    },\n    {\n        \"title\": \"Landratsamt Dachau\",\n        \"url\": \"https://www.landratsamt-dachau.de/\",\n        \"service_id\": \"lra-dah\",\n    },\n    {\n        \"title\": \"Landkreisbetriebe Neuburg-Schrobenhausen\",\n        \"url\": \"https://www.landkreisbetriebe.de/\",\n        \"service_id\": \"landkreisbetriebe\",\n    },\n    {\n        \"title\": \"Abfallwirtschaftsbetrieb Landkreis Altenkirchen\",\n        \"url\": \"https://www.awb-ak.de/\",\n        \"service_id\": \"awb-ak\",\n    },\n    {\n        \"title\": \"Abfallwirtschaft Lahn-Dill-Kreises\",\n        \"url\": \"https://www.awld.de/\",\n        \"service_id\": \"awld\",\n    },\n    {\n        \"title\": \"Abfallwirtschafts-Zweckverband des Landkreises Hersfeld-Rotenburg\",\n        \"url\": \"https://www.azv-hef-rof.de/\",\n        \"service_id\": \"azv-hef-rof\",\n    },\n    {\n        \"title\": \"Abfall-Wirtschafts-Verband Nordschwaben\",\n        \"url\": \"https://www.awv-nordschwaben.de/\",\n        \"service_id\": \"awv-nordschwaben\",\n    },\n]\nTEST_CASES = {\n    \"Schorndorf, Miedelsbacher Stra\u00dfe 30 /1\": {\n        \"customer\": \"rmk\",\n        \"city\": \"Schorndorf\",\n        \"street\": \"Miedelsbacher Stra\u00dfe\",\n        \"housenumber\": \"30 /1\",\n    },\n    \"Altom\u00fcnster, Maisbrunn\": {\n        \"customer\": \"lra-dah\",\n        \"city\": \"Altom\u00fcnster\",\n        \"street\": \"Maisbrunn\",\n    },\n    \"SOK-Alsmannsdorf\": {\"customer\": \"zaso\", \"city\": \"SOK-Alsmannsdorf\"},\n    \"Kaufbeuren, Rehgrund\": {\n        \"customer\": \"kaufbeuren\",\n        \"city\": \"Kaufbeuren\",\n        \"street\": \"Rehgrund\",\n    },\n    \"T\u00fcbingen, Dettenhausen\": {\"customer\": \"tuebingen\", \"city\": \"Dettenhausen\"},\n}\n\n_LOGGER = logging.getLogger(__name__)\n\n\nclass Source:\n    def __init__(self, customer, city, street=None, housenumber=None):\n        self._customer = customer\n        self._city = city\n        self._street = street\n        self._housenumber = housenumber\n\n    def fetch(self):\n        # Retrieve list of places\n        r = requests.get(\n            f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getPlaces/client={self._customer}\"\n        )\n        r.raise_for_status()\n        places = r.json()\n\n        # create city to key map from retrieved places\n        city_to_oid = {place[\"value\"].strip(): place[\"key\"] for (place) in places}\n\n        if self._city not in city_to_oid:\n            raise Exception(f\"city not found: {self._city}\")\n\n        oid = city_to_oid[self._city]\n\n        if self._street is None:\n            # test if we have to use city also as street name\n            self._street = self._city\n            r = requests.get(\n                f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{oid}\",\n                params={\"client\": self._customer},\n            )\n            r.raise_for_status()\n            streets = r.json()\n\n            # create street to key map from retrieved places\n            street_to_oid = {\n                street[\"value\"].strip(): street[\"key\"] for (street) in streets\n            }\n\n            if self._street in street_to_oid:\n                oid = street_to_oid[self._street]\n\n        else:\n            # street specified\n            r = requests.get(\n                f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{oid}\",\n                params={\"client\": self._customer},\n            )\n            r.raise_for_status()\n            streets = r.json()\n\n            # create street to key map from retrieved places\n            street_to_oid = {\n                street[\"value\"].strip(): street[\"key\"] for (street) in streets\n            }\n\n            if self._street not in street_to_oid:\n                raise Exception(f\"street not found: {self._street}\")\n\n            oid = street_to_oid[self._street]\n\n            if self._housenumber is not None:\n                r = requests.get(\n                    f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getStreetAddons/{oid}\",\n                    params={\"client\": self._customer},\n                )\n                r.raise_for_status()\n                hsnbrs = r.json()\n\n                # create housenumber to key map from retrieved places\n                hsnbr_to_oid = {\n                    hsnbr[\"value\"].strip(): hsnbr[\"key\"] for (hsnbr) in hsnbrs\n                }\n\n                if self._housenumber not in hsnbr_to_oid:\n                    raise Exception(f\"housenumber not found: {self._housenumber}\")\n\n                oid = hsnbr_to_oid[self._housenumber]\n\n        # get calendar data\n        r = requests.get(\n            f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getData/{oid}\",\n            params={\"fractions\": \"\", \"client\": self._customer},\n        )\n        r.raise_for_status()\n        cal_json = r.json()\n\n        # map fraction code to fraction name\n        fractions = {fract[\"snm\"]: fract[\"nm\"] for (fract) in cal_json[\"fracts\"]}\n\n        # calendar also contains public holidays. In this case, 'ad' is None\n        calendar = [item for item in cal_json[\"calendar\"] if item[\"ad\"] is not None]\n\n        entries = []\n        for calitem in calendar:\n            date = datetime.datetime.strptime(calitem[\"dt\"], \"%Y%m%d\").date()\n\n            # add all fractions for this date\n            for fracitem in calitem[\"fr\"]:\n                waste_type = fractions[fracitem]\n                entries.append(Collection(date, waste_type))\n\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py"}], "after_files": [{"content": "import datetime\nimport logging\n\nimport requests\nfrom waste_collection_schedule import Collection  # type: ignore[attr-defined]\n\nTITLE = \"AWIDO Online\"\nDESCRIPTION = \"Source for AWIDO waste collection.\"\nURL = \"https://www.awido-online.de/\"\n\n\ndef EXTRA_INFO():\n    return [{\"title\": s[\"title\"], \"url\": s[\"url\"]} for s in SERVICE_MAP]\n\n\nSERVICE_MAP = [\n    {\n        \"title\": \"Abfallwirtschaft Rems-Murr\",\n        \"url\": \"https://www.abfallwirtschaft-rems-murr.de/\",\n        \"service_id\": \"rmk\",\n    },\n    {\n        \"title\": \"Landkreis Schweinfurt\",\n        \"url\": \"https://www.landkreis-schweinfurt.de\",\n        \"service_id\": \"lra-schweinfurt\",\n    },\n    {\n        \"title\": \"Landkreis Gotha\",\n        \"url\": \"https://www.landkreis-gotha.de/\",\n        \"service_id\": \"gotha\",\n    },\n    {\n        \"title\": \"Zweckverband Abfallwirtschaft Saale-Orla\",\n        \"url\": \"https://www.zaso-online.de/\",\n        \"service_id\": \"zaso\",\n    },\n    {\n        \"title\": \"Gemeinde Unterhaching\",\n        \"url\": \"https://www.unterhaching.de/\",\n        \"service_id\": \"unterhaching\",\n    },\n    {\n        \"title\": \"Stadt Kaufbeuren\",\n        \"url\": \"https://www.kaufbeuren.de/\",\n        \"service_id\": \"kaufbeuren\",\n    },\n    {\n        \"title\": \"Landkreis Berchtesgadener Land\",\n        \"url\": \"https://www.lra-bgl.de/\",\n        \"service_id\": \"bgl\",\n    },\n    {\n        \"title\": \"Pullach im Isartal\",\n        \"url\": \"https://www.pullach.de/\",\n        \"service_id\": \"pullach\",\n    },\n    {\n        \"title\": \"AWB Landkreis F\u00fcrstenfeldbruck\",\n        \"url\": \"https://www.awb-ffb.de/\",\n        \"service_id\": \"ffb\",\n    },\n    {\n        \"title\": \"Stadt Unterschlei\u00dfheim\",\n        \"url\": \"https://www.unterschleissheim.de/\",\n        \"service_id\": \"unterschleissheim\",\n    },\n    {\n        \"title\": \"Landkreis Tirschenreuth\",\n        \"url\": \"https://www.kreis-tir.de/\",\n        \"service_id\": \"kreis-tir\",\n    },\n    {\n        \"title\": \"Landkreis Rosenheim\",\n        \"url\": \"https://www.abfall.landkreis-rosenheim.de/\",\n        \"service_id\": \"rosenheim\",\n    },\n    {\n        \"title\": \"Landkreis T\u00fcbingen\",\n        \"url\": \"https://www.abfall-kreis-tuebingen.de/\",\n        \"service_id\": \"tuebingen\",\n    },\n    {\n        \"title\": \"Landkreis Kronach\",\n        \"url\": \"https://www.landkreis-kronach.de/\",\n        \"service_id\": \"kronach\",\n    },\n    {\n        \"title\": \"Landkreis Erding\",\n        \"url\": \"https://www.landkreis-erding.de/\",\n        \"service_id\": \"erding\",\n    },\n    {\n        \"title\": \"Zweckverband M\u00fcnchen-S\u00fcdost\",\n        \"url\": \"https://www.zvmso.de/\",\n        \"service_id\": \"zv-muc-so\",\n    },\n    {\n        \"title\": \"Landkreis Coburg\",\n        \"url\": \"https://www.landkreis-coburg.de/\",\n        \"service_id\": \"coburg\",\n    },\n    {\n        \"title\": \"Landkreis Ansbach\",\n        \"url\": \"https://www.landkreis-ansbach.de/\",\n        \"service_id\": \"ansbach\",\n    },\n    {\n        \"title\": \"AWB Landkreis Bad D\u00fcrkheim\",\n        \"url\": \"http://awb.kreis-bad-duerkheim.de/\",\n        \"service_id\": \"awb-duerkheim\",\n    },\n    {\n        \"title\": \"Landratsamt Aichach-Friedberg\",\n        \"url\": \"https://lra-aic-fdb.de/\",\n        \"service_id\": \"aic-fdb\",\n    },\n    {\n        \"title\": \"WGV Recycling GmbH\",\n        \"url\": \"https://wgv-quarzbichl.de/\",\n        \"service_id\": \"wgv\",\n    },\n    {\n        \"title\": \"Neustadt a.d. Waldnaab\",\n        \"url\": \"https://www.neustadt.de/\",\n        \"service_id\": \"neustadt\",\n    },\n    {\n        \"title\": \"Landkreis Kelheim\",\n        \"url\": \"https://www.landkreis-kelheim.de/\",\n        \"service_id\": \"kelheim\",\n    },\n    {\n        \"title\": \"Landkreis G\u00fcnzburg\",\n        \"url\": \"https://kaw.landkreis-guenzburg.de/\",\n        \"service_id\": \"kaw-guenzburg\",\n    },\n    {\n        \"title\": \"Stadt Memmingen\",\n        \"url\": \"https://umwelt.memmingen.de/\",\n        \"service_id\": \"memmingen\",\n    },\n    {\n        \"title\": \"Landkreis S\u00fcdliche Weinstra\u00dfe\",\n        \"url\": \"https://www.suedliche-weinstrasse.de/\",\n        \"service_id\": \"eww-suew\",\n    },\n    {\n        \"title\": \"Landratsamt Dachau\",\n        \"url\": \"https://www.landratsamt-dachau.de/\",\n        \"service_id\": \"lra-dah\",\n    },\n    {\n        \"title\": \"Landkreisbetriebe Neuburg-Schrobenhausen\",\n        \"url\": \"https://www.landkreisbetriebe.de/\",\n        \"service_id\": \"landkreisbetriebe\",\n    },\n    {\n        \"title\": \"Abfallwirtschaftsbetrieb Landkreis Altenkirchen\",\n        \"url\": \"https://www.awb-ak.de/\",\n        \"service_id\": \"awb-ak\",\n    },\n    {\n        \"title\": \"Abfallwirtschaft Lahn-Dill-Kreises\",\n        \"url\": \"https://www.awld.de/\",\n        \"service_id\": \"awld\",\n    },\n    {\n        \"title\": \"Abfallwirtschafts-Zweckverband des Landkreises Hersfeld-Rotenburg\",\n        \"url\": \"https://www.azv-hef-rof.de/\",\n        \"service_id\": \"azv-hef-rof\",\n    },\n    {\n        \"title\": \"Abfall-Wirtschafts-Verband Nordschwaben\",\n        \"url\": \"https://www.awv-nordschwaben.de/\",\n        \"service_id\": \"awv-nordschwaben\",\n    },\n]\nTEST_CASES = {\n    \"Schorndorf, Miedelsbacher Stra\u00dfe 30 /1\": {\n        \"customer\": \"rmk\",\n        \"city\": \"Schorndorf\",\n        \"street\": \"Miedelsbacher Stra\u00dfe\",\n        \"housenumber\": \"30 /1\",\n    },\n    \"Altom\u00fcnster, Maisbrunn\": {\n        \"customer\": \"lra-dah\",\n        \"city\": \"Altom\u00fcnster\",\n        \"street\": \"Maisbrunn\",\n    },\n    \"SOK-Alsmannsdorf\": {\"customer\": \"zaso\", \"city\": \"SOK-Alsmannsdorf\"},\n    \"Kaufbeuren, Rehgrund\": {\n        \"customer\": \"kaufbeuren\",\n        \"city\": \"Kaufbeuren\",\n        \"street\": \"Rehgrund\",\n    },\n    \"T\u00fcbingen, Dettenhausen\": {\"customer\": \"tuebingen\", \"city\": \"Dettenhausen\"},\n    \"Berchtesgadener Land\": {\n        \"customer\": \"bgl\",\n        \"city\": \"Laufen\",\n        \"street\": \"Ahornweg\",\n        \"housenumber\": 1,\n    },\n}\n\n_LOGGER = logging.getLogger(__name__)\n\n\nclass Source:\n    def __init__(self, customer, city, street=None, housenumber=None):\n        self._customer = customer\n        self._city = city\n        self._street = street\n        self._housenumber = None if housenumber is None else str(housenumber)\n\n    def fetch(self):\n        # Retrieve list of places\n        r = requests.get(\n            f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getPlaces/client={self._customer}\"\n        )\n        r.raise_for_status()\n        places = r.json()\n\n        # create city to key map from retrieved places\n        city_to_oid = {place[\"value\"].strip(): place[\"key\"] for (place) in places}\n\n        if self._city not in city_to_oid:\n            raise Exception(f\"city not found: {self._city}\")\n\n        oid = city_to_oid[self._city]\n\n        if self._street is None:\n            # test if we have to use city also as street name\n            self._street = self._city\n            r = requests.get(\n                f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{oid}\",\n                params={\"client\": self._customer},\n            )\n            r.raise_for_status()\n            streets = r.json()\n\n            # create street to key map from retrieved places\n            street_to_oid = {\n                street[\"value\"].strip(): street[\"key\"] for (street) in streets\n            }\n\n            if self._street in street_to_oid:\n                oid = street_to_oid[self._street]\n\n        else:\n            # street specified\n            r = requests.get(\n                f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{oid}\",\n                params={\"client\": self._customer},\n            )\n            r.raise_for_status()\n            streets = r.json()\n\n            # create street to key map from retrieved places\n            street_to_oid = {\n                street[\"value\"].strip(): street[\"key\"] for (street) in streets\n            }\n\n            if self._street not in street_to_oid:\n                raise Exception(f\"street not found: {self._street}\")\n\n            oid = street_to_oid[self._street]\n\n            if self._housenumber is not None:\n                r = requests.get(\n                    f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getStreetAddons/{oid}\",\n                    params={\"client\": self._customer},\n                )\n                r.raise_for_status()\n                hsnbrs = r.json()\n\n                # create housenumber to key map from retrieved places\n                hsnbr_to_oid = {\n                    hsnbr[\"value\"].strip(): hsnbr[\"key\"] for (hsnbr) in hsnbrs\n                }\n\n                if self._housenumber not in hsnbr_to_oid:\n                    raise Exception(f\"housenumber not found: {self._housenumber}\")\n\n                oid = hsnbr_to_oid[self._housenumber]\n\n        # get calendar data\n        r = requests.get(\n            f\"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getData/{oid}\",\n            params={\"fractions\": \"\", \"client\": self._customer},\n        )\n        r.raise_for_status()\n        cal_json = r.json()\n\n        # map fraction code to fraction name\n        fractions = {fract[\"snm\"]: fract[\"nm\"] for (fract) in cal_json[\"fracts\"]}\n\n        # calendar also contains public holidays. In this case, 'ad' is None\n        calendar = [item for item in cal_json[\"calendar\"] if item[\"ad\"] is not None]\n\n        entries = []\n        for calitem in calendar:\n            date = datetime.datetime.strptime(calitem[\"dt\"], \"%Y%m%d\").date()\n\n            # add all fractions for this date\n            for fracitem in calitem[\"fr\"]:\n                waste_type = fractions[fracitem]\n                entries.append(Collection(date, waste_type))\n\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py"}]}