From 86c99d6c2744a9b7dec79d5f72108e50001737af Mon Sep 17 00:00:00 2001 From: frankknoll Date: Wed, 16 Mar 2022 17:05:21 +0100 Subject: [PATCH 1/2] computing KreisOptions --- docs/intensivstationen.html | 2 +- src/intensivstationen/Intensivstationen.ipynb | 169 ++++++++++++++++-- 2 files changed, 160 insertions(+), 11 deletions(-) diff --git a/docs/intensivstationen.html b/docs/intensivstationen.html index d28cf6ed1aa..bdf6590c315 100644 --- a/docs/intensivstationen.html +++ b/docs/intensivstationen.html @@ -464,7 +464,7 @@
Kartenansichten
Datenstand:
-
12.03.2022, 12:38 Uhr
+
16.03.2022, 12:38 Uhr
diff --git a/src/intensivstationen/Intensivstationen.ipynb b/src/intensivstationen/Intensivstationen.ipynb index 4bba36497fb..09e1a773fb2 100644 --- a/src/intensivstationen/Intensivstationen.ipynb +++ b/src/intensivstationen/Intensivstationen.ipynb @@ -258,7 +258,7 @@ "metadata": {}, "outputs": [], "source": [ - "kreisValues = timeSeries['Kreis'].drop_duplicates().values" + "kreisValues = sorted(timeSeries['Kreis'].drop_duplicates().values)" ] }, { @@ -268,24 +268,173 @@ "metadata": {}, "outputs": [], "source": [ - "def printKreisOptions(kreisValues):\n", - " for kreis in kreisValues:\n", - " printKreisOption(kreis)\n", + "def getKreisOptions(kreisValues):\n", + " return [getKreisOption(kreis) for kreis in kreisValues]\n", "\n", - "def printKreisOption(kreis):\n", - " print(''.format(kreis = kreis))" + "def getKreisOption(kreis):\n", + " return ''.format(kreis = kreis)\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "33a4b725", + "id": "9c38ca16", "metadata": {}, "outputs": [], "source": [ - "kreisValues = sorted(kreisValues)\n", - "# FK-TODO: die folgenden Optionen in der Datei intensivstationen.html in das select-Element nach \"Alle Landkreise\" einsetzen \n", - "printKreisOptions(kreisValues)" + "kreisOptions = [''] + getKreisOptions(kreisValues)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9eb453d0", + "metadata": {}, + "outputs": [], + "source": [ + "from bs4 import BeautifulSoup\n", + "\n", + "\n", + "class KreisOptionsSetter:\n", + "\n", + " def setKreisOptions(self, html, options):\n", + " soup = self._setKreisOptions(self._parse(html), self._parseOptions(options))\n", + " return str(soup)\n", + "\n", + " def _setKreisOptions(self, soup, options):\n", + " kreisSelect = soup.find(id = \"kreisSelect\")\n", + " kreisSelect.clear()\n", + " for option in options:\n", + " kreisSelect.append(option)\n", + " return soup\n", + "\n", + " def _parseOptions(self, options):\n", + " return [self._parse(option).option for option in options]\n", + "\n", + " def _parse(self, html):\n", + " return BeautifulSoup(html, 'lxml')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e4f8fa80", + "metadata": {}, + "outputs": [], + "source": [ + "import unittest\n", + "\n", + "\n", + "class KreisOptionsSetterTest(unittest.TestCase):\n", + "\n", + " def test_setKreisOptions(self):\n", + " # Given\n", + " kreisOptionsSetter = KreisOptionsSetter()\n", + "\n", + " # When\n", + " htmlActual = kreisOptionsSetter.setKreisOptions(\n", + " html = '''\n", + " \n", + " \n", + "

Test

\n", + " \n", + " \n", + " \n", + " ''',\n", + " options = [\n", + " '',\n", + " '',\n", + " ''])\n", + "\n", + " # Then\n", + " assertEqualHTML(\n", + " htmlActual,\n", + " '''\n", + " \n", + " \n", + "

Test

\n", + " \n", + " \n", + " \n", + " ''')\n", + "\n", + "# adapted from https://stackoverflow.com/questions/8006909/pretty-print-assertequal-for-html-strings\n", + "def assertEqualHTML(string1, string2, file1='', file2=''):\n", + " u'''\n", + " Compare two unicode strings containing HTML.\n", + " A human friendly diff goes to logging.error() if they\n", + " are not equal, and an exception gets raised.\n", + " '''\n", + " from bs4 import BeautifulSoup as bs\n", + " import difflib\n", + "\n", + " def short(mystr):\n", + " max = 20\n", + " if len(mystr) > max:\n", + " return mystr[:max]\n", + " return mystr\n", + " p = []\n", + " for mystr, file in [(string1, file1), (string2, file2)]:\n", + " if not isinstance(mystr, str):\n", + " raise Exception(u'string ist not unicode: %r %s' %\n", + " (short(mystr), file))\n", + " soup = bs(mystr)\n", + " pretty = soup.prettify()\n", + " p.append(pretty)\n", + " if p[0] != p[1]:\n", + " for line in difflib.unified_diff(p[0].splitlines(), p[1].splitlines(), fromfile=file1, tofile=file2):\n", + " display(line)\n", + " display(p[0], ' != ', p[1])\n", + " raise Exception('Not equal %s %s' % (file1, file2))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e80117e5", + "metadata": {}, + "outputs": [], + "source": [ + "unittest.main(argv = [''], verbosity = 2, exit = False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "403f8b7b", + "metadata": {}, + "outputs": [], + "source": [ + "from bs4 import BeautifulSoup\n", + "\n", + "def saveKreisOptions(kreisOptions):\n", + " file = \"../../docs/intensivstationen.html\"\n", + " with open(file) as fp:\n", + " soup = BeautifulSoup(fp, 'lxml')\n", + "\n", + " soup = KreisOptionsSetter().setKreisOptions(html = str(soup), options = kreisOptions)\n", + "\n", + " with open(file, \"w\") as fp:\n", + " fp.write(soup)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5dd8d864", + "metadata": {}, + "outputs": [], + "source": [ + "saveKreisOptions(kreisOptions)" ] }, { From 72617bc5fbb86fbc546fa55dc37ccd5681a93d7e Mon Sep 17 00:00:00 2001 From: frankknoll Date: Wed, 16 Mar 2022 18:19:18 +0100 Subject: [PATCH 2/2] refactoring --- src/intensivstationen/Intensivstationen.ipynb | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/intensivstationen/Intensivstationen.ipynb b/src/intensivstationen/Intensivstationen.ipynb index 09e1a773fb2..f5714ebaa15 100644 --- a/src/intensivstationen/Intensivstationen.ipynb +++ b/src/intensivstationen/Intensivstationen.ipynb @@ -108,15 +108,36 @@ "source": [ "from bs4 import BeautifulSoup\n", "\n", + "class HtmlTransformerUtil:\n", + " \n", + " def applySoupTransformerToFile(self, file, soupTransformer):\n", + " self._writeSoup(soupTransformer(self._readSoup(file)), file)\n", + "\n", + " def _readSoup(self, file):\n", + " with open(file) as fp:\n", + " soup = BeautifulSoup(fp, 'lxml')\n", + " return soup\n", + "\n", + " def _writeSoup(self, soup, file):\n", + " with open(file, \"w\") as fp:\n", + " fp.write(str(soup)) \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af101279", + "metadata": {}, + "outputs": [], + "source": [ "def saveLastUpdatedIntensivstationen(lastUpdated):\n", - " file = \"../../docs/intensivstationen.html\"\n", - " with open(file) as fp:\n", - " soup = BeautifulSoup(fp, 'lxml')\n", + " def setLastUpdated(soup):\n", + " soup.find(id = \"Datenstand\").string.replace_with(lastUpdated.strftime(DateProvider.INTENSIVSTATIONEN_DATE_FORMAT))\n", + " return soup\n", "\n", - " soup.find(id = \"Datenstand\").string.replace_with(lastUpdated.strftime(DateProvider.INTENSIVSTATIONEN_DATE_FORMAT))\n", - "\n", - " with open(file, \"w\") as fp:\n", - " fp.write(str(soup))" + " HtmlTransformerUtil().applySoupTransformerToFile(\n", + " file = \"../../docs/intensivstationen.html\",\n", + " soupTransformer = setLastUpdated)" ] }, { @@ -416,15 +437,11 @@ "source": [ "from bs4 import BeautifulSoup\n", "\n", + "\n", "def saveKreisOptions(kreisOptions):\n", - " file = \"../../docs/intensivstationen.html\"\n", - " with open(file) as fp:\n", - " soup = BeautifulSoup(fp, 'lxml')\n", - "\n", - " soup = KreisOptionsSetter().setKreisOptions(html = str(soup), options = kreisOptions)\n", - "\n", - " with open(file, \"w\") as fp:\n", - " fp.write(soup)" + " HtmlTransformerUtil().applySoupTransformerToFile(\n", + " file = \"../../docs/intensivstationen.html\",\n", + " soupTransformer = lambda soup: BeautifulSoup(KreisOptionsSetter().setKreisOptions(html = str(soup), options = kreisOptions), 'lxml'))\n" ] }, {