prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  data.umweltprofis.at: iCal service retired
  I had to change the interval in my data.umweltprofis.at waste schedule when I noticed that the server throws an error when requesting a new iCal link at https://data.umweltprofis.at/opendata/AppointmentService/index.aspx
  
  I contacted their support and they told me that this service is not going to be fixed because they are currently working on (another?) app.
  
  Should this integration be marked as broken for the time being? Existing iCal URLs continue to work, at least for the time being.
  
  </issue>
  <code>
  [start of custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py]
  1 import logging
  2 import requests
  3 from waste_collection_schedule import Collection  # type: ignore[attr-defined]
  4 from waste_collection_schedule.service.ICS import ICS
  5 
  6 TITLE = "UMWELTPROFIS"
  7 DESCRIPTION = "Source for Umweltprofis"
  8 URL = "https://www.umweltprofis.at"
  9 TEST_CASES = {
  10     "Ebensee": {"url": "https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1"},
  11 }
  12 
  13 _LOGGER = logging.getLogger(__name__)
  14 
  15 
  16 class Source:
  17     def __init__(self, url):
  18         self._url = url
  19         self._ics = ICS()
  20 
  21     def fetch(self):
  22         r = requests.get(self._url)
  23         if r.status_code != 200:
  24             _LOGGER.error("Error querying calendar data")
  25             return []
  26 
  27         fixed_text = r.text.replace("REFRESH - INTERVAL; VALUE = ", "REFRESH-INTERVAL;VALUE=")
  28 
  29         dates = self._ics.convert(fixed_text)
  30 
  31         entries = []
  32         for d in dates:
  33             entries.append(Collection(d[0], d[1]))
  34         return entries
  35
  [end of custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py
  --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py
  +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py
  @@ -1,5 +1,7 @@
   import logging
   import requests
  +from datetime import datetime
  +from xml.dom.minidom import parseString
   from waste_collection_schedule import Collection  # type: ignore[attr-defined]
   from waste_collection_schedule.service.ICS import ICS
   
  @@ -8,17 +10,33 @@
   URL = "https://www.umweltprofis.at"
   TEST_CASES = {
       "Ebensee": {"url": "https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1"},
  +    "Rohrbach": {"xmlurl": "https://data.umweltprofis.at/opendata/AppointmentService/AppointmentService.asmx/GetTermineForLocationSecured?Key=TEMPKeyabvvMKVCic0cMcmsTEMPKey&StreetNr=118213&HouseNr=Alle&intervall=Alle"},
   }
   
   _LOGGER = logging.getLogger(__name__)
   
  +def getText(element):
  +    s = ""
  +    for e in element.childNodes:
  +        if e.nodeType == e.TEXT_NODE:
  +            s += e.nodeValue
  +    return s
   
   class Source:
  -    def __init__(self, url):
  +    def __init__(self, url=None, xmlurl=None):
           self._url = url
  +        self._xmlurl = xmlurl
           self._ics = ICS()
  +        if url is None and xmlurl is None:
  +            raise Exception("either url or xmlurl needs to be specified")
   
       def fetch(self):
  +        if self._url is not None:
  +            return self.fetch_ics()
  +        elif self._xmlurl is not None:
  +            return self.fetch_xml()
  +
  +    def fetch_ics(self):
           r = requests.get(self._url)
           if r.status_code != 200:
               _LOGGER.error("Error querying calendar data")
  @@ -32,3 +50,18 @@
           for d in dates:
               entries.append(Collection(d[0], d[1]))
           return entries
  +
  +    def fetch_xml(self):
  +        r = requests.get(self._xmlurl)
  +        r.raise_for_status()
  +
  +        doc = parseString(r.text)
  +        appointments = doc.getElementsByTagName("AppointmentEntry")
  +
  +        entries = []
  +        for a in appointments:
  +            date_string = getText(a.getElementsByTagName("Datum")[0])
  +            date = datetime.fromisoformat(date_string).date()
  +            waste_type = getText(a.getElementsByTagName("WasteType")[0])
  +            entries.append(Collection(date, waste_type))
  +        return entries
  
verification_info: {"golden_diff": "diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py\n--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py\n+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py\n@@ -1,5 +1,7 @@\n import logging\n import requests\n+from datetime import datetime\n+from xml.dom.minidom import parseString\n from waste_collection_schedule import Collection  # type: ignore[attr-defined]\n from waste_collection_schedule.service.ICS import ICS\n \n@@ -8,17 +10,33 @@\n URL = \"https://www.umweltprofis.at\"\n TEST_CASES = {\n     \"Ebensee\": {\"url\": \"https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1\"},\n+    \"Rohrbach\": {\"xmlurl\": \"https://data.umweltprofis.at/opendata/AppointmentService/AppointmentService.asmx/GetTermineForLocationSecured?Key=TEMPKeyabvvMKVCic0cMcmsTEMPKey&StreetNr=118213&HouseNr=Alle&intervall=Alle\"},\n }\n \n _LOGGER = logging.getLogger(__name__)\n \n+def getText(element):\n+    s = \"\"\n+    for e in element.childNodes:\n+        if e.nodeType == e.TEXT_NODE:\n+            s += e.nodeValue\n+    return s\n \n class Source:\n-    def __init__(self, url):\n+    def __init__(self, url=None, xmlurl=None):\n         self._url = url\n+        self._xmlurl = xmlurl\n         self._ics = ICS()\n+        if url is None and xmlurl is None:\n+            raise Exception(\"either url or xmlurl needs to be specified\")\n \n     def fetch(self):\n+        if self._url is not None:\n+            return self.fetch_ics()\n+        elif self._xmlurl is not None:\n+            return self.fetch_xml()\n+\n+    def fetch_ics(self):\n         r = requests.get(self._url)\n         if r.status_code != 200:\n             _LOGGER.error(\"Error querying calendar data\")\n@@ -32,3 +50,18 @@\n         for d in dates:\n             entries.append(Collection(d[0], d[1]))\n         return entries\n+\n+    def fetch_xml(self):\n+        r = requests.get(self._xmlurl)\n+        r.raise_for_status()\n+\n+        doc = parseString(r.text)\n+        appointments = doc.getElementsByTagName(\"AppointmentEntry\")\n+\n+        entries = []\n+        for a in appointments:\n+            date_string = getText(a.getElementsByTagName(\"Datum\")[0])\n+            date = datetime.fromisoformat(date_string).date()\n+            waste_type = getText(a.getElementsByTagName(\"WasteType\")[0])\n+            entries.append(Collection(date, waste_type))\n+        return entries\n", "issue": "data.umweltprofis.at: iCal service retired\nI had to change the interval in my data.umweltprofis.at waste schedule when I noticed that the server throws an error when requesting a new iCal link at https://data.umweltprofis.at/opendata/AppointmentService/index.aspx\r\n\r\nI contacted their support and they told me that this service is not going to be fixed because they are currently working on (another?) app.\r\n\r\nShould this integration be marked as broken for the time being? Existing iCal URLs continue to work, at least for the time being.\n", "before_files": [{"content": "import logging\nimport requests\nfrom waste_collection_schedule import Collection  # type: ignore[attr-defined]\nfrom waste_collection_schedule.service.ICS import ICS\n\nTITLE = \"UMWELTPROFIS\"\nDESCRIPTION = \"Source for Umweltprofis\"\nURL = \"https://www.umweltprofis.at\"\nTEST_CASES = {\n    \"Ebensee\": {\"url\": \"https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1\"},\n}\n\n_LOGGER = logging.getLogger(__name__)\n\n\nclass Source:\n    def __init__(self, url):\n        self._url = url\n        self._ics = ICS()\n\n    def fetch(self):\n        r = requests.get(self._url)\n        if r.status_code != 200:\n            _LOGGER.error(\"Error querying calendar data\")\n            return []\n\n        fixed_text = r.text.replace(\"REFRESH - INTERVAL; VALUE = \", \"REFRESH-INTERVAL;VALUE=\")\n\n        dates = self._ics.convert(fixed_text)\n\n        entries = []\n        for d in dates:\n            entries.append(Collection(d[0], d[1]))\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py"}]}