<!doctype html><html lang=en itemscope itemtype=http://schema.org/WebPage><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1"><meta name=description content="Bist du selbstständig und suchst nach einer einfachen Möglichkeit, deine E-Rechnungen zu erstellen? Dann bist du bei meiner neuen Mac App SupaRechnung genau richtig!
💡 Jetzt kostenlos im App Store herunterladen"><script type=application/ld+json>{"@context":"http://schema.org","@type":"WebSite","name":"Stefan Ukena\u0027s Blog","url":"https:\/\/blog.ukena.de\/"}</script><script type=application/ld+json>{"@context":"http://schema.org","@type":"Organization","name":"","url":"https:\/\/blog.ukena.de\/"}</script><meta property="og:title" content="Stefan Ukena's Blog"><meta property="og:description" content="Bist du selbstständig und suchst nach einer einfachen Möglichkeit, deine E-Rechnungen zu erstellen? Dann bist du bei meiner neuen Mac App SupaRechnung genau richtig!
💡 Jetzt kostenlos im App Store herunterladen"><meta property="og:image" content="https://blog.ukena.de/img/stefan-1024x1024.jpg"><meta property="og:url" content="https://blog.ukena.de/"><meta property="og:type" content="website"><meta property="og:site_name" content="Stefan Ukena's Blog"><meta name=twitter:title content="Stefan Ukena's Blog"><meta name=twitter:description content="Bist du selbstständig und suchst nach einer einfachen Möglichkeit, deine E-Rechnungen zu erstellen? Dann bist du bei meiner neuen Mac App SupaRechnung genau richtig!
💡 Jetzt kostenlos im App Store …"><meta name=twitter:image content="https://blog.ukena.de/img/stefan-1024x1024.jpg"><meta name=twitter:card content="summary_large_image"><meta name=generator content="Hugo 0.156.0"><link rel=alternate href=https://blog.ukena.de/index.xml type=application/rss+xml title="Stefan Ukena's Blog"><link rel=stylesheet href=https://blog.ukena.de/css/katex.min.css><link rel=stylesheet href=https://blog.ukena.de/fontawesome/css/brands.min.css><link rel=stylesheet href=https://blog.ukena.de/fontawesome/css/fontawesome.min.css><link rel=stylesheet href=https://blog.ukena.de/fontawesome/css/regular.min.css><link rel=stylesheet href=https://blog.ukena.de/fontawesome/css/solid.min.css><link rel=stylesheet href=https://blog.ukena.de/fontawesome/css/svg.min.css><link rel=stylesheet href=https://blog.ukena.de/fontawesome/css/svg-with-js.min.css><link rel=stylesheet href=https://blog.ukena.de/fontawesome/css/v4-font-face.min.css><link rel=stylesheet href=https://blog.ukena.de/fontawesome/css/v4-shims.min.css><link rel=stylesheet href=https://blog.ukena.de/fontawesome/css/v5-font-face.min.css><link rel=stylesheet href=https://blog.ukena.de/css/bootstrap.min.css><link rel=stylesheet href=https://blog.ukena.de/css/main.css><link rel=stylesheet href=https://blog.ukena.de/css/fonts.css><link rel=stylesheet href=https://blog.ukena.de/css/syntax.css><link rel=stylesheet href=https://blog.ukena.de/css/codeblock.css><link rel=stylesheet href=https://blog.ukena.de/css/photoswipe.min.css><link rel=stylesheet href=https://blog.ukena.de/css/photoswipe.default-skin.min.css><link rel=stylesheet href=https://blog.ukena.de/css/cookiebanner.css></head><body><nav class="navbar navbar-default navbar-fixed-top navbar-custom"><div class=container-fluid><div class=navbar-header><button type=button class=navbar-toggle data-toggle=collapse data-target=#main-navbar>
<span class=sr-only>Toggle navigation</span>
<span class=icon-bar></span>
<span class=icon-bar></span>
<span class=icon-bar></span>
</button>
<a class=navbar-brand href=https://blog.ukena.de/>Stefan Ukena's Blog</a></div><div class="collapse navbar-collapse" id=main-navbar><ul class="nav navbar-nav navbar-right"><li><a title="How can I help?" href=/about>How can I help?</a></li></ul></div><div class=avatar-container><div class=avatar-img-border><a title="Stefan Ukena's Blog" href=https://blog.ukena.de/><img class=avatar-img src=https://blog.ukena.de/img/stefan-1024x1024.jpg alt="Stefan Ukena's Blog"></a></div></div></div></nav><div class=pswp tabindex=-1 role=dialog aria-hidden=true><div class=pswp__bg></div><div class=pswp__scroll-wrap><div class=pswp__container><div class=pswp__item></div><div class=pswp__item></div><div class=pswp__item></div></div><div class="pswp__ui pswp__ui--hidden"><div class=pswp__top-bar><div class=pswp__counter></div><button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title=Share></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button><div class=pswp__preloader><div class=pswp__preloader__icn><div class=pswp__preloader__cut><div class=pswp__preloader__donut></div></div></div></div></div><div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"><div class=pswp__share-tooltip></div></div><button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button><div class=pswp__caption><div class=pswp__caption__center></div></div></div></div></div><header class=header-section><div class="intro-header no-img"><div class=container><div class=row><div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1"><div class=page-heading><h1>Stefan Ukena's Blog</h1><hr class=small><span class=page-subheading>Thanks for dropping by!</span></div></div></div></div></div></header><div role=main class=container><div class=row><div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1"><div class=well><p>Bist du <strong>selbstständig</strong> und suchst nach einer einfachen Möglichkeit, deine E-Rechnungen zu erstellen? Dann bist du bei meiner neuen Mac App <strong>SupaRechnung</strong> genau richtig!</p><p>💡 <a href="https://apps.apple.com/de/app/rechnung-schreiben-suparechn/id6749506446?mt=12">Jetzt kostenlos im App Store herunterladen</a></p></div><div class=posts-list><article class=post-preview><a href=https://blog.ukena.de/posts/2026/indie-dev-markting-challenge-first-week-recap/><h2 class=post-title>So verlief die erste Woche meiner Indie-Dev Marketing Challenge</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;3&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;</span></p><div class=post-entry><p><img src=ergebnisse-woche1.png alt=ergebnisse-woche1.png></p><p>Ich mache gerade eine Marketing-Challenge für Indie-Devs: Vier Wochen jeden Tag einen Social Media Post veröffentlichen, um meine App <a href=https://suparechnung.de>SupaRechnung</a> bekannter zu machen. Aber um die App geht es heute nicht. Heute geht&rsquo;s um einen Rückblick auf die erste Woche:</p><ul><li>Wie oft und wo habe ich gepostet?</li><li>Was war schwieriger als erwartet?</li><li>Was hat mich überrascht?</li><li>Hat es sich gelohnt und würde ich es weiterempfehlen</li></ul><h2 id=wie-oft-und-wo-habe-ich-gepostet>Wie oft und wo habe ich gepostet?</h2><p>Mein ursprünglicher Plan war, täglich auf LinkedIn zu posten. Aber gleich am ersten Tag habe ich mich entschieden, das Instagram auch sein muss. Da bin ich jetzt <a href=https://www.instagram.com/rechnungschaos/>@rechnungschaos</a>. Und ein paar Tage später habe ich dann auch noch <a href=https://www.tiktok.com/@_stefan3000>TikTok (@_stefan3000)</a> mit aufgenommen.</p><a href=https://blog.ukena.de/posts/2026/indie-dev-markting-challenge-first-week-recap/ class=post-read-more>[Read More]</a></div><div class=blog-tags><a href=https://blog.ukena.de/tags/indie-dev/>indie-dev</a>&nbsp;
<a href=https://blog.ukena.de/tags/marketing/>marketing</a>&nbsp;
<a href=https://blog.ukena.de/tags/suparechnung/>SupaRechnung</a>&nbsp;</div></article><article class=post-preview><a href=https://blog.ukena.de/posts/2021/12/django-4.0-released/><h2 class=post-title>Django 4.0 released</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;1&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;Stefan Ukena</span></p><div class=post-entry><p>Django 4.0 has been released, so it&rsquo;s time to plan the upgrade from 3.x. Here are some important things to note about the upgrade:</p><ul><li>The latest 3.x-release is 3.2, which will <a href=https://www.djangoproject.com/weblog/2021/dec/07/django-40-released/>receive security and &ldquo;data loss&rdquo; fixes until April 2024.</a> Any 3.x-release before 3.2 will no longer receive updates or fixes. It&rsquo;s time to upgrade to 3.2!</li><li>Django 4.0 drops support for Python version &lt;= 3.7. <a href=https://docs.djangoproject.com/en/4.0/releases/4.0/#python-compatibility>Django 3.2 still supports Python 3.6 and 3.7</a></li><li>Django 4.0 <a href=https://docs.djangoproject.com/en/4.0/releases/4.0/#features-removed-in-4-0>drops a number of features</a> that have previous been deprecated in 3.x. More details about these features can be found in the &ldquo;deprecated&rdquo; section of the previous releases: <a href=https://docs.djangoproject.com/en/4.0/releases/3.0/#features-deprecated-in-3-0>Django 3.0 deprecated features</a>, <a href=https://docs.djangoproject.com/en/3.2/releases/3.1/#features-deprecated-in-3-1>Django 3.1 deprecated features</a></li><li><a href=https://docs.djangoproject.com/en/4.0/releases/4.0/#deleteview-changes>If you are using <code>DeleteView</code> with custom logic in <code>delete()</code>, you should make yourself familiar with the new logic.</a></li></ul><p>More links to the official docs:</p><a href=https://blog.ukena.de/posts/2021/12/django-4.0-released/ class=post-read-more>[Read More]</a></div><div class=blog-tags><a href=https://blog.ukena.de/tags/python/>python</a>&nbsp;</div></article><article class=post-preview><a href=https://blog.ukena.de/posts/2021/12/extract-date-from-pdf-update/><h2 class=post-title>Updated: How to extract a date from a PDF file using Python</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;1&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;Stefan Ukena</span></p><div class=post-entry><p>I have updated the script to support a new parameter. Here is my use case:</p><p>Why this update? When I generate a PDF from a web-page, the resulting PDF often contains the current date at the very top, before all other dates. However, that&rsquo;s not the date that I am interested in. I introduced a new <code>before</code>-parameter that will return the first date that is <em>before</em> the given date.</p><p><a href=/posts/2021/12/extract-date-from-pdf/>I have updated the previous post with the changes.</a> (Maybe it&rsquo;s time to publish this as a github project, but it still feels like overkill.)</p></div><div class=blog-tags><a href=https://blog.ukena.de/tags/python/>python</a>&nbsp;</div></article><article class=post-preview><a href=https://blog.ukena.de/posts/2021/12/jetbrains-adds-remote-development-workflow/><h2 class=post-title>A new remote workflow for PyCharm (and other Jetbrains IDEs)</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;2&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;Stefan Ukena</span></p><div class=post-entry><p>The recent PyCharm release (2021.3) adds a feature that enables a new kind of remote development workflow. This seems to be similar to what <a href=https://code.visualstudio.com/docs/remote/remote-overview>VS Code has been able to do</a>, but since I am using PyCharm, this is exciting. Basically, the new feature allows you to run PyCharm locally and connect it to a &ldquo;PyCharm server&rdquo; running remotely. The PyCharm server is a headless version of IntelliJ that you connect to using your local PyCharm (or rather a special version of a locally installed PyCharm IDE, I believe). Note that this is different from the existing workflow were you connect the local debugger to a remote session.</p><a href=https://blog.ukena.de/posts/2021/12/jetbrains-adds-remote-development-workflow/ class=post-read-more>[Read More]</a></div><div class=blog-tags><a href=https://blog.ukena.de/tags/python/>python</a>&nbsp;</div></article><article class=post-preview><a href=https://blog.ukena.de/posts/2021/12/tools-and-services-for-remote-pair-programming/><h2 class=post-title>Remote pair programming tools (end of 2021)</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;1&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;Stefan Ukena</span></p><div class=post-entry><p>If you&rsquo;re a remote team, or a freelance looking to do some pair programming with someone remotely, you used to be very limited in your choices. You could go old school on the terminal using <a href=https://www.hamvocke.com/blog/remote-pair-programming-with-tmux/>ssh and tmux</a>. But that&rsquo;s only an option if you are comfortable with a terminal-based editor or IDE. If you are like me, and use a non-terminal based IDE, the easiest way was to use screen sharing, but that is very limited. You cannot easily hand over the keyboard and mouse from the &ldquo;driver&rdquo; to the &ldquo;navigator&rdquo;.</p><a href=https://blog.ukena.de/posts/2021/12/tools-and-services-for-remote-pair-programming/ class=post-read-more>[Read More]</a></div><div class=blog-tags><a href=https://blog.ukena.de/tags/productivity/>productivity</a>&nbsp;</div></article><article class=post-preview><a href=https://blog.ukena.de/posts/2021/12/extract-date-from-pdf/><h2 class=post-title>How to extract a date from a PDF file using Python</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;5&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;Stefan Ukena</span></p><div class=post-entry><p>Here is a quick one-off script that I created to extract a date from PDFs. (Actually, this is an updated version. Maybe it&rsquo;s not a one-off script after all?)</p><ul><li>The script will look for dates in common German formats, like <code>31.12.2021</code>, <code>31. Dezember 2021</code>, <code>31 Dez 2021</code>.</li><li>It will print either the first date it finds, or nothing</li><li>It will print the date using ISO 8601 date part, e.g. <code>2021-12-31</code></li><li>Using an optional second parameter, you can make sure the printed date is <code>before</code> a certain date</li></ul><h2 id=requirements>Requirements</h2><p>The script uses two external libraries for PDF and date parsing: <code>pdfminer.six</code> and <code>dateparser</code></p><a href=https://blog.ukena.de/posts/2021/12/extract-date-from-pdf/ class=post-read-more>[Read More]</a></div><div class=blog-tags><a href=https://blog.ukena.de/tags/python/>python</a>&nbsp;</div></article><article class=post-preview><a href=https://blog.ukena.de/posts/2021/11/rxpy3-on-error-and-on-completed/><h2 class=post-title>rxPY3: Always implement on_error and on_completed</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;1&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;Stefan Ukena</span></p><div class=post-entry><p>In my quest to better understand <code>rxPY</code>, I have written some short example scripts that use different operators. I have published these on GitHub as <a href=https://github.com/steuke/rxpy3-examples/>rxpy3-examples</a>. In order to keep the examples as short as possible, I had omitted implementing <code>on_error</code> and <code>on_completed</code>. I thought that simple examples would be bloated by this, but that was actually a mistake.</p><p>When I implemented these calls, I noticed that I had made a couple of mistakes in my previous implementation of the custom observable called <a href=https://github.com/steuke/rxpy3-examples/blob/71bb1a4a8d91fb86c41edd0e88684a443b57735f/examples/rx3_multiple_observers_example.py#L13><code>dequeue</code></a>:</p><a href=https://blog.ukena.de/posts/2021/11/rxpy3-on-error-and-on-completed/ class=post-read-more>[Read More]</a></div><div class=blog-tags><a href=https://blog.ukena.de/tags/python/>python</a>&nbsp;</div></article><article class=post-preview><a href=https://blog.ukena.de/posts/2021/11/where-is-the-todo-app-that-can-do-this/><h2 class=post-title>Is there no todo-app that can do this?</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;1&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;Stefan Ukena</span></p><div class=post-entry><p>There are so many todo apps, but none of them seems to have the ability to let me do this:</p><p>I want to be able to create a list of todo items &ndash; let&rsquo;s call this list the <em>should-do-list</em> &ndash; and manually change the order of todo-items. Then I want to take this list, and create a new view of it. Let&rsquo;s call this view the <em>want-to-list</em>. The want-to and the should-do list will always contain the same items, only the order of items is different. I want to be able to manually change the order on each list without impacting the order on the other list.</p><a href=https://blog.ukena.de/posts/2021/11/where-is-the-todo-app-that-can-do-this/ class=post-read-more>[Read More]</a></div><div class=blog-tags><a href=https://blog.ukena.de/tags/misc/>misc</a>&nbsp;</div></article><article class=post-preview><a href=https://blog.ukena.de/posts/2021/11/how-to-ask-developers-for-help/><h2 class=post-title>How to ask developers for help</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;2&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;Stefan Ukena</span></p><div class=post-entry><p>Today I reached out to the maintainers of <code>rxPY</code> for help on understanding the <code>window_with_count</code>-operator. I have trying to get this to work for a while now, and it just does not what I would expect. I have read the official rxPY-documentation, searched Stackoverflow, Google, and the project&rsquo;s GitHub issues (because people are very helpful there in this particular project). I also looked at the tests, but those were confusing me even more. So I decided to ask for help by submitting a GitHub issue. <em>Note: In general, I would assume that GitHub issues are the right place to ask for help. Many projects will automatically close questions, because issues are reserved for issues, like bug reports. However, in this case the project maintainers are actively answering questions there.</em></p><a href=https://blog.ukena.de/posts/2021/11/how-to-ask-developers-for-help/ class=post-read-more>[Read More]</a></div><div class=blog-tags><a href=https://blog.ukena.de/tags/misc/>misc</a>&nbsp;</div></article><article class=post-preview><a href=https://blog.ukena.de/posts/2021/11/rxpy3-examples-fixing-the-multiple-observer-example/><h2 class=post-title>rxpy3-examples: Fixing the multiple observer example</h2></a><p class=post-meta><span class=post-meta><i class="fas fa-calendar"></i>&nbsp;
&nbsp;|&nbsp;<i class="fas fa-clock"></i>&nbsp;1&nbsp;minutes
&nbsp;|&nbsp;<i class="fas fa-user"></i>&nbsp;Stefan Ukena</span></p><div class=post-entry><p>As I was adding a test for the <a href=https://github.com/steuke/rxpy3-examples/commit/337c72ff5681c5cd467e983e3f454ceb20df21b5#diff-65b9ea45af59dd7123260eaee0c5804ef752a885958bd469df2d5219edea27f5R33><code>examples/rx3_buffer_example.py</code></a> I noticed that the endless while-loop was actually never called, because <code>observable.connect()</code> seems to be a blocking operation, until the stream finishes with <code>on_error</code> or <code>on_complete</code>.</p><p>To make this example testable, I changed the <code>dequeue()</code> from using an endless while-loop to emitting a list of items. <a href=https://github.com/steuke/rxpy3-examples/commit/a79c260f08d79ae72ee003ea954f8709e1b99f37#diff-65b9ea45af59dd7123260eaee0c5804ef752a885958bd469df2d5219edea27f5>The changes can bee seen in this commit.</a></p><p>In addition, I made a small change to the <code>capture_stdout_as_list</code> context-manager: I renamed the <code>to_string()</code>-method to <code>__str__()</code>, so that the context-manager&rsquo;s result can be used in the test assertions using <code>str(result)</code> instead of <code>result.to_string()</code>. It does look a little nicer, and I guess that this could be called &ldquo;more pythonic&rdquo;.</p></div><div class=blog-tags><a href=https://blog.ukena.de/tags/python/>python</a>&nbsp;</div></article></div><ul class="pager main-pager"><li class=next><a href=https://blog.ukena.de/page/2/>Older Posts &rarr;</a></li></ul></div></div></div><div class=page-meta></div><footer><div class=container><div class=row><div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1"><ul class="list-inline text-center footer-links"><li><a href=/index.xml title=RSS><span class="fa-stack fa-lg"><i class="fas fa-circle fa-stack-2x"></i>
<i class="fas fa-rss fa-stack-1x fa-inverse"></i></span></a></li></ul><p class="credits copyright text-muted">&nbsp;&bull;&nbsp;&copy;
2026
&nbsp;&bull;&nbsp;
<a href=https://blog.ukena.de/>Stefan Ukena's Blog</a></p><p class="credits theme-by text-muted"><a href=https://gohugo.io>Hugo</a> powered &nbsp;&bull;&nbsp; Theme based on <a href=https://github.com/halogenica/beautifulhugo>Beautiful Hugo</a></p></div></div></div></footer><script defer src=https://blog.ukena.de/js/katex.min.js></script><script defer src=https://blog.ukena.de/js/auto-render.min.js onload=renderMathInElement(document.body)></script><script src=https://blog.ukena.de/js/jquery-3.7.0.slim.min.js></script><script src=https://blog.ukena.de/js/bootstrap.min.js></script><script src=https://blog.ukena.de/js/main.js></script><script src=https://blog.ukena.de/js/photoswipe.min.js></script><script src=https://blog.ukena.de/js/photoswipe-ui-default.min.js></script><script src=https://blog.ukena.de/js/load-photoswipe.js></script><script src=/js/utils.js></script><script src=/js/cookiebanner.js></script></body></html>