diff --git a/icalevents/icaldownload.py b/icalevents/icaldownload.py index 04578c9..d94f04a 100644 --- a/icalevents/icaldownload.py +++ b/icalevents/icaldownload.py @@ -2,7 +2,7 @@ Downloads an iCal url or reads an iCal file. """ -from httplib2 import Http +import urllib3 import logging @@ -33,25 +33,15 @@ class ICalDownload: Downloads or reads and decodes iCal sources. """ - def __init__(self, http=None, encoding="utf-8"): + def __init__(self, http=None): # Get logger logger = logging.getLogger() # default http connection to use if http is None: - try: - http = Http(".cache") - except (PermissionError, OSError) as e: - # Cache disabled if no write permission in working directory - logger.warning( - ( - "Caching is disabled due to a read-only working directory: {}" - ).format(e) - ) - http = Http() + http = urllib3.PoolManager() self.http = http - self.encoding = encoding def data_from_url(self, url, apple_fix=False): """ @@ -64,12 +54,19 @@ def data_from_url(self, url, apple_fix=False): if apple_fix: url = apple_url_fix(url) - _, content = self.http.request(url) + response = self.http.request("GET", url) - if not content: + if not response.data: raise ConnectionError("Could not get data from %s!" % url) - return self.decode(content, apple_fix=apple_fix) + content_type = response.headers.get("content-type") + + try: + encoding = content_type.split("charset=")[1] + except (AttributeError, IndexError): + encoding = "utf-8" + + return self.decode(response.data, encoding, apple_fix=apple_fix) def data_from_file(self, file, apple_fix=False): """ @@ -93,15 +90,17 @@ def data_from_string(self, string_content, apple_fix=False): return self.decode(string_content, apple_fix=apple_fix) - def decode(self, content, apple_fix=False): + @staticmethod + def decode(content, encoding="utf-8", apple_fix=False): """ Decode content using the set charset. :param content: content do decode + :param encoding: the used charset for decoding the content :param apple_fix: fix Apple txdata bug :return: decoded (and fixed) content """ - content = content.decode(self.encoding) + content = content.decode(encoding) content = content.replace("\r", "") if apple_fix: diff --git a/poetry.lock b/poetry.lock index c037768..90bb93b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,25 @@ # This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. +[[package]] +name = "attrs" +version = "24.3.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"}, + {file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"}, +] + +[package.extras] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] + [[package]] name = "black" version = "24.10.0" @@ -184,19 +204,20 @@ pycodestyle = ">=2.12.0,<2.13.0" pyflakes = ">=3.2.0,<3.3.0" [[package]] -name = "httplib2" -version = "0.22.0" -description = "A comprehensive HTTP client library." +name = "furl" +version = "2.1.3" +description = "URL manipulation made simple." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] +python-versions = "*" +groups = ["dev"] files = [ - {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, - {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, + {file = "furl-2.1.3-py2.py3-none-any.whl", hash = "sha256:9ab425062c4217f9802508e45feb4a83e54324273ac4b202f1850363309666c0"}, + {file = "furl-2.1.3.tar.gz", hash = "sha256:5a6188fe2666c484a12159c18be97a1977a71d632ef5bb867ef15f54af39cc4e"}, ] [package.dependencies] -pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} +orderedmultidict = ">=1.0.1" +six = ">=1.8.0" [[package]] name = "icalendar" @@ -229,6 +250,43 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "jsonschema" +version = "4.23.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, + {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] + +[[package]] +name = "jsonschema-specifications" +version = "2024.10.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"}, + {file = "jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + [[package]] name = "mccabe" version = "0.7.0" @@ -253,6 +311,21 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "orderedmultidict" +version = "1.0.1" +description = "Ordered Multivalue Dictionary" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "orderedmultidict-1.0.1-py2.py3-none-any.whl", hash = "sha256:43c839a17ee3cdd62234c47deca1a8508a3f2ca1d0678a3bf791c87cf84adbf3"}, + {file = "orderedmultidict-1.0.1.tar.gz", hash = "sha256:04070bbb5e87291cc9bfa51df413677faf2141c73c61d2a5f7b26bea3cd882ad"}, +] + +[package.dependencies] +six = ">=1.8.0" + [[package]] name = "packaging" version = "24.2" @@ -310,6 +383,23 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "pook" +version = "2.1.3" +description = "HTTP traffic mocking and expectations made easy" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pook-2.1.3-py3-none-any.whl", hash = "sha256:f8e75e2e41b1f6da37d0bc6b77a0f4da33c4d4de382105046efd644fe5ca2f8e"}, + {file = "pook-2.1.3.tar.gz", hash = "sha256:441191c0f3d014b141ca71430a0c2bfa6d2369ac24703a3fdfbbf5a25146d8c0"}, +] + +[package.dependencies] +furl = ">=0.5.6" +jsonschema = ">=2.5.1" +xmltodict = ">=0.11.0" + [[package]] name = "pycodestyle" version = "2.12.1" @@ -334,21 +424,6 @@ files = [ {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, ] -[[package]] -name = "pyparsing" -version = "3.2.1" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1"}, - {file = "pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - [[package]] name = "pytest" version = "8.3.4" @@ -399,13 +474,143 @@ files = [ {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, ] +[[package]] +name = "referencing" +version = "0.36.1" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "referencing-0.36.1-py3-none-any.whl", hash = "sha256:363d9c65f080d0d70bc41c721dce3c7f3e77fc09f269cd5c8813da18069a6794"}, + {file = "referencing-0.36.1.tar.gz", hash = "sha256:ca2e6492769e3602957e9b831b94211599d2aade9477f5d44110d2530cf9aade"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" +typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} + +[[package]] +name = "rpds-py" +version = "0.22.3" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "rpds_py-0.22.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967"}, + {file = "rpds_py-0.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf"}, + {file = "rpds_py-0.22.3-cp310-cp310-win32.whl", hash = "sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652"}, + {file = "rpds_py-0.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8"}, + {file = "rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f"}, + {file = "rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a"}, + {file = "rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64"}, + {file = "rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c"}, + {file = "rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e"}, + {file = "rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7"}, + {file = "rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627"}, + {file = "rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4"}, + {file = "rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84"}, + {file = "rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f"}, + {file = "rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de"}, + {file = "rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9"}, + {file = "rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333"}, + {file = "rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730"}, + {file = "rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf"}, + {file = "rpds_py-0.22.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea"}, + {file = "rpds_py-0.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520"}, + {file = "rpds_py-0.22.3-cp39-cp39-win32.whl", hash = "sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9"}, + {file = "rpds_py-0.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6"}, + {file = "rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d"}, +] + [[package]] name = "six" version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -461,7 +666,7 @@ description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version < \"3.11\"" +markers = "python_version < \"3.13\"" files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -479,7 +684,37 @@ files = [ {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, ] +[[package]] +name = "urllib3" +version = "2.3.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, + {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "xmltodict" +version = "0.14.2" +description = "Makes working with XML feel like you are working with JSON" +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, + {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, +] + [metadata] lock-version = "2.1" python-versions = ">=3.9" -content-hash = "9202c0e82a6a86526c87f88c1aab08323450d3b303977e6f61e8ffa7e1e114db" +content-hash = "8fc64de4f55b234589828215b2dca5a673f1772127f00a7eb4708a634ed109a4" diff --git a/pyproject.toml b/pyproject.toml index 8f6a259..fd8350b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ dependencies = [ "icalendar (~=6.0)", "python-dateutil (~=2.9)", "pytz (>=2024.2)", - "httplib2 (~=0.22)", + "urllib3 (>=1.26.5)", ] [tool.poetry] @@ -26,6 +26,7 @@ coverage = "^7.6.10" pytest = "^8.3.4" black = "^24.10.0" flake8 = "^7.1.1" +pook = "^2.1.3" [build-system] requires = ["poetry-core>=2.0"] diff --git a/test/test_data/basic_latin1.ics b/test/test_data/basic_latin1.ics new file mode 100644 index 0000000..0506618 --- /dev/null +++ b/test/test_data/basic_latin1.ics @@ -0,0 +1,1508 @@ +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:Müll +X-WR-TIMEZONE:Europe/Berlin +X-WR-CALDESC:Müllabholung Treuchtlingen Luitpoldstraße +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170712 +DTEND;VALUE=DATE:20170713 +DTSTAMP:20170711T171222Z +UID:0eedefedba891fcbb49dcfa4279d9d93 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170711T160050Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170712 +DTEND;VALUE=DATE:20170713 +DTSTAMP:20170711T171222Z +UID:e122da9cfb107b38516b45571d212f4f +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170711T160048Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170626 +DTEND;VALUE=DATE:20170627 +DTSTAMP:20170711T171222Z +UID:efe9e2c0be259e0f3aabd383ee6c4d15 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170625T160105Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170622 +DTEND;VALUE=DATE:20170623 +DTSTAMP:20170711T171222Z +UID:07c802ef4f8fe50f95faf0ac95ac881c +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170621T144339Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170614 +DTEND;VALUE=DATE:20170615 +DTSTAMP:20170711T171222Z +UID:7c994ff7de1de11183053c180adfc867 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170613T173416Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC +BEGIN:VALARM +ACTION:AUDIO +TRIGGER:-PT15H +X-WR-ALARMUID:BC3EDCEF-AAB1-4A24-AB4D-69B6B4A9F597 +UID:BC3EDCEF-AAB1-4A24-AB4D-69B6B4A9F597 +ATTACH;VALUE=URI:Basso +X-APPLE-DEFAULT-ALARM:TRUE +ACKNOWLEDGED:20170613T173415Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170614 +DTEND;VALUE=DATE:20170615 +DTSTAMP:20170711T171222Z +UID:36b222845f3311adc661fe262b1154b8 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170613T173340Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC +BEGIN:VALARM +ACTION:AUDIO +TRIGGER:-PT15H +X-WR-ALARMUID:E005835A-4FBA-4FC8-A8EA-3DDAFF0D195F +UID:E005835A-4FBA-4FC8-A8EA-3DDAFF0D195F +ATTACH;VALUE=URI:Basso +X-APPLE-DEFAULT-ALARM:TRUE +ACKNOWLEDGED:20170613T173339Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170608 +DTEND;VALUE=DATE:20170609 +DTSTAMP:20170711T171222Z +UID:c396c07c3daa1c21849738723d9a595e +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170608T152251Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170531 +DTEND;VALUE=DATE:20170601 +DTSTAMP:20170711T171222Z +UID:4dbfa315cac19965a33882b0aa4c9e90 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170530T082532Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170531 +DTEND;VALUE=DATE:20170601 +DTSTAMP:20170711T171222Z +UID:5ca0da577f9c2b932c2ac7b430b38ab4 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170530T082531Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170524 +DTEND;VALUE=DATE:20170525 +DTSTAMP:20170711T171222Z +UID:617bdd5b0817191ed3c8b95ec8aa910b +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170523T090111Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170524 +DTEND;VALUE=DATE:20170525 +DTSTAMP:20170711T171222Z +UID:92dddc277b05b3b25a60f3896beb85f9 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170523T090111Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170522 +DTEND;VALUE=DATE:20170523 +DTSTAMP:20170711T171222Z +UID:12a65763abc1354e36aa04e7b57d3ae0 +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170521T125619Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170517 +DTEND;VALUE=DATE:20170518 +DTSTAMP:20170711T171222Z +UID:f6e6b6d3eb68b176f8a88fbdaba6910e +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170516T092545Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170517 +DTEND;VALUE=DATE:20170518 +DTSTAMP:20170711T171222Z +UID:c49bacfe7ceb769cf61d842448dd6102 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170516T092544Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170510 +DTEND;VALUE=DATE:20170511 +DTSTAMP:20170711T171222Z +UID:0432f7eea3d2ae4032ea41bbe76392d1 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170509T160147Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170426 +DTEND;VALUE=DATE:20170427 +DTSTAMP:20170711T171222Z +UID:012af86d58d90698ea922fb6b4661b06 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170425T174313Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170424 +DTEND;VALUE=DATE:20170425 +DTSTAMP:20170711T171222Z +UID:a918e86e2a2f4c6098a7c619ae2f4a40 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170423T162255Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170412 +DTEND;VALUE=DATE:20170413 +DTSTAMP:20170711T171222Z +UID:935847042462cd08b76015c97cd90d14 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170412T155528Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170405 +DTEND;VALUE=DATE:20170406 +DTSTAMP:20170711T171222Z +UID:a6414e7f22bf7b30f45c427aaa947b4a +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170404T070148Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170329 +DTEND;VALUE=DATE:20170330 +DTSTAMP:20170711T171222Z +UID:1a567b4e0d1efc31dc7893f087697a4f +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170328T165756Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170320 +DTEND;VALUE=DATE:20170321 +DTSTAMP:20170711T171222Z +UID:7a5416a2ca1ac6d4bb77f8b94ed0a8be +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170319T131719Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC +BEGIN:VALARM +ACTION:AUDIO +TRIGGER:-PT15H +X-WR-ALARMUID:4BB6A40E-6845-4541-BD87-0962514D03DC +UID:4BB6A40E-6845-4541-BD87-0962514D03DC +ATTACH;VALUE=URI:Basso +X-APPLE-DEFAULT-ALARM:TRUE +ACKNOWLEDGED:20170319T131719Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170308 +DTEND;VALUE=DATE:20170309 +DTSTAMP:20170711T171222Z +UID:3c72a54356c95bfbfe7383d1d3d19379 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170307T100509Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC +BEGIN:VALARM +ACTION:AUDIO +TRIGGER:-PT15H +X-WR-ALARMUID:2DB10823-1AD7-4793-BC69-BC4FC1383E5E +UID:2DB10823-1AD7-4793-BC69-BC4FC1383E5E +ATTACH;VALUE=URI:Basso +X-APPLE-DEFAULT-ALARM:TRUE +ACKNOWLEDGED:20170307T100501Z +END:VALARM +BEGIN:VALARM +ACTION:AUDIO +TRIGGER;VALUE=DATE-TIME:20170307T100500Z +X-WR-ALARMUID:EE4099B4-69A5-4199-8601-F131819E01E0 +UID:EE4099B4-69A5-4199-8601-F131819E01E0 +ATTACH;VALUE=URI:Basso +RELATED-TO:2DB10823-1AD7-4793-BC69-BC4FC1383E5E +ACKNOWLEDGED:20170307T100501Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170301 +DTEND;VALUE=DATE:20170302 +DTSTAMP:20170711T171222Z +UID:0e17dbf248106fc4e0750b82204b1eb3 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170228T174301Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC +BEGIN:VALARM +ACTION:AUDIO +TRIGGER:-PT15H +X-WR-ALARMUID:BE658068-8213-4228-BE68-AF2A53D8508F +UID:BE658068-8213-4228-BE68-AF2A53D8508F +ATTACH;VALUE=URI:Basso +X-APPLE-DEFAULT-ALARM:TRUE +ACKNOWLEDGED:20170228T174318Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170215 +DTEND;VALUE=DATE:20170216 +DTSTAMP:20170711T171222Z +UID:1e540f2f49688b87332de4f74c77b9c9 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170214T182848Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170203 +DTEND;VALUE=DATE:20170204 +DTSTAMP:20170711T171222Z +UID:bd22e2dec844adf3bddca2f4c0fd2f88 +CREATED:20170103T080401Z +DESCRIPTION:Sondermüll 13.00-16.00 Volksfestplatz nicht vergessen! +LAST-MODIFIED:20170202T125220Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Sondermüll +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170201 +DTEND;VALUE=DATE:20170202 +DTSTAMP:20170711T171222Z +UID:8d6b72cc11bc18b07b6662e4230ebf6b +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170201T184715Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171027 +DTEND;VALUE=DATE:20171028 +DTSTAMP:20170711T171222Z +UID:b9f96af011f03644a186fd1633dd26c6 +CREATED:20170103T080401Z +DESCRIPTION:Sondermüll 13.00-16.00 Volksfestplatz nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Sondermüll +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170804 +DTEND;VALUE=DATE:20170805 +DTSTAMP:20170711T171222Z +UID:4cb27817622e7b3274ad087e1894572a +CREATED:20170103T080401Z +DESCRIPTION:Sondermüll 13.00-16.00 Volksfestplatz nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Sondermüll +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170422 +DTEND;VALUE=DATE:20170423 +DTSTAMP:20170711T171222Z +UID:3ab8a5bdbf22fa9b330e203611f5bcc7 +CREATED:20170103T080401Z +DESCRIPTION:Sondermüll 11.00-14.00 Volksfestplatz nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Sondermüll +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170123 +DTEND;VALUE=DATE:20170124 +DTSTAMP:20170711T171222Z +UID:e3ac69ae8d6f05c15e5c1a8e2688c9b7 +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170720 +DTEND;VALUE=DATE:20170721 +DTSTAMP:20170711T171222Z +UID:db02708b90bcac408e84a37f1f09010e +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170914 +DTEND;VALUE=DATE:20170915 +DTSTAMP:20170711T171222Z +UID:b987aeb6ceedae19a92ed8e6d47feede +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170220 +DTEND;VALUE=DATE:20170221 +DTSTAMP:20170711T171222Z +UID:ab0aaeb9d8487558c283be1422915899 +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170817 +DTEND;VALUE=DATE:20170818 +DTSTAMP:20170711T171222Z +UID:8b8b1253498443ea1dcf4996b85384dc +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171219 +DTEND;VALUE=DATE:20171220 +DTSTAMP:20170711T171222Z +UID:71cba68020f1918038e158901906c38d +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171121 +DTEND;VALUE=DATE:20171122 +DTSTAMP:20170711T171222Z +UID:3e1b9285d22c9e3fc6aea39f30dcbf32 +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170418 +DTEND;VALUE=DATE:20170419 +DTSTAMP:20170711T171222Z +UID:2dd84b7600eec3f674e2704b8b1ae442 +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171019 +DTEND;VALUE=DATE:20171020 +DTSTAMP:20170711T171222Z +UID:295a8a624928c949ece1f3991f2ab200 +CREATED:20170103T080401Z +DESCRIPTION:grüne Papiertonne und grüner 1\,1m³ Papiercontainer nicht verge + ssen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:grüne Papiertonne und grüner 1\,1m³ Papiercontainer +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171115 +DTEND;VALUE=DATE:20171116 +DTSTAMP:20170711T171222Z +UID:f84edfee25e57fec7b2a0036235ae3ef +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171129 +DTEND;VALUE=DATE:20171130 +DTSTAMP:20170711T171222Z +UID:e00a31d744277d44633bb8ff219853fb +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170823 +DTEND;VALUE=DATE:20170824 +DTSTAMP:20170711T171222Z +UID:ddf5c06a0f0ac02bebc0e8485fadd43f +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170322 +DTEND;VALUE=DATE:20170323 +DTSTAMP:20170711T171222Z +UID:dc7c42b1704baecd17811f6ccf5fb1ba +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170726 +DTEND;VALUE=DATE:20170727 +DTSTAMP:20170711T171222Z +UID:d758da5abb4acd5f3f84d25dec69ec1b +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170222 +DTEND;VALUE=DATE:20170223 +DTSTAMP:20170711T171222Z +UID:ceb59dbac23995412bfb62a59019f25c +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170920 +DTEND;VALUE=DATE:20170921 +DTSTAMP:20170711T171222Z +UID:c5f71249b1943da7bdbdad13922421cf +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170420 +DTEND;VALUE=DATE:20170421 +DTSTAMP:20170711T171222Z +UID:c14c86836347f9922f0c5d68a952dfd6 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170809 +DTEND;VALUE=DATE:20170810 +DTSTAMP:20170711T171222Z +UID:93239592ff0f8d16bf34b2aa5c7288e2 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170628 +DTEND;VALUE=DATE:20170629 +DTSTAMP:20170711T171222Z +UID:8e5e62128fe3ed2a22577725e6a605af +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170111 +DTEND;VALUE=DATE:20170112 +DTSTAMP:20170711T171222Z +UID:8c1c6aff0a57960ea573409be9c14c32 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170208 +DTEND;VALUE=DATE:20170209 +DTSTAMP:20170711T171222Z +UID:7f7f6d57ee0058e042d9da043c111cb8 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170125 +DTEND;VALUE=DATE:20170126 +DTSTAMP:20170711T171222Z +UID:68d38cb88d40779fa9aec09b84c004d8 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170906 +DTEND;VALUE=DATE:20170907 +DTSTAMP:20170711T171222Z +UID:63dc783377f10a4c141a663fcdcff2a9 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171102 +DTEND;VALUE=DATE:20171103 +DTSTAMP:20170711T171222Z +UID:5e6fc787cb425c39cb3998639b4966a7 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170504 +DTEND;VALUE=DATE:20170505 +DTSTAMP:20170711T171222Z +UID:5bf75396a5d201d18efebd220b1c1177 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171228 +DTEND;VALUE=DATE:20171229 +DTSTAMP:20170711T171222Z +UID:5a30134566e84224f30128808d89a31e +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171005 +DTEND;VALUE=DATE:20171006 +DTSTAMP:20170711T171222Z +UID:4c58836e8beaee68920f11cfbb19b820 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171018 +DTEND;VALUE=DATE:20171019 +DTSTAMP:20170711T171222Z +UID:2415471b7ab7a6aa92a84eb7fddcee92 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171213 +DTEND;VALUE=DATE:20171214 +DTSTAMP:20170711T171222Z +UID:11be18f68972fbb15e8dff78616ea3a8 +CREATED:20170103T080401Z +DESCRIPTION:graue Restmülltonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:graue Restmülltonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170322 +DTEND;VALUE=DATE:20170323 +DTSTAMP:20170711T171222Z +UID:fe7bdd0f1ae26125306052a4a03d2841 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170222 +DTEND;VALUE=DATE:20170223 +DTSTAMP:20170711T171222Z +UID:fbe837e05f4d57a238fd21f1fd990525 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170823 +DTEND;VALUE=DATE:20170824 +DTSTAMP:20170711T171222Z +UID:c5b7d52b109fbcbd55039c4d8e3fa69f +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170125 +DTEND;VALUE=DATE:20170126 +DTSTAMP:20170711T171222Z +UID:becee7d5a184726bb0096bee84297e63 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171023 +DTEND;VALUE=DATE:20171024 +DTSTAMP:20170711T171222Z +UID:aee6a98c7260300e8b857fb6c94855d2 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170726 +DTEND;VALUE=DATE:20170727 +DTSTAMP:20170711T171222Z +UID:a223fb2ab3c9c6948c2bfe17f5201fb2 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171120 +DTEND;VALUE=DATE:20171121 +DTSTAMP:20170711T171222Z +UID:7e0895d1e0462593836c6ffab1051a44 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170921 +DTEND;VALUE=DATE:20170922 +DTSTAMP:20170711T171222Z +UID:4c5c9c893de7b4f7b3900cecb8198d56 +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171220 +DTEND;VALUE=DATE:20171221 +DTSTAMP:20170711T171222Z +UID:0d3a14a2db43e83871d6e890d1bf106d +CREATED:20170103T080401Z +DESCRIPTION:Gelber Sack nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Gelber Sack +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170913 +DTEND;VALUE=DATE:20170914 +DTSTAMP:20170711T171222Z +UID:ffdb3556ae7d8e69cdf1abdb3b8724e5 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170726 +DTEND;VALUE=DATE:20170727 +DTSTAMP:20170711T171222Z +UID:eb12b8e39471d01a0731370caee3a8d9 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170920 +DTEND;VALUE=DATE:20170921 +DTSTAMP:20170711T171222Z +UID:e6b7080131d472ce18d7287d69f28f95 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170705 +DTEND;VALUE=DATE:20170706 +DTSTAMP:20170711T171222Z +UID:e3a004ecd454d47b251d9a54ca9eb1f4 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171025 +DTEND;VALUE=DATE:20171026 +DTSTAMP:20170711T171222Z +UID:e19e1c3c2a9a53087d7965bcc9ced05f +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170927 +DTEND;VALUE=DATE:20170928 +DTSTAMP:20170711T171222Z +UID:dab760f60854de69501f6f12f561640c +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170830 +DTEND;VALUE=DATE:20170831 +DTSTAMP:20170711T171222Z +UID:c8d70536a1eba5b4a75f154c2b262747 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171102 +DTEND;VALUE=DATE:20171103 +DTSTAMP:20170711T171222Z +UID:b61452b731eda4e297ddc5077371b23b +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170118 +DTEND;VALUE=DATE:20170119 +DTSTAMP:20170711T171222Z +UID:acb89bbb7132daf5d1dfad9d37465566 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171108 +DTEND;VALUE=DATE:20171109 +DTSTAMP:20170711T171222Z +UID:a93e6810ba360eea0abbc25d9625c6b5 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170621 +DTEND;VALUE=DATE:20170622 +DTSTAMP:20170711T171222Z +UID:a6718774e02d1fc560e885b555c80635 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170504 +DTEND;VALUE=DATE:20170505 +DTSTAMP:20170711T171222Z +UID:a649b385d5b63bf49c1708ee4c48e5fb +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170719 +DTEND;VALUE=DATE:20170720 +DTSTAMP:20170711T171222Z +UID:9bc9a9a7a20118f55e8f8a3874f7caee +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170906 +DTEND;VALUE=DATE:20170907 +DTSTAMP:20170711T171222Z +UID:863ef88cd36254a31ef0e940e89f7650 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170817 +DTEND;VALUE=DATE:20170818 +DTSTAMP:20170711T171222Z +UID:63d836662f6ee8fafe3dab60077da9ad +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171005 +DTEND;VALUE=DATE:20171006 +DTSTAMP:20170711T171222Z +UID:6026bb0d055caf74eac88b8b31dd7f05 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171206 +DTEND;VALUE=DATE:20171207 +DTSTAMP:20170711T171222Z +UID:58b9d72d6641e50499b527f7e2afc8de +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170809 +DTEND;VALUE=DATE:20170810 +DTSTAMP:20170711T171222Z +UID:55bb6c11f2a3556431e943f2dd10cd2c +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171122 +DTEND;VALUE=DATE:20171123 +DTSTAMP:20170711T171222Z +UID:48dc695b62a967fed5a3f4c35c082b9e +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170823 +DTEND;VALUE=DATE:20170824 +DTSTAMP:20170711T171222Z +UID:44d5882112b286940fd474c1256a330c +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170104 +DTEND;VALUE=DATE:20170105 +DTSTAMP:20170711T171222Z +UID:35b4b6d13b585bccc3d9e76f209de769 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +BEGIN:VALARM +ACTION:NONE +TRIGGER;VALUE=DATE-TIME:19760401T005545Z +END:VALARM +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170628 +DTEND;VALUE=DATE:20170629 +DTSTAMP:20170711T171222Z +UID:347383367fdf3f0f47e7c7720f626e1c +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171220 +DTEND;VALUE=DATE:20171221 +DTSTAMP:20170711T171222Z +UID:2afeb7fb18f41bcbed600c88109fb34d +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170802 +DTEND;VALUE=DATE:20170803 +DTSTAMP:20170711T171222Z +UID:22b2a3c2db5d4f5d156478197ce2f099 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20170315 +DTEND;VALUE=DATE:20170316 +DTSTAMP:20170711T171222Z +UID:1c9b834c5770278fb11c534741eddd22 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171011 +DTEND;VALUE=DATE:20171012 +DTSTAMP:20170711T171222Z +UID:16ac78600ddabe1f3687ddbfe117759a +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20171018 +DTEND;VALUE=DATE:20171019 +DTSTAMP:20170711T171222Z +UID:02ffbdd421078a217b1a8055482e4012 +CREATED:20170103T080401Z +DESCRIPTION:braune Biotonne nicht vergessen! +LAST-MODIFIED:20170126T100735Z +LOCATION:Luitpoldstraße\, Treuchtlingen +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:braune Biotonne +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20161213 +DTEND;VALUE=DATE:20161214 +DTSTAMP:20170711T171222Z +UID:d2fqot83imae46g8ov14p93jv4@google.com +CREATED:20161208T124911Z +DESCRIPTION: +LAST-MODIFIED:20161212T122336Z +LOCATION:Treuchtlingen\, 91757 Treuchtlingen\, Deutschland +SEQUENCE:1 +STATUS:CONFIRMED +SUMMARY:Bio +TRANSP:TRANSPARENT +X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC +BEGIN:VALARM +ACTION:AUDIO +TRIGGER:-PT15H +X-WR-ALARMUID:4B966FA0-EAB2-43C6-A054-0782318F886A +UID:4B966FA0-EAB2-43C6-A054-0782318F886A +ATTACH;VALUE=URI:Basso +X-APPLE-DEFAULT-ALARM:TRUE +ACKNOWLEDGED:20161212T122336Z +END:VALARM +END:VEVENT +END:VCALENDAR diff --git a/test/test_icaldownload.py b/test/test_icaldownload.py index 09dbc9c..9f85a97 100644 --- a/test/test_icaldownload.py +++ b/test/test_icaldownload.py @@ -71,29 +71,6 @@ def test_data_from_file_apple(self): self.assertEqual(expected, content, "content form iCal file, google format") - def test_read_only_directory(self): - # Switch to new directory so we can perform os.chmod() - os.mkdir("tmp") - os.chdir("tmp") - - # Save current directory permissions - oldPerms = os.stat(os.getcwd()).st_mode - # Set working directory as read-only - os.chmod(os.getcwd(), 0o500) - - # Assert log message is being thrown - try: - with self.assertLogs(level="WARNING") as cm: - # Create new ICalDownload instance which will try to create the .cache directory - ical_download = icalevents.icaldownload.ICalDownload(http=None) - finally: - # Change directory back to old permissions - os.chmod(os.getcwd(), oldPerms) - - # Delete tmp dir - os.chdir("..") - shutil.rmtree("tmp") - def test_empty_file(self): empty_ical = "test/test_data/empty.ics" diff --git a/test/test_icalevents.py b/test/test_icalevents.py index 1abc629..46c37df 100644 --- a/test/test_icalevents.py +++ b/test/test_icalevents.py @@ -1,23 +1,108 @@ import unittest -from icalevents import icalevents from datetime import date, timedelta, datetime from time import sleep -from dateutil.relativedelta import relativedelta -from dateutil.tz import UTC, gettz -from re import search -import textwrap + +import pook import pytz +from dateutil.tz import UTC, gettz + +from icalevents import icalevents class ICalEventsTests(unittest.TestCase): - def test_events_url(self): + @pook.on + def test_events_url_without_content_type(self): url = "https://raw.githubusercontent.com/jazzband/icalevents/master/test/test_data/basic.ics" + + with open("test/test_data/basic.ics", "rb") as file: + body = file.read() + + pook.get( + url, + reply=200, + response_body=body, + ) + start = date(2017, 5, 18) end = date(2017, 5, 19) - evs = icalevents.events(url=url, file=None, start=start, end=end) + events = icalevents.events(url=url, file=None, start=start, end=end) - self.assertEqual(len(evs), 2, "two events are found") + self.assertEqual(len(events), 2, "two events are found") + + @pook.on + def test_events_url_without_charset(self): + url = "https://raw.githubusercontent.com/jazzband/icalevents/master/test/test_data/basic.ics" + + with open("test/test_data/basic.ics", "rb") as file: + body = file.read() + + pook.get( + url, + reply=200, + response_headers={"Content-Type": "text/calendar"}, + response_body=body, + ) + + start = date(2017, 5, 18) + end = date(2017, 5, 19) + + events = icalevents.events(url=url, file=None, start=start, end=end) + + self.assertEqual(len(events), 2, "two events are found") + + @pook.on + def test_events_url_with_utf8(self): + url = "https://raw.githubusercontent.com/jazzband/icalevents/master/test/test_data/basic.ics" + + with open("test/test_data/basic.ics", "rb") as file: + body = file.read() + + pook.get( + url, + reply=200, + response_headers={"Content-Type": "text/calendar; charset=UTF-8"}, + response_body=body, + ) + + start = date(2017, 5, 18) + end = date(2017, 5, 19) + + events = icalevents.events(url=url, file=None, start=start, end=end) + + self.assertEqual(len(events), 2, "two events are found") + + @pook.on + def test_events_url_with_latin1(self): + url = "https://raw.githubusercontent.com/jazzband/icalevents/master/test/test_data/basic_latin1.ics" + + with open("test/test_data/basic_latin1.ics", "rb") as file: + body = file.read() + + pook.get( + url, + reply=200, + response_headers={"Content-Type": "text/calendar; charset=ISO-8859-1"}, + response_body=body, + ) + + start = date(2017, 5, 18) + end = date(2017, 5, 19) + + events = icalevents.events(url=url, file=None, start=start, end=end) + + self.assertEqual(len(events), 2, "two events are found") + + @pook.on + def test_exception_on_empty_events_url(self): + url = "https://raw.githubusercontent.com/jazzband/icalevents/master/test/test_data/basic.ics" + + pook.get( + url, + reply=500, + ) + + self.assertRaises(ConnectionError, icalevents.events, url=url) def test_events_start(self): ical = "test/test_data/basic.ics"