Enrico Zini
http://www.enricozini.org/tags/rant
staticsite
2019-07-27T09:29:21Z
Enrico Zini: posts with tag rant
Opinion Sort
http://www.enricozini.org/blog/2019/opinion-sort
2019-07-27T09:29:21Z
2019-07-27T09:29:21Z
<blockquote>
<p>«Bullshit is unavoidable whenever circumstances require someone to talk
without knowing what he is talking about. Thus the production of bullshit is
stimulated whenever a person’s obligations or opportunities to speak about
some topic are more excessive than his knowledge of the facts that are
relevant to that topic.</p>
<p>This discrepancy is common in public life, where people are frequently
impelled— whether by their own propensities or by the demands of others—to
speak extensively about matters of which they are to some degree ignorant.</p>
<p>Closely related instances arise from the widespread conviction that it is the
responsibility of a citizen in a democracy to have opinions about everything,
or at least everything that pertains to the conduct of his country’s affairs.</p>
<p>The lack of any significant connection between a person’s opinions and his
apprehension of reality will be even more severe, needless to say, for
someone who believes it his responsibility, as a conscientious moral agent,
to evaluate events and conditions in all parts of the world.»</p>
<p>(From <a href="https://en.wikipedia.org/wiki/On_Bullshit">Harry G. Frankfurt's <em>On Bullshit</em></a>)</p>
</blockquote>
<h2>Opinion Sort</h2>
<p>In a world where it is more important to have a quick opinion than a thorough
understanding, I propose this novel sorting algoritihm.</p>
<div class="codehilite"><pre><span></span><span class="k">def</span> <span class="nf">opinion_sort</span><span class="p">(</span><span class="nb">list</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">post</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">List</span><span class="p">]):</span>
<span class="sd">"""</span>
<span class="sd"> list: a list of elements to sort in place</span>
<span class="sd"> post: a callable that requires a sorted list as input and does</span>
<span class="sd"> proper error checking, as they should do</span>
<span class="sd"> """</span>
<span class="k">if</span> <span class="nb">list</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">></span> <span class="nb">list</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">swap</span><span class="p">(</span><span class="nb">list</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nb">list</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># Assert opinion: "It is a sorted list!"</span>
<span class="n">post</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
<span class="k">except</span> <span class="n">NotSortedException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="c1"># Someone disagrees, and they have a good point</span>
<span class="n">swap</span><span class="p">(</span><span class="nb">list</span><span class="p">[</span><span class="n">e</span><span class="o">.</span><span class="n">unsorted_idx_1</span><span class="p">],</span> <span class="nb">list</span><span class="p">[</span><span class="n">e</span><span class="o">.</span><span class="n">unsorted_idx_2</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">break</span>
<span class="c1"># The list is now sorted, and the callable has to agree</span>
</pre></div>
<p>This algorithm is the most efficient sorting algorithm, because it can sort a
list by only looking at the first two elements.</p>
Gnome without chrome-gnome-shell
http://www.enricozini.org/blog/2018/debian/gnome-without-chrome-gnome-shell
2018-02-08T09:26:06Z
2018-02-08T09:26:06Z
<p>New laptop, has a touchscreen, can be folded into a tablet, I heard gnome-shell
would be a good choice of desktop environment, and I managed to tweak it enough
that I can reuse existing habits.</p>
<p>I have a big problem, however, with how it encourages one to download random
extensions off the internet and run them as part of the whole desktop
environment. I have an even bigger problem with
<a href="https://packages.debian.org/gnome-core">gnome-core</a> having a hard
dependency on
<a href="https://packages.debian.org/chrome-gnome-shell">chrome-gnome-shell</a>, a plugin
which cannot be disabled without root editing files in <code>/etc</code>, which exposes
parts of my destktop environment to websites.</p>
<p>Visit <a href="https://extensions.gnome.org/">this site</a> and it will know which
extensions you have installed, and it will be able to install more. I do not
trust that, I do not need that, I do not want that. I am horrified by the idea
of that.</p>
<p><a href="https://salsa.debian.org/enrico/contain-gnome-shell">I made a workaround.</a></p>
<p>How can one do the same for firefox?</p>
<h2>Description</h2>
<p>chrome-gnome-shell is a hard dependency of gnome-core, and it installs a
browser plugin that one may not want, and mandates its use by system-wide
chrome policies.</p>
<p>I consider having chrome-gnome-shell an unneeded increase of the attack
surface of my system, in exchange for the dubious privilege of being able to
download and execute, as my main user, random unreviewed code.</p>
<p>This package satifies the chrome-gnome-shell dependency, but installs nothing.</p>
<p>Note that after installing this package you need to purge chrome-gnome-shell
if it was previously installed, to have it remove its chromium policy files in
/etc/chromium</p>
<h1>Instructions</h1>
<div class="codehilite"><pre><span></span>apt install equivs
equivs-build contain-gnome-shell
sudo dpkg -i contain-gnome-shell_1.0_all.deb
sudo dpkg --purge chrome-gnome-shell
</pre></div>
Software quality in 2016
http://www.enricozini.org/blog/2016/debian/software-quality-in-2016
2016-11-15T12:01:39Z
2016-11-15T12:01:39Z
<p>Ansible's default output, including the <code>stderr</code> of failed commands, is JSON
encoded, which makes reading Jenkins' output hard.</p>
<p>Ansible however has <a href="http://docs.ansible.com/ansible/dev_guide/developing_plugins.html#callback-plugins">Callback plugins</a> that could be used. In that page it says:</p>
<blockquote>
<p>Ansible comes with a number of callback plugins that you can look at for examples. These can be found in <a href="https://github.com/ansible/ansible/tree/devel/lib/ansible/plugins/callback">lib/ansible/plugins/callback</a>.</p>
</blockquote>
<p>That is a link to a git repo with just a pile of Python sources and no, say
<code>README.md</code> index to what they do. Hopefully they have some docstring with a short description of what they do?
<a href="https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/callback/actionable.py">no</a>.</p>
<p>Actually,
<a href="https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/callback/oneline.py">some</a>
<a href="https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/callback/minimal.py">do</a>,
but just because someone copypasted
<a href="https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/callback/default.py">the default one</a>
and didn't even bother removing its docstring.</p>
<p><img alt="frustration" src="https://cdn.meme.am/cache/instances/folder999/500x/73178999.jpg"></p>
I chipped in
http://www.enricozini.org/blog/2016/i-chipped-in
2016-05-23T12:45:34Z
2016-05-23T12:45:34Z
<p>I clicked on a random link and I found myself again in front of a wired.com
popup that wanted to explain to me what I have to think about adblockers.</p>
<p>This time I was convinced, and I took my wallet out.</p>
<p>I finally donated $35 to <a href="https://getadblock.com">AdBlock</a>.</p>
<p><small><em>(And then somebody pointed me to <a href="https://github.com/gorhill/uBlock/">uBlock Origin</a>
and I switched to that.)</em></small></p>
Simple one liner to save battery life and reduce system latency
http://www.enricozini.org/blog/2016/debian/simple-one-liner-to-save-battery-life-and-reduce-system-latency
2016-03-08T19:16:40Z
2016-03-08T19:16:40Z
<p>Sometimes I am in an airplane, and I just want to write code and compile it.</p>
<p>Sometimes I am playing a game in full screen, and I don't want it to lag.</p>
<p><a href="http://lynoure.net">Lynoure</a> suggested this simple one-liner which helps
immensely, to a point that I have turned it into a habit:</p>
<div class="codehilite"><pre><span></span>pkill -STOP chromium
</pre></div>
<p>When I want to use the browser again:</p>
<div class="codehilite"><pre><span></span>pkill -CONT chromium
</pre></div>
<p>I wish web browsers would stop running <em>anything</em> when unfocused, unless asked
otherwise on a site by site basis.</p>
<p><strong>Update:</strong>
Johannes Schauer blogged more than a year ago about
<a href="https://blog.mister-muffin.de/2014/11/07/automatically-suspending-cpu-hungry-applications/">how to automate this in awesome</a>.</p>
Debugging output of GUI apps
http://www.enricozini.org/blog/2016/debian/gui-debugging-output
2016-02-18T14:09:26Z
2016-02-18T14:09:26Z
<p>I have been hit by <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=643726">#643726</a> again.
I was happily working on a terminal while an <code>apt upgrade</code> was running on
another, and suddenly <code>kbuildsycoca4</code> started vomiting on my command line
because I had run okular once on that terminal last tuesday.</p>
<p>Among the possible workarounds, one can run <code>kdebugdialog</code> from package
<code>kde-runtime</code> and check the "Disable all debug output" button.</p>
<p>This is the output of <code>kdebugdialog</code> when run on a terminal after enabling
"Disable all debug output":</p>
<div class="codehilite"><pre><span></span>$ kdebugdialog
QDBusConnection: session D-Bus connection created before QCoreApplication. Application may misbehave.
QDBusConnection: session D-Bus connection created before QCoreApplication. Application may misbehave.
</pre></div>
<p>I see it as debugging output turned into an art performance, and I have an
appreciation for this kind of things. <code>kdebugdialog</code>, my hat's off to you.</p>
Downgrading network-manager
http://www.enricozini.org/blog/2016/debian/downgrading-network-manager
2016-01-07T10:37:19Z
2016-01-07T10:37:19Z
<p>This morning I woke up. Bad idea.</p>
<p>I find in the work mail a compiler error that I cannot reproduce, so I need to
log into a machine at work. But <a href="https://bugs.debian.org/809195">#809195</a>.</p>
<p>I decided to downgrade network-manager. I recall there was a tool to download
packages from snapshots.debian.org, I discussed it recently on IRC, let's sync
the IRC logs from my server. <a href="https://bugs.debian.org/810212">Or not (#810212)</a>.</p>
<p>Never mind, I'll log into the server and grep. Ooh, it's
<a href="http://manpages.ubuntu.com/manpages/natty/man1/debsnap.1.html">debsnap</a>.
However, <a href="https://bugs.debian.org/667712">it doesn't quite do what I hoped (#667712)</a>.</p>
<p>After some help from <code>#debian-devel</code> (thanks jcristau and LebedevRI), here is
how to downgrade network-manager:</p>
<div class="codehilite"><pre><span></span># echo "deb http://snapshot.debian.org/archive/debian/20151125T155830Z/ sid main" >> /etc/apt/sources.list.d/tmp-downgrade-nm.list
# apt -o Acquire::Check-Valid-Until=false update
# apt -o Acquire::Check-Valid-Until=false install network-manager=1.0.6-1
# rm /etc/apt/sources.list.d/tmp-downgrade-nm.list
# service network-manager restart
</pre></div>
<p>And as user:</p>
<div class="codehilite"><pre><span></span>$ killall nm-applet
$ nm-applet <span class="p">&</span>
</pre></div>
<p>The yak is now nice and shaved, I can now go and see what those compiler errors
are all about.</p>
<p>Actually, no, there was still an unshaved patch on the yak, and now we have a
<a href="https://github.com/spanezz/debcya">debcya</a> script.</p>
When Akonadi silently fails to sync your calendar...
http://www.enricozini.org/blog/2015/akonadi-fails-to-sync
2015-12-01T13:01:09Z
2015-12-01T13:01:09Z
<p>Bug severity: <a href="https://bugs.debian.org/804272">seriously ruining my life</a>.</p>
<p>Try to use korganizer to create a calendar entry when the server is not
reachable (say, you are offline, or you typed the wrong password), and you may
find that you end up with no error messages, an entry that shows up perfectly
fine, but that will <em>never</em> be synced to the server, <em>ever again</em>.</p>
<p>I use korganizer, radicale and caldav for important things. The practical
ramifications of me inserting entries in korganizer, seeing that everything
looks ok, and then not finding them on my phone while on the go, are <em>scary</em>.</p>
<p>Think of things like importing <code>.ics</code> files with flight schedules, entering tax
deadlines, time and places for customer meetings, time and places of arrival of
loved ones I'm supposed to pick up.</p>
<p><a href="http://www.enricozini.org/blog/2014/radicale-davdroid">I spent time setting up my own infrastructure for this</a>
exactly because I care that all of this works reliably.</p>
<p>And now I urgently took a morning off work to <a href="https://github.com/spanezz/akonadi-workarounds">find a way</a>
to detect those entries that Akonadi is refusing to update,</p>
<p>The whole thing is cumbersome to run, but if you are using kdepim-based tools
to manage your calendars and sync them across devices, you may want to give it
a go every once in a while.</p>
<p>You can find the script and the notes I took so far on the issue at <a href="https://github.com/spanezz/akonadi-workarounds">https://github.com/spanezz/akonadi-workarounds</a>.</p>
Italian Fattura Elettronica with OpenSSL
http://www.enricozini.org/blog/2015/italian-fattura-elettronica-with-openssl
2015-10-23T08:35:53Z
2015-10-23T08:35:53Z
<p>I have had some success <a href="https://github.com/spanezz/fatturaelettronica/blob/master/openssl.md">signing an Italian fattura elettronica with OpenSSL</a>.</p>
<p>I am amazed to realise that the software they gave me to do the job is of
<a href="http://www.enricozini.org/blog/2015/italian-fattura-elettronica">such bad quality</a> that I felt like spending a
few hours trying to do the same thing with <em>OpenSSL</em> instead.</p>
Extracting XML payload from Italian Fattura Elettronica zipfiles
http://www.enricozini.org/blog/2015/extract-xml-from-fattura-elettronica
2015-10-09T09:52:04Z
2015-10-09T09:52:04Z
<p><a href="http://www.enricozini.org/blog/2015/italian-fattura-elettronica">This</a> system does not even export to PDF. In
order to provide my accountant with something better than a DER-encoded file
with a random-looking name stored inside a zipfile,
<a href="https://github.com/spanezz/fatturaelettronica">here</a> is a script that at least
extracts the unsigned XML payload out of a saved Fattura Elettronica.</p>
<p>If you're giving a python course in Italy, this sounds like a nice early
programming assignment.</p>
Billing an Italian public administration
http://www.enricozini.org/blog/2015/italian-fattura-elettronica
2015-07-02T21:48:36Z
2015-07-02T21:48:36Z
<p>Here's a simple guide for how I managed to
<a href="https://it.wikipedia.org/wiki/Fattura_elettronica">bill</a> one of my customers
as is now mandated by law in Italy.</p>
<h1>Create a new virtualbox machine</h1>
<p>I would <em>never</em> do any of this to any system I would ever want to use for
anything else, so it's virtual machine time.</p>
<ul>
<li>I started virtualbox, created a new machine for *buntu <em>32bit</em>, 8Gb disk,
4Gb RAM, and placed the .vdi image in an encrypted partition. The <em>web
services</em> of Infocert's fattura-pa requires <em>"Java (JRE) a 32bit di versione
1.6 o superiore"</em>.</li>
<li>I installed *buntu 12.04 on it: that is what
<a href="https://www.firma.infocert.it/installazione/installazione_DiKe.php">dike</a>
declares to support.</li>
<li>I booted the VM, installed virtualbox-guest-utils, and de sure I also had
virtualbox-guest-x11</li>
<li>I restarted the VM so that I could resize the virtualbox window and have
*buntu resize itself as well. Now I could actually read popup error messages
in full.</li>
<li>I changed the desktop background to something that gave me the idea that
this is an <em>untrusted</em> machine where I need to be <em>very</em> careful of what I
type. I went for bright red.</li>
</ul>
<h1>Install smart card software into it</h1>
<ul>
<li><code>apt-get install pcscd pcsc-tools opensc</code></li>
<li>In virtualbox, I went to <em>Devices/USB devices</em> and enabled the smart card
reader in the virtual machine.</li>
<li>I ran <code>pcsc_scan</code> to see if it could see my smart card.</li>
<li>I ran Firefox, went to preferences, advanced, security devices, load. Module
name is "CRS PKCS#11", module path is <code>/usr/lib/opensc-pkcs11.so</code></li>
<li>I went to <a href="https://fattura-pa.infocamere.it/fpmi/service">https://fattura-pa.infocamere.it/fpmi/service</a> and I was able to
log in. To log in, I had to type the PIN <em>4 times</em> into popups that offered
little explanations about what was going on, enjoying cold shivers because
the smart card would lock itself at the 3rd failed attempt.</li>
<li>Congratulations to myself! I thought that all was set, but unfortunately,
at this stage, <em>I was not able to do anything else except log into the
website</em>.</li>
</ul>
<h1>Descent into darkness</h1>
<h2>Set up things for fattura-pa</h2>
<ul>
<li>I got the PDF with the setup instructions from
<a href="https://www.firma.infocert.it/installazione/pdf/configura_FF_3.5.5_SSL.pdf">here</a>.
Get it too, for a reference, a laugh, and in case you do not believe the
instructions below.</li>
<li>I went to <a href="https://www.firma.infocert.it/installazione/certificato.php">https://www.firma.infocert.it/installazione/certificato.php</a>, and saved
the two certificates.</li>
<li>Firefox, preferences, advanced, show certificates, I imported both CA
certificates, <em>trusted for everything</em>, all my base are belong to <em>them</em>.</li>
<li><code>apt-get install icedtea-plugin</code></li>
<li>I went to <a href="https://fattura-pa.infocamere.it/fpmi/service">https://fattura-pa.infocamere.it/fpmi/service</a> and tried to sign.
I could not: I got an error about invalid UTF8 for something or other in
Firefox's stdandard error. Firefox froze and had to be killed.</li>
</ul>
<h2>Set up things for signing locally with dike</h2>
<ul>
<li>I removed icedtea so that I could use the site without firefox crashing.</li>
<li>I installed <a href="https://www.firma.infocert.it/installazione/installazione_DiKe.php">DiKe For *buntu 12.04 32bit</a></li>
<li>I ran dikeutil to see if it could talk to my smart card</li>
<li>When signing with the website, I chose the manual signing options and
downloaded the zip file with the xml to be signed.</li>
<li>I got a zip file, unzipped it.</li>
<li>I loaded the xml into dike.</li>
<li>I signed it with dike.</li>
<li>I got this error message: <em>"nessun certificato di firma presente sul
dispositivo di firma"</em> and then this error message: <em>"Impossibile recuperare
il certificato dal dispositivo di firma"</em>. No luck.</li>
</ul>
<h2>Set up things for signing locally with ArubaSign</h2>
<ul>
<li>I went to <a href="https://www.pec.it/Download.aspx">https://www.pec.it/Download.aspx</a></li>
<li>I downloaded ArubaSign for Linux 32 bit.</li>
<li>Oh! People say that it only works with Oracle's version of Java.</li>
<li><code>sudo add-apt-repository ppa:webupd8team/java</code></li>
<li><code>apt-get update</code></li>
<li><code>apt-get install oracle-java7-installer</code></li>
<li>During the installation process I had to agree to <em>also</em> sell my soul to
Oracle.</li>
<li><code>tar axf ArubaSign*.tar*</code></li>
<li><code>cd ArubaSing-*/apps/dist</code></li>
<li><code>java -jar ArubaSign.jar</code></li>
<li>I let it download its own updates. Another time I did not. It does not seem
to matter: I get asked that question every time I start it anyway.</li>
<li>I enjoyed the fancy brushed metal theme, and had an interesting time
navigating an interface where every label on every icon or input
field was truncated.</li>
<li>I downloaded
<a href="https://www.pec.it/documenti/Manuale_ArubaSign2_firma%20Remota_V03_02_07_2012.pdf">https://www.pec.it/documenti/Manuale_ArubaSign2_firma%20Remota_V03_02_07_2012.pdf</a>
to get screenshots of that interface with all the labels intact</li>
<li>I signed the xml that I got from the website. I got told that I needed to
really view carefully what I was signing, because the signature would be
legally binding</li>
<li>I enjoyed carefully reading a <em>legally binding</em>, <em>raw XML file</em>.</li>
<li>I told it to go ahead, and there was now a <code>.p7m</code> file ready for me. I
rejoiced, as now I might, just might actually get paid for my work.</li>
</ul>
<h2>Try fattura-pa again</h2>
<p>Maybe fattura-pa would work with Oracle's Java plugin?</p>
<ul>
<li>I went to <a href="https://fattura-pa.infocamere.it/fpmi/service">https://fattura-pa.infocamere.it/fpmi/service</a></li>
<li>I got asked to verify java at www.java.com. I did it.</li>
<li>I told FireFox to enable java.</li>
<li>Suddenly, and while I was still in java.com's tab, I got prompted about
allowing Infocert's applet to run: I allowed it to run.</li>
<li>I also got prompted several times, still while the current tab was not even
Infocert's tab, about running components that could compromise the security
of my system. I <em>allowed</em> and <em>unblocked</em> <em>all of them</em>.</li>
<li>I entered my PIN.</li>
<li>Congratulations! Now I have two ways of generating legally binding
signatures with government issued smart cards!</li>
</ul>
<h1>Aftermath</h1>
<p>I shut down that virtual machine and I'm making sure I never run anything
important on it. Except, of course, generating legally binding signatures as
required by the Italian government.</p>
<p><a href="http://www.ilsole24ore.com/art/notizie/2012-03-26/rubano-firma-digitale-intestano-181133.shtml">What could possibly go wrong?</a></p>
debtags rewritten in python3
http://www.enricozini.org/blog/2015/debian/debtags-rewrite-python3
2015-06-21T16:04:39Z
2015-06-21T16:04:39Z
<p>In my long quest towards closing <a href="https://bugs.debian.org/540218">#540218</a>, I
have <a href="https://packages.qa.debian.org/libe/libept/news/20150619T152105Z.html">uploaded a new libept to experimental</a>.
Then I tried to build debtags on a sid+experimental chroot and the result runs
but has libc's <code>free()</code> print existential warnings about whatevers.</p>
<p>At a quick glance, there are now things around like a new libapt, gcc 5 with
ABI changes, and who knows what else. I figured how much time it'd take me to
debug something like that, and I've used that time to rewrite debtags in
python3. It took 8 hours, 5 of pleasant programming and the usual tax of
another 3 of utter frustration packaging the results. I guess I gained over the
risk of spending an unspecified amount of hours of just pure frustration.</p>
<p>So from now on debtags is going to be a pure python3 package, with dependencies
on only python3-apt and python3-debian. 700 lines of python instead of several
C++ files built on 4 layers of libraries. Hopefully, this is the last of the
big headaches I get from hacking on this package. Also, one less package using
libept.</p>
Another day in the life of a poor developer
http://www.enricozini.org/blog/2015/python-api-stability
2015-02-27T11:02:33Z
2015-02-27T11:02:33Z
<div class="codehilite"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="c1"># After Python 3.3</span>
<span class="kn">from</span> <span class="nn">collections.abc</span> <span class="kn">import</span> <span class="n">Iterable</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="c1"># This has changed in Python 3.3 (why, oh why?), reinforcing the idea that</span>
<span class="c1"># the best Python version ever is still 2.7, simply because upstream has</span>
<span class="c1"># promised that they won't touch it (and break it) for at least 5 more</span>
<span class="c1"># years.</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Iterable</span>
<span class="kn">import</span> <span class="nn">shlex</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">shlex</span><span class="p">,</span> <span class="s2">"quote"</span><span class="p">):</span>
<span class="c1"># New in version 3.3.</span>
<span class="n">shell_quote</span> <span class="o">=</span> <span class="n">shlex</span><span class="o">.</span><span class="n">quote</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Available since python 1.6 but deprecated since version 2.7: Prior to Python</span>
<span class="c1"># 2.7, this function was not publicly documented. It is finally exposed</span>
<span class="c1"># publicly in Python 3.3 as the quote function in the shlex module.</span>
<span class="c1">#</span>
<span class="c1"># Except everyone was using it, because it was the only way provided by the</span>
<span class="c1"># python standard library to make a string safe for shell use</span>
<span class="c1">#</span>
<span class="c1"># See http://stackoverflow.com/questions/35817/how-to-escape-os-system-calls-in-python</span>
<span class="kn">import</span> <span class="nn">pipes</span>
<span class="n">shell_quote</span> <span class="o">=</span> <span class="n">pipes</span><span class="o">.</span><span class="n">quote</span>
<span class="kn">import</span> <span class="nn">shutil</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">shutil</span><span class="p">,</span> <span class="s2">"which"</span><span class="p">):</span>
<span class="c1"># New in version 3.3.</span>
<span class="n">shell_which</span> <span class="o">=</span> <span class="n">shutil</span><span class="o">.</span><span class="n">which</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Available since python 1.6:</span>
<span class="c1"># http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python</span>
<span class="kn">from</span> <span class="nn">distutils.spawn</span> <span class="kn">import</span> <span class="n">find_executable</span>
<span class="n">shell_which</span> <span class="o">=</span> <span class="n">find_executable</span>
</pre></div>
Akonadi client example
http://www.enricozini.org/blog/2015/akonadi-client-example
2015-02-23T14:44:01Z
2015-02-23T14:44:01Z
<p><a href="http://www.enricozini.org/blog/2015/akonadi-build-hth">After many failed attemps</a> I have managed to build a C++
akonadi client. It has felt like one of the most frustrating programming
experiences of my whole life, so I'm <a href="https://github.com/spanezz/akonadi-client-example">sharing the
results</a> hoping to spare
others from all the suffering.</p>
<p>First thing first, akonadi client libraries are not in <code>libakonadi-dev</code> but in
<code>kdepimlibs5-dev</code>, even if <code>kdepimlibs5-dev</code> does not show in <code>apt-cache search
akonadi</code>.</p>
<p>Then, kdepimlibs is built with Qt4. If your application uses Qt5 (mine was) you
need to port it back to Qt4 if you want to talk to Akonadi.</p>
<p>Then, kdepimlibs does not seem to support qmake and does not ship pkg-config
<code>.pc</code> files, and if you want to use kdepimlibs your build system needs to be
<em>cmake</em>. I ported by code from qmake to cmake, and now qtcreator wants me to
run cmake by hand every time I change the <code>CMakeLists.txt</code> file, and it stopped
allowing to add, rename or delete sources.</p>
<p>Finally, most of the code / build system snippets found on the internet seem
flawed in a way or another, because the build toolchain of Qt/KDE applications
has undergone several redesignins during time, and the network is littered with
examples from different eras. <em>The</em> way to obtain template code to start a
Qt/KDE project is to use
<a href="https://www.kde.org/applications/development/kapptemplate/">kapptemplate</a>.
I have found no getting started tutorial on the internet that said "do not just
copy the snippets from here, run kapptemplate instead so you get them up to
date".</p>
<p>kapptemplate supports building an "Akonadi Resource" and an "Akonadi
Serializer", but it does not support generating template code for an akonadi
client. That left me with the feeling that I was dealing with some software
that wants to be developed but does not want to be used.</p>
<p>Anyway, now an example of how to interrogate Akonadi <a href="https://github.com/spanezz/akonadi-client-example">exists as is on the
internet</a>. I hope that all
the tears of blood that I cried this morning have not been cried in vain.</p>
The wonders of missing documentation
http://www.enricozini.org/blog/2015/akonadi-build-hth
2015-02-23T10:36:18Z
2015-02-23T10:36:18Z
<p><strong>Update</strong>: [[I have managed to build an example Akonadi client
application|akonadi-client-example]].</p>
<p>I'm new here, I want to make a simple C++ GUI app that pops up a
<a href="http://doc.qt.io/qt-5/qcalendarwidget.html">QCalendarWidget</a> which [[my local
Akonadi|akonadi-install]] has appointments.</p>
<p>I open qtcreator, create a new app, hack away for a while, then of course I get
undefined references for all Akonadi symbols, since I didn't tell the build
system that I'm building with akonadi. Ok.</p>
<p>How do I tell the build system that I'm building with akonadi? After 20 minutes
of frantic looking around the internet, I still have no idea.</p>
<p>There is a package called <code>libakonadi-dev</code> which does not seem to have anything
to do with <a href="http://api.kde.org/stable/kdepimlibs-apidocs/akonadi/html/index.html">this</a>.
That page mentions everything about making applications with Akonadi except how
to build them.</p>
<p>There is a package called <code>kdepimlibs5-dev</code> which looks promising: it has no
<code>.a</code> files but it does have haders and cmake files. However, qtcreator is
only integrated with qmake, and I would <em>really</em> like the handholding of an IDE
at this stage.</p>
<p>I put something together naively doing just what looked right, and I managed to
get an application that segfaults <em>before main() is even called</em>:</p>
<div class="codehilite"><pre><span></span><span class="cm">/*</span>
<span class="cm"> * Copyright © 2015 Enrico Zini <enrico@enricozini.org></span>
<span class="cm"> *</span>
<span class="cm"> * This work is free. You can redistribute it and/or modify it under the</span>
<span class="cm"> * terms of the Do What The Fuck You Want To Public License, Version 2,</span>
<span class="cm"> * as published by Sam Hocevar. See the COPYING file for more details.</span>
<span class="cm"> */</span>
<span class="cp">#include</span> <span class="cpf"><QDebug></span><span class="cp"></span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="n">qDebug</span><span class="p">()</span> <span class="o"><<</span> <span class="s">"BEGIN"</span><span class="p">;</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<div class="codehilite"><pre><span></span>QT += core gui widgets
CONFIG += c++11
TARGET = wtf
TEMPLATE = app
LIBS += -lkdecore -lakonadi-kde
SOURCES += wtf.cpp
</pre></div>
<p>I didn't achieve what I wanted, but I feel like I achieved something magical
and beautiful after all.</p>
<p>I shall now perform some <a href="http://en.wikipedia.org/wiki/Haruspex">haruspicy</a> on
those oscure cmake files to see if I can figure something out. But seriously,
people?</p>