<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>danigm.net - work</title><link>https://danigm.net/</link><description></description><lastBuildDate>Mon, 27 Jan 2025 12:00:00 +0100</lastBuildDate><item><title>Python 2</title><link>https://danigm.net/python2.html</link><description>&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/python2.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;In 2020, the
&lt;a href="https://www.python.org/doc/sunset-python-2/"&gt;Python foundation declared Python 2 as not maintained anymore&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Python 2 is really old, not maintained and should not be used by
anyone in any modern environment, but software is complex and python2
still exists in some modern Linux distributions like Tumbleweed.&lt;/p&gt;
&lt;p&gt;The past week the &lt;a href="https://build.opensuse.org/request/show/1240106"&gt;request to delete Python 2&lt;/a&gt; from Tumbleweed was
created and is going through the staging process.&lt;/p&gt;
&lt;p&gt;The main package keeping Python 2 around for Tumbleweed was Gimp 2,
that doesn't depends directly on Python 2, but some of the plugins
depends on it. Now that we've Gimp 3 in Tumbleweed, we are able to
finally remove it.&lt;/p&gt;
&lt;h2&gt;Python 2&lt;/h2&gt;
&lt;p&gt;The first version of Python 2 was released around 2000, so it's now 25
years old. That's not true, because software is a living creature, so
as you may know, Python 2 grew during the following years with patch
and minor releases until 2020 that was the final release 2.7.18.&lt;/p&gt;
&lt;p&gt;But even when it was maintained until 2020, it was deprecated for a
long time so everyone "should" have time to migrate to python 3.&lt;/p&gt;
&lt;h2&gt;Py3K&lt;/h2&gt;
&lt;p&gt;I started to write python code around the year 2006. I was bored
during a summer internship at my third year of computer science, and I
decided to learn something new. In the following months / years I
heard a lot about the futurist &lt;a href="https://peps.python.org/pep-3000/"&gt;Python 3000&lt;/a&gt;, but I didn't worry too
much until it was officially released and the &lt;a href="https://docs.python.org/3.10/library/2to3.html"&gt;migration&lt;/a&gt; started to be
a thing.&lt;/p&gt;
&lt;p&gt;If you have ever write python2 code you will know about some of the
main differences with python3:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;print vs print()&lt;/li&gt;
&lt;li&gt;raw_input() vs input()&lt;/li&gt;
&lt;li&gt;unicode() vs str&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some tools appeared to make it easier to migrate from python2 to
python3, and even it was possible to have code compatible with both
versions at the same time using the &lt;code&gt;__future__&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;You should have heard about the &lt;a href="https://pypi.org/project/six/"&gt;six&lt;/a&gt; package, 2 * 3 = 6. Maybe the
name should be five instead of six, because it was a Python "2 and 3"
compatibility library.&lt;/p&gt;
&lt;h2&gt;Python in Linux command line&lt;/h2&gt;
&lt;p&gt;When python3 started to be the main python, there were some discussion
about how to handle that in different Linux distributions. The
/usr/bin/python binary was present and everyone expect that to be
python2, so almost everyone decided to keep that relation forever and
distribute python3 as /usr/bin/python3, so you can have both installed
without conflicts and there's no confusion.&lt;/p&gt;
&lt;p&gt;But python is an interpreted language, and if you have python code,
you can't tell if it's python2 or python3. The shebang line in the
executable python scripts should point to the correct interpreter and
that should be enough like &lt;code&gt;#!/usr/bin/python3&lt;/code&gt; will use the python3
interpreter and &lt;code&gt;#!/usr/bin/python&lt;/code&gt; will use python2.&lt;/p&gt;
&lt;p&gt;But this is not always true, some distributions uses python3 in
&lt;code&gt;/usr/bin/python&lt;/code&gt; like Archlinux or if you create a virtualenv with
python3, the &lt;code&gt;python&lt;/code&gt; binary points to the python3 interpreter, so a
shebang like &lt;code&gt;#!/usr/bin/python&lt;/code&gt; could be something valid for a
python3 script.&lt;/p&gt;
&lt;p&gt;In any case, the recommended and safest way is to always use &lt;code&gt;python3&lt;/code&gt;
binary because that way it'll work correctly "everywhere".&lt;/p&gt;
&lt;h2&gt;Goodbye&lt;/h2&gt;
&lt;p&gt;It's time to say goodbye to &lt;code&gt;python2&lt;/code&gt;, at least we can remove it now
from Tumbleweed. It'll be around for some more time in Leap, but it's
the time to let it go.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 27 Jan 2025 12:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2025-01-27:/python2.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>opensuse</category></item><item><title>Hackweek 24</title><link>https://danigm.net/hackweek24.html</link><description>&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/hackweek24.png" width="50%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;It's the time for a new &lt;a href="https://hackweek.opensuse.org/"&gt;Hack Week&lt;/a&gt;. The Hack Week 24 was from
November 18th to November 22th, and I've decided to join the &lt;a href="https://hackweek.opensuse.org/projects/opensuse-welcome"&gt;New openSUSE-welcome&lt;/a&gt;
project this time.&lt;/p&gt;
&lt;p&gt;The idea of this project is to revisit the existing openSUSE welcome
app, and I've been trying to help here, specifically for the GNOME
desktop installation.&lt;/p&gt;
&lt;h2&gt;openSUSE-welcome&lt;/h2&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/opensuse-welcome.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;Right now after installing any openSUSE distribution with a graphical
desktop, the user is welcomed on first login with a &lt;a href="https://github.com/openSUSE/openSUSE-welcome/"&gt;custom welcome app&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This custom application is a Qt/QML with some basic information and
useful links.&lt;/p&gt;
&lt;p&gt;The same generic application is used for all desktops, and for popular
desktops right now exists upstream applications for this purpose, so
we were talking on Monday morning about it and decided to use specific
apps for desktops.&lt;/p&gt;
&lt;p&gt;So for GNOME, we can use the &lt;a href="https://gitlab.gnome.org/GNOME/gnome-tour/"&gt;GNOME Tour&lt;/a&gt; application.&lt;/p&gt;
&lt;h2&gt;gnome-tour&lt;/h2&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-tour.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;GNOME Tour is a simple rust/gtk4 application with some fancy images in
a slideshow.&lt;/p&gt;
&lt;p&gt;This application is generic and just shows information about GNOME
desktop, so I created a &lt;a href="https://github.com/openSUSE/gnome-tour"&gt;fork for openSUSE&lt;/a&gt; to do some openSUSE
specific customization and use this application as openSUSE welcome in
GNOME desktop for Tumbleweed and Leap.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-tour-opensuse.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;h2&gt;Desktop patterns, the welcome workflow&lt;/h2&gt;
&lt;p&gt;After some testing and investigation about the current workflow for
the welcome app:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://code.opensuse.org/package/patterns-base/blob/master/f/patterns-base.spec#_861"&gt;x11_enhanced&lt;/a&gt; pattern recommends opensuse-welcome app.&lt;/li&gt;
&lt;li&gt;We can add a &lt;code&gt;Recommends: gnome-tour&lt;/code&gt; to the &lt;a href="https://code.opensuse.org/package/patterns-gnome/blob/master/f/patterns-gnome.spec#_240"&gt;gnome pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The application run using &lt;a href="https://specifications.freedesktop.org/autostart-spec/latest/"&gt;xdg autostart&lt;/a&gt;, so gnome-tour package
   should put the file in &lt;code&gt;/etc/xdg/autostart&lt;/code&gt; and set to hidden on
   close.&lt;/li&gt;
&lt;li&gt;In the case of having a system with multiple desktops, we can
   choose the specific welcome app using the &lt;code&gt;OnlyShowIn/NotShowIn&lt;/code&gt;
   &lt;a href="https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html"&gt;config in desktop file&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So I've created a &lt;a href="https://github.com/openSUSE/openSUSE-welcome/pull/43"&gt;draft PR&lt;/a&gt; to do not show the openSUSE-welcome
app in GNOME, and I've also the &lt;a href="https://build.opensuse.org/package/show/home:dgarcia:branches:GNOME:Next/gnome-tour"&gt;gnome-tour fork&lt;/a&gt; in my home OBS
project.&lt;/p&gt;
&lt;p&gt;I've been testing this configuration in Tumbleweed with GNOME, KDE and
XFCE installed and it works as expected. The openSUSE-welcome is shown
in KDE and XFCE and the gnome-tour app is only shown in GNOME.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-tour-tumbleweed.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;h2&gt;Next steps&lt;/h2&gt;
&lt;p&gt;The next steps to have the GNOME Tour app as default welcome for
openSUSE GNOME installation are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Send forked &lt;code&gt;gnome-tour&lt;/code&gt; package to &lt;code&gt;GNOME:Next&lt;/code&gt; project in OBS.&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;Recommends: gnome-tour&lt;/code&gt; to &lt;code&gt;patterns-gnome&lt;/code&gt; to &lt;code&gt;GNOME:Next&lt;/code&gt; project in OBS.&lt;/li&gt;
&lt;li&gt;Make sure that any other welcome application is &lt;a href="https://github.com/openSUSE/openSUSE-welcome/pull/43"&gt;not shown in GNOME&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Review openQA tests that expect opensuse-welcome and adapt for the
   new application.&lt;/li&gt;
&lt;/ol&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 22 Nov 2024 12:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2024-11-22:/hackweek24.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>opensuse</category><category>hackweek</category></item><item><title>Python 3.13 Beta 1</title><link>https://danigm.net/python313-beta1.html</link><description>&lt;p&gt;&lt;img src="/pictures/python-logo-master-v313-TM.png" width="100%" /&gt;&lt;/p&gt;
&lt;p&gt;Python &lt;a href="https://www.python.org/downloads/release/python-3130b1/"&gt;3.13 beta 1 is out&lt;/a&gt;, and I've been working on the openSUSE
Tumbleweed package to get it ready for the release.&lt;/p&gt;
&lt;h2&gt;Installing python 3.13 beta 1 in Tumbleweed&lt;/h2&gt;
&lt;p&gt;If you are adventurous enough to want to test the python 3.13 and you
are using openSUSE Tumbleweed, you can give it a try and install the
current devel package:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# zypper addrepo -p 1000 https://download.opensuse.org/repositories/devel:languages:python:Factory/openSUSE_Tumbleweed/devel:languages:python:Factory.repo&lt;/span&gt;
&lt;span class="c1"&gt;# zypper refresh&lt;/span&gt;
&lt;span class="c1"&gt;# zypper install python313&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;What's new in Python 3.13&lt;/h2&gt;
&lt;p&gt;Python interpreter is pretty stable nowadays and it doesn't change too
much to keep code compatible between versions, so if you are writing
modern Python, your code should continue working whit this new
version. But it's actively developed and new versions have cool new
functionalities.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3.13/whatsnew/3.13.html#a-better-interactive-interpreter"&gt;New and improved interactive interpreter&lt;/a&gt;, colorized prompts,
   multiline editing with history preservation, interactive help with
   &lt;code&gt;F1&lt;/code&gt;, history browsing with &lt;code&gt;F2&lt;/code&gt;, paste mode with &lt;code&gt;F3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A set of performance improvements.&lt;/li&gt;
&lt;li&gt;Removal of many deprecated modules: aifc, audioop, chunk, cgi,
   cgitb, crypt, imghdr, mailcap, msilib, nis, nntplib, ossaudiodev,
   pipes, sndhdr, spwd, sunau, telnetlib, uu, xdrlib, lib2to3.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Enabling Experimental JIT Compiler&lt;/h2&gt;
&lt;p&gt;The python 3.13 version will arrive with an &lt;a href="https://docs.python.org/3.13/whatsnew/3.13.html#experimental-jit-compiler"&gt;experimental functionality&lt;/a&gt;
to improve performance. We're building with the
&lt;code&gt;--enable-experimental-jit=yes-off&lt;/code&gt; so it's disabled by default but it
can be enabled with a virtualenv before launching:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PYTHON_JIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3.13
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Free-threaded CPython&lt;/h2&gt;
&lt;p&gt;The python 3.13 has another build option to disable the Global
Interpreter Lock (&lt;code&gt;--disable-gil&lt;/code&gt;), but we're not enabling it because
in this case it's not possible to keep the same behavior. Building
with &lt;code&gt;disabled-gil&lt;/code&gt; will break compatibility.&lt;/p&gt;
&lt;p&gt;In any case, maybe it's interesting to be able to provide another
version of the interpreter with the GIL disabled, for specific cases
where the performance is something critical, but that's something to
evaluate.&lt;/p&gt;
&lt;p&gt;We can think about having a &lt;code&gt;python313-nogil&lt;/code&gt; package, but it's not
something trivial to be able to have &lt;code&gt;python313&lt;/code&gt; and &lt;code&gt;python313-nogil&lt;/code&gt;
at the same time in the same system installation, so I'm not planning
to work on that for now.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 22 May 2024 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2024-05-22:/python313-beta1.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>linux</category><category>python</category></item><item><title>Where's my python code?</title><link>https://danigm.net/wheres-my-python-code.html</link><description>&lt;p&gt;&lt;img src="/pictures/python-logo-master-v3-TM.png" width="100%" /&gt;&lt;/p&gt;
&lt;p&gt;Python is a interpreted language, so the python code are just text
files with the &lt;code&gt;.py&lt;/code&gt; extension. For simple scripts it's really easy to
have your files located, but when you starts to use dependencies and
different projects with different requirements the thing starts to get
more complex.&lt;/p&gt;
&lt;h2&gt;PYTHONPATH&lt;/h2&gt;
&lt;p&gt;The Python interpreter uses a list of paths to try to locate python
modules, for example this is what you can get in a modern GNU/Linux
distribution by default:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="mf"&gt;3.11.7&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GCC&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;linux&lt;/span&gt;
&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;help&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;copyright&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;credits&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;license&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python311.zip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python3.11&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python3.11/lib-dynload&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python3.11/site-packages&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python3.11/_import_failed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib/python3.11/site-packages&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These are the default paths where the python modules are installed. If
you install any python module using your linux packaging tool, the
python code will be placed inside the &lt;code&gt;site-packages&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;So system installed python modules can be located in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/usr/lib/python3.11/site-packages&lt;/code&gt; for modules that are
   architecture independent (pure python, all &lt;code&gt;.py&lt;/code&gt; files)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/usr/lib64/python3.11/site-packages&lt;/code&gt; for modules that depends on
   the arquitecture, that's something that uses low level libraries
   and needs to build so there are some &lt;code&gt;.so&lt;/code&gt; files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;pip&lt;/h2&gt;
&lt;p&gt;When you need a new python dependency you can try to install from your
GNU/Linux distribution using the default package manager like
&lt;code&gt;zypper&lt;/code&gt;, &lt;code&gt;dnf&lt;/code&gt; or &lt;code&gt;apt&lt;/code&gt;, and those python files will be placed in the
system paths that you can see above.&lt;/p&gt;
&lt;p&gt;But distributions doesn't pack all the python modules and even if they
do, you can require an specific version that's different from the one
packaged in your favourite distribution, so in python it's common to
install dependencies from the &lt;a href="https://pypi.org/"&gt;Python Package Index (PyPI)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Python has a tool to install and manage Python packages that looks for
desired python modules in PyPI.&lt;/p&gt;
&lt;p&gt;You can install new dependencies with &lt;code&gt;pip&lt;/code&gt; just like:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;django
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And that command looks for the &lt;code&gt;django&lt;/code&gt; python module in the PyPI,
downloads and install it, in your user
&lt;code&gt;$HOME/.local/lib/python3.11/site-packages&lt;/code&gt; folder if you
use &lt;code&gt;--user&lt;/code&gt;, or in a global system path like &lt;code&gt;/usr/local/lib&lt;/code&gt; or
&lt;code&gt;/usr/lib&lt;/code&gt; if you run pip as root.&lt;/p&gt;
&lt;p&gt;But the usage of &lt;code&gt;pip&lt;/code&gt; directly in the system is something &lt;strong&gt;not
recommended today&lt;/strong&gt;, and even &lt;a href="https://packaging.python.org/en/latest/specifications/externally-managed-environments/#externally-managed-environments"&gt;it's disabled&lt;/a&gt; in some
distributions, like openSUSE Tumbleweed.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;danigm&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;django&lt;/span&gt;
&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;externally&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;managed&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;

&lt;span class="err"&gt;×&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;externally&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;managed&lt;/span&gt;
&lt;span class="err"&gt;╰─&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;To&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;system&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;wide&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;try&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;zypper&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;python311&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;xyz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xyz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;package&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trying&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wish&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rpm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;packaged&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;virtual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;python3&lt;/span&gt;&lt;span class="m m-Double"&gt;.11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;Then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;pip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wish&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rpm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;packaged&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;may&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;easiest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nx"&gt;pipx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xyz&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;manage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;virtual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pipx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;via&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nx"&gt;zypper&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;python311&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;pipx&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;believe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mistake&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;please&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;installation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;distribution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;You&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;risk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;breaking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;installation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;passing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;system&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;See&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PEP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;668&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;detailed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;specification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;virtualenvs&lt;/h2&gt;
&lt;p&gt;Following the current recommendation, the correct way of installing
third party python modules is to use &lt;code&gt;virtualenvs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;virtualenvs&lt;/code&gt; are just specific folders where you install your
python modules and some scripts that make's easy to use it in
combination with your system libraries so you don't need to modify the
&lt;code&gt;PYTHONPATH&lt;/code&gt; manually.&lt;/p&gt;
&lt;p&gt;So if you've a custom project and want to install python modules you
can create your own virtualenv and use pip to install dependencies
there:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm@localhost tmp&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;venv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm@localhost tmp&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;activate&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm@localhost tmp&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;
&lt;span class="n"&gt;Collecting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;Successfully&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;installed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;asgiref&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;3.7.2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;5.0.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sqlparse&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.4.4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So all dependencies are installed in my new virtualenv folder and if I
use the python from the virtualenv it's using those paths, so all the
modules installed there are usable inside that virtualenv:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm&lt;/span&gt;&lt;span class="nd"&gt;@localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="mf"&gt;.11&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;contrib&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;shortcuts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;templatetags&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;
&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;__main__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;__pycache__&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm&lt;/span&gt;&lt;span class="nd"&gt;@localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;import django; print(django.__version__)&amp;quot;&lt;/span&gt;
&lt;span class="mf"&gt;5.0.1&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm&lt;/span&gt;&lt;span class="nd"&gt;@localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deactivate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With virtualenvs you can have multiple python projects, with different
dependencies, isolated, so you use different dependencies when you
activate your desired virtualenv:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;activate &lt;code&gt;$ . ./myenv/bin/activate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;deactivate &lt;code&gt;$ deactivate&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;High level tools to handle virtualenvs&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://docs.python.org/3/library/venv.html#module-venv"&gt;venv&lt;/a&gt; module is a default Python module and as you can see
above, it's really simple to use, but there are some tools that
provides some tooling around it, to make it easy for you, so usually
you don't need to use &lt;code&gt;venv&lt;/code&gt; directly.&lt;/p&gt;
&lt;h3&gt;pipx&lt;/h3&gt;
&lt;p&gt;For final python tools, that you are not going to use as dependencies
in your python code, the recommended tool to use is &lt;a href="https://github.com/pypa/pipx"&gt;pipx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="/pictures/pipx_demo.gif" width="100%" /&gt;&lt;/p&gt;
&lt;p&gt;The tool creates virtualenv automatically and links the binaries so
you don't need to worry about anything, just use as a way to install
third party python applications and update/uninstall using it. The
&lt;code&gt;pipx&lt;/code&gt; won't mess your system libraries and each installation will use
a different virtualenv, so even tools with incompatible dependencies
will work nicely together in the same system.&lt;/p&gt;
&lt;h3&gt;Libraries, for Python developers&lt;/h3&gt;
&lt;p&gt;In the case of Python developers, when you need to manage dependencies
for your project, there are a lot of nice high level tools for
&lt;a href="https://packaging.python.org/en/latest/tutorials/managing-dependencies/#other-tools-for-application-dependency-management"&gt;managing dependencies&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pdm-project/pdm"&gt;PDM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/hatch"&gt;hatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/thoth-station/micropipenv"&gt;micropipenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jazzband/pip-tools"&gt;pip-tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packaging.python.org/en/latest/key_projects/#pipenv"&gt;pipenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/python-poetry/poetry"&gt;poetry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These tools provides different ways of managing dependencies, but all
of them relies in the use of &lt;code&gt;venv&lt;/code&gt;, creating the virtualenv in
different locations and providing tools to enable/disable and manage
dependencies inside those virtualenvs.&lt;/p&gt;
&lt;p&gt;For example, &lt;code&gt;poetry&lt;/code&gt; creates virtualenvs by default inside the
&lt;code&gt;.cache&lt;/code&gt; folder, in my case I can find all poetry created virtualenvs
in:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/home/danigm/.cache/pypoetry/virtualenvs/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Most of these tools add other utilities on top of the dependency
management. Just for installing python modules easily you can always
use default &lt;code&gt;venv&lt;/code&gt; and &lt;code&gt;pip&lt;/code&gt; modules, but for more complex projects
it's worth to investigate high level tools, because it'll make easy to
manage your project dependencies and virtualenvs.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There are a lot of python code inside any modern Linux distribution
and if you're a python developer it's possible to have a lot of python
code. Make sure to know the source of your modules and do not mix
different environments to avoid future headaches.&lt;/p&gt;
&lt;p&gt;As a final trick, if you don't know where's the actual code of some
python module in your running python script, you can always ask:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__file__&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;/tmp/myenv/lib64/python3.11/site-packages/django/__init__.py&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This could be even more complicated if you start to use containers
and different python versions, so keep you dependencies clean and up
to date and make sue that you know &lt;strong&gt;where is your Python code&lt;/strong&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 03 Feb 2024 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2024-02-03:/wheres-my-python-code.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>linux</category><category>python</category></item><item><title>Hackweek 23</title><link>https://danigm.net/hackweek23.html</link><description>&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/hackweek23.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hackweek.opensuse.org/"&gt;Hack Week&lt;/a&gt; is the time SUSE employees experiment, innovate &amp;amp; learn
interruption-free for a whole week! Across teams or alone, but always without
limits.&lt;/p&gt;
&lt;p&gt;The Hack Week 23 was from November 6th to November 10th, and my project was to
gvie some &lt;a href="https://hackweek.opensuse.org/23/projects/gnome-love"&gt;love to the GNOME Project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before the start of the Hack week I asked in the GNOME devs Matrix channel,
what project needs some help and they gave me some ideas. At the end I decided
to work on the &lt;a href="https://gitlab.gnome.org/GNOME/gnome-calendar/"&gt;GNOME Calendar&lt;/a&gt;, more specifically, improving the test suite
and fixing &lt;a href="https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/1093"&gt;issues related to timezones&lt;/a&gt;, DST, etc.&lt;/p&gt;
&lt;h2&gt;GNOME Calendar&lt;/h2&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-calendar.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;GNOME Calendar is a &lt;a href="https://gtk.org/"&gt;Gtk4 application&lt;/a&gt;, written in C, that heavily uses the
&lt;a href="https://gitlab.gnome.org/GNOME/evolution-data-server"&gt;evolution-data-server&lt;/a&gt; library. It's a desktop calendar application with a
modern user interface that can connect handle local and remote calendars. It's
integrated in the GNOME desktop.&lt;/p&gt;
&lt;p&gt;The current gnome-calendar project has some unit tests, using the &lt;a href="https://docs.gtk.org/glib/testing.html"&gt;GLib testing
framework&lt;/a&gt;. But right now there are just a few tests, so the main goal right
now is to increase the number of tests as much as possible, to detect new
problems and regressions.&lt;/p&gt;
&lt;p&gt;Testing a desktop application is not something easy to do. The unit tests can
check basic operations, structures and methods, but the user interaction and
how it's represented is something hard to test. So the best approach is to try
replicate user interactions and check the outputs.&lt;/p&gt;
&lt;p&gt;A more sophisticated approach could be to start to use the accessibility stack
in tests, so it's possible to verify the UI widgets output without the need of
rendering the app.&lt;/p&gt;
&lt;p&gt;With gnome-calendar there's another point of complexity for tests because it
relies on the evolution-data-server to be running, the app communicates with it
using dbus, so to be able to do more complex tests we should mock the
evolution-data-server and we should create fake data for testing.&lt;/p&gt;
&lt;h2&gt;My contribution&lt;/h2&gt;
&lt;p&gt;By the end of the week I've created four &lt;a href="https://gitlab.gnome.org/GNOME/gnome-calendar/-/merge_requests?scope=all&amp;amp;state=all&amp;amp;author_username=danigm&amp;amp;label_name%5B%5D=Timezones"&gt;Merge requests&lt;/a&gt;, three of them
have been merged now, and I'll continue working on this project in the
following weeks/months.&lt;/p&gt;
&lt;p&gt;I'm happy with the work that I was able to do during this Hack Week. I've
learned a bit about testing with GLib in C, and a lot about the
evolution-data-server, timezones and calendar problems.&lt;/p&gt;
&lt;p&gt;It's just a desktop calendar application, how hard it could be? Have you ever
deal with dates, times and different regions and time zones? It's a nightmare.
There are a lot of edge cases working with dates that can cause problems,
operations with dates in different time zones, changes in dates for daylight
saving, if I've an event created for October 29th 2023 at 2:30 it will happens
two times?&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-calendar-issues.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;A lot of problems could happen and there are a lot of bugs reported for
gnome-calendar related to this kind of issues, so working on this is not
something simple, it requires a lot of edge case testing and that's the plan,
to cover most of them with automated tests, because any small change could lead
to a bug related to time zones that won't be noticed until someone has an
appointment at a very specific time.&lt;/p&gt;
&lt;p&gt;And this week was very productive thanks to the people working on
gnome-calendar. Georges Stavracas reviews my MR very quickly and it was
possible to merge during the week, and Jeff Fortin does a great work with the
issues in gitlab and leading me to most relevant bugs.&lt;/p&gt;
&lt;p&gt;So after a week of going deep into the gnome-calendar source code it could be a
pity to just forget about it, so I'll try to keep the momentum and continue
working on this project, of course, I'll have just a few hours per week, but
any contribution is better than nothing. And maybe for the next summer I can
propose a Google Summer of Code project to get an intern working on this full
time.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 10 Nov 2023 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2023-11-10:/hackweek23.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>opensuse</category><category>hackweek</category></item><item><title>Updating GNOME shell extensions to GNOME 45</title><link>https://danigm.net/gnome-45-extensions.html</link><description>&lt;p&gt;&lt;img src="/pictures/GNOME45.webp" width="100%" /&gt;&lt;/p&gt;
&lt;p&gt;The new version of the &lt;a href="https://www.gnome.org/"&gt;GNOME desktop&lt;/a&gt; was released &lt;a href="https://foundation.gnome.org/2023/09/20/introducing-gnome-45/"&gt;more than one month&lt;/a&gt;
ago. It takes some time to arrive to the final user, because distributions
should integrate, tests and release the new desktop, and that's not something
simple, and it should integrate in the distribution release planning.&lt;/p&gt;
&lt;p&gt;So right now, it's possible that there's just a few people with the latest
version of the desktop right now, just people with rolling release distros or
people using testing versions of mayor distributions.&lt;/p&gt;
&lt;p&gt;This is one of the reasons because a lot of gnome-shell extensions aren't
updated to work with the latest version of GNOME, even after a few months,
because even developers doesn't have the latest version of the desktop and
it's not something "easy" to install, without a virtual machine or something
like that. Even if the update is just a change in the metadata.json, there
should be someone to test the extension, and even someone to request this
update, and that will happen once the mayor distributions release a new
version.&lt;/p&gt;
&lt;p&gt;I'm using Tumbleweed, that's a rolling release and GNOME 45 is here just after
the official release, but of course, a lot of extensions are not working, and
in the infamous list of non working extensions there where the three that I'm
&lt;a href="https://extensions.gnome.org/accounts/profile/danigm"&gt;maintaining right now&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/danigm/spotify-ad-blocker"&gt;mute-spotify-ads&lt;/a&gt;, extension to mute the spotify app when it's playing ads.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/danigm/gnome-shell-calculator"&gt;calc&lt;/a&gt;, a simple calculator in the alt+F2 input.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/danigm/hide-minimized"&gt;hide-minimized&lt;/a&gt;, hide minimized windows from alt+tab and overview.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/GNOME45-desktop.webp" /&gt;
&lt;/p&gt;

&lt;h2&gt;The correct way&lt;/h2&gt;
&lt;p&gt;The correct way to maintain and update a gnome-shell extension should be to
test and update "before" the official release of GNOME. It should be something
easy for me, using Tumbleweed I can just add the &lt;a href="https://build.opensuse.org/project/show/GNOME:Next"&gt;GNOME Next&lt;/a&gt; repository,
install the new desktop when it's in beta stage, and update the extension
there.&lt;/p&gt;
&lt;p&gt;But that's something that require an active maintainership... And right now
what I do is to update the extensions when they are broken for me, so just when
I need them, and that's after I get the new desktop and I find some time to
update.&lt;/p&gt;
&lt;p&gt;I know that's not the correct way and this produces a bad experience for other
people using the extensions, but this is the easier thing to do for me. Maybe
in the future I can do it correctly, and provide a tested update before the
official release, maybe using snapper to be able to go back to stable, without
the need of using virtual machines.&lt;/p&gt;
&lt;h2&gt;Update your extension to GNOME 45&lt;/h2&gt;
&lt;p&gt;The update to GNOME 45 was a bit more complex than previous ones. This version
of the shell and gjs change a lot of things, so the migration it's not just to
add a new number to the metadata.json, but requires incompatible changes, so
extensions that works for GNOME 45 won't work for previous versions and
vice versa.&lt;/p&gt;
&lt;p&gt;But the people working in gnome-shell does a great work documenting and there's
a really nice guide about &lt;a href="https://gjs.guide/extensions/upgrading/gnome-shell-45.html"&gt;how to upgrade your extension&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The most important part is the import section, that now it has a different syntax.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Before&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GNOME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;
&lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;imports&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GNOME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;resource:///org/gnome/shell/ui/main.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And some changes in the extension class, that now can inherit from existing
ones to provide common usage, like preferences window:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;Adw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gi://Adw&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ExtensionPreferences&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gettext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;MyExtensionPreferences&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ExtensionPreferences&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;fillPreferencesWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_settings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getSettings&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PreferencesPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PreferencesGroup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Group Title&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 03 Nov 2023 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2023-11-03:/gnome-45-extensions.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>linux</category><category>javascript</category></item><item><title>One year of Tumbleweed</title><link>https://danigm.net/tumbleweed.html</link><description>&lt;p class="img"&gt;
    &lt;a target="_blank" href="https://www.opensuse.org/#Tumbleweed"&gt;
        &lt;img src="/pictures/tumbleweed.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;More than a year has passed since I switched to &lt;a href="https://www.opensuse.org/#Tumbleweed"&gt;openSUSE Tumbleweed&lt;/a&gt;
Linux distribution, in both, my work computer (for obvious reasons)
and in my personal computer and I can say that I'm really happy with
the change.&lt;/p&gt;
&lt;p&gt;Tumbleweed is a &lt;a href="https://en.wikipedia.org/wiki/Rolling_release"&gt;rolling release&lt;/a&gt; distribution, and in this kind of
distributions there are a lot of changes every week, if you want the
latest software, this kind of distribution is the way to go. But with
high update frequency you are exposed to some kind of instability,
it's impossible to have the latest changes without some broken program
here and there, because not everyone is able to follow upstream
changes without some weeks or months to update.&lt;/p&gt;
&lt;h2&gt;My distro history&lt;/h2&gt;
&lt;p&gt;I've been always a Linux user, since I get my first computer at 2003.
In those days I was using a &lt;a href="https://www.debian.org/"&gt;debian&lt;/a&gt; base distribution called
&lt;a href="https://www.knopper.net/knoppix/index-en.html"&gt;knoppix&lt;/a&gt;. Then I switched to &lt;a href="https://ubuntu.com/"&gt;ubuntu&lt;/a&gt; when it appeared around 2004.
But at that time I was a computer science student and I was exploring
the whole free software and Linux ecosystem, so I was changing my
distribution every time that I found a new one.&lt;/p&gt;
&lt;p&gt;Like a lot of distro-hoppers, at some point I landed at &lt;a href="https://archlinux.org/"&gt;ArchLinux&lt;/a&gt;
and there I discovered the rolling release concept. And that was my
home for some time, it was nice to have the latest available software
just after the release.&lt;/p&gt;
&lt;p&gt;At some point I bough a new computer and it was too new to work
correctly with the kernel distributed in ArchLinux, so I tried
different distributions and at that moment &lt;a href="https://fedoraproject.org/"&gt;Fedora&lt;/a&gt; was the distro
that works without too much complications with that computer, so I
picked that one.&lt;/p&gt;
&lt;p&gt;In 2019 I started to work at Endless and at that time I should try the
&lt;a href="https://www.endlessos.org/"&gt;EndlessOS&lt;/a&gt;, so I played a bit with &lt;a href="https://danigm.net/endlessos-dual-boot.html"&gt;the dual boot&lt;/a&gt;, having
Fedora and EndlessOS at the same time. That was the first time that I
get in contact with immutable distributions, something that's getting
more popular everyday, but this distributions rely a lot on containers
(flatpak, podman) and, even being something that could work, as a
software engineer, I don't feel comfortable enough needing a container
with another distribution to do something that could be in my system.&lt;/p&gt;
&lt;p&gt;In 2022 I started to &lt;a href="https://danigm.net/suse.html"&gt;work at SUSE&lt;/a&gt; and for the first time I tried
the openSUSE distribution until today.&lt;/p&gt;
&lt;h2&gt;The Tumbleweed&lt;/h2&gt;
&lt;p&gt;Today I've three different computers with Tumbleweed running. One for
work, Thinkpad T14s, one for personal usage, Dell inspiron 5490, and
another one as a personal media server, Libre computer &lt;a href="https://libre.computer/products/aml-s805x-ac/"&gt;La-frite&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The best thing of having Tumbleweed for me is that I get the latest
&lt;strong&gt;GNOME&lt;/strong&gt; as soon as it's released. And another big thing for this
distribution is how easy it's to fix something upstream thanks to the
&lt;a href="https://build.opensuse.org/project/show/openSUSE:Factory"&gt;Open Build Service&lt;/a&gt;, but I work everyday with that, so I'm
biased. For sure, any other community distribution has different ways
to contribute, but I find this one easy enough.&lt;/p&gt;
&lt;p&gt;Even being a rolling release distro, Tumbleweed doesn't break a lot. I
can't say that it's stable, because the API of everything is broken
everyday, but the &lt;a href="https://openqa.opensuse.org/group_overview/1"&gt;distribution is tested&lt;/a&gt; for every release and
at least some level of package compatibility check is done. That makes
Tumbleweed a good distribution and I can update without fearing some
weird package breakage.&lt;/p&gt;
&lt;p&gt;I usually update my work and personal laptops once a week, and
la-frite not so often, maybe every 6 months.&lt;/p&gt;
&lt;p&gt;With the default installation, Tumbleweed uses btrfs with snapshots,
and it's really easy to go back and forward using the
&lt;a href="https://en.opensuse.org/openSUSE:Snapper_Tutorial"&gt;snapper tool&lt;/a&gt;. So it's really easy to go back to a good state if
the distribution is broken for some reason, and wait for a fix.&lt;/p&gt;
&lt;h2&gt;The problems that I found during this year&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Some problems with the NVidia graphic card in my Dell laptop, some
   times the kernel and the driver were not working correctly. I had
   to use snapper to get the NVidia working again, but fixed a few
   days later.&lt;/li&gt;
&lt;li&gt;Currently I'm having some random crashes because some bug with
   &lt;a href="https://bugzilla.suse.com/show_bug.cgi?id=1215695"&gt;amdgpu&lt;/a&gt; and wayland and mutter, but it's not too annoying for
   me to go back, so I didn't use snapper this time and I'm facing
   this random crashes waiting for the fix.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Long live the Tumbleweed&lt;/h2&gt;
&lt;p&gt;So far so good. Tumbleweed is a nice distribution that I'm enjoying.
It's not getting in the way and I can find almost anything that I need
for work, programming, gaming, media, etc. I'm really happy with this
distribution and it's the perfect distribution for people like me,
that want to have the latest things.&lt;/p&gt;
&lt;p&gt;I know that there are other openSUSE flavors that are interesting,
like the &lt;a href="https://en.opensuse.org/Portal:Aeon"&gt;immutable ones&lt;/a&gt;, &lt;a href="https://en.opensuse.org/openSUSE:Slowroll"&gt;Leap&lt;/a&gt; or the latest one
&lt;a href="https://en.opensuse.org/openSUSE:Slowroll"&gt;Slowroll&lt;/a&gt;, but Tumbleweed is the one for me.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 06 Oct 2023 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2023-10-06:/tumbleweed.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>openSUSE</category><category>tumbleweed</category><category>linux</category><category>distribution</category></item><item><title>Hackweek 2023</title><link>https://danigm.net/hackweek22.html</link><description>&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/hackweek.png" width="50%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hackweek.opensuse.org/"&gt;Hack Week&lt;/a&gt; is the time SUSE employees experiment, innovate &amp;amp; learn
interruption-free for a whole week! Across teams or alone, but always without
limits.&lt;/p&gt;
&lt;p&gt;This year the Hack Week was this week, the last week of January and for my
first SUSE hack week I decided to work in something funny, &lt;a href="https://hackweek.opensuse.org/22/projects/linux-immersive-learning-system-lils"&gt;LILS&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Linux Immersive Learning System (LILS)&lt;/h2&gt;
&lt;p&gt;I don't think that this is a good name, but don't focus on it. The main idea of
this project is to create some basic machinery to be able to write
"interactive" tutorials or games using the &lt;a href="https://www.inklestudios.com/ink/"&gt;INK language&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is not an original idea, indeed all I've done is something that's
currently working on &lt;a href="https://www.endlessos.org/"&gt;EndlessOS&lt;/a&gt;, and was the main idea behind the dead
project &lt;a href="https://www.hack-computer.com/"&gt;Hack Computer&lt;/a&gt;, you can even take a look to the
&lt;a href="https://flathub.org/apps/details/com.hack_computer.Clubhouse"&gt;Hack app in flathub&lt;/a&gt;. But I wanted to work around this, and create
something simpler, from scratch.&lt;/p&gt;
&lt;p&gt;I wanted to build something simple, with just Python, and make it simple enough
to be able to build other tools on top. The design is simple, an INK parser,
with a simple game runner. In the INK script you can define &lt;em&gt;commands&lt;/em&gt;, to do
something special, and wait for events with &lt;em&gt;listeners&lt;/em&gt;, to wait for an event
in the OS to continue.&lt;/p&gt;
&lt;p&gt;With this basic functionality it's possible to build different user interfaces
for different environments. And the original idea was to make the &lt;em&gt;commands&lt;/em&gt;
and &lt;em&gt;listeners&lt;/em&gt; something extensible with a simple API, but that's something
that I have not done yet, it's all Python functions without extension point.&lt;/p&gt;
&lt;p&gt;The code can be found in &lt;a href="https://github.com/danigm/lils"&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The INK parser&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/inky.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The most complex part of this project is the INK language parser. The &lt;a href="https://github.com/inkle/ink"&gt;Ink&lt;/a&gt;
parser is free software and there's a Linux version that you can use to parse
and &lt;strong&gt;compile&lt;/strong&gt; to &lt;em&gt;json&lt;/em&gt;, but I wanted to create my own parser with Python.&lt;/p&gt;
&lt;p&gt;I've spent most of the Hack Week time fighting with the parser and indeed was
the most challenging and fun part, because I've not worked a lot with parsers
and it's not something easy as pie 😛️.&lt;/p&gt;
&lt;p&gt;I remember creating a java compiler long time ago, when I was in the Seville
University, for the Language Processors course. We did that with &lt;a href="https://www.antlr.org/"&gt;ANTLR&lt;/a&gt;, so
starting from that, and looking for a Python lib, I found the &lt;a href="https://github.com/lark-parser/lark"&gt;Lark&lt;/a&gt;
project. So if you like regular expressions, writing a grammar is a lot more
FUN.&lt;/p&gt;
&lt;p&gt;At the end I was able to support some basic INK language with support for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Text&lt;/li&gt;
&lt;li&gt;Tag support&lt;/li&gt;
&lt;li&gt;Options, with suppress text support&lt;/li&gt;
&lt;li&gt;Knots, Stitches and Diverts&lt;/li&gt;
&lt;li&gt;Include other .ink files&lt;/li&gt;
&lt;li&gt;Variable definition and basic operations&lt;/li&gt;
&lt;li&gt;Knots and Stitches automatic visiting count variables&lt;/li&gt;
&lt;li&gt;Conditional options using variables&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It still fails in some cases, the comments and &lt;em&gt;TODO&lt;/em&gt; placed in between text is
not detected correctly and there's a lot of complex stuff that's not supported
yet, but with what's supported right now it's possible to create complex
scripts with loops and complex game graphs, so it's good enough to build games
just with it.&lt;/p&gt;
&lt;h2&gt;GNOME shell extension&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;video src="/pictures/lils.mp4" width="100%" autoplay controls loop /&gt;
&lt;/p&gt;

&lt;p&gt;To integrate with the system I've done a simple &lt;a href="https://github.com/danigm/lils/tree/master/lils%40danigm.net"&gt;GNOME shell extension&lt;/a&gt;.
The extension just shows the text as bubbles and options as buttons, it's
really simple and I've no time to make it something ready to be used, but
I was able to make something usable.&lt;/p&gt;
&lt;p&gt;To be able to run the &lt;em&gt;LILS&lt;/em&gt; python library from &lt;em&gt;gjs&lt;/em&gt; I've created a simple
&lt;em&gt;dbus&lt;/em&gt; service that exposes the basic &lt;em&gt;InkScript&lt;/em&gt; class functionality as a dbus
API.&lt;/p&gt;
&lt;p&gt;I was thinking about being able to change the desktop background, depending of
the value of a &lt;em&gt;background&lt;/em&gt; variable in the script and do something similar to
play music and sounds, so it could be a cool &lt;em&gt;game engine&lt;/em&gt; with some additions.&lt;/p&gt;
&lt;h2&gt;SUSE Hack Week&lt;/h2&gt;
&lt;p&gt;So this Hack week was really fun and I learned a lot. It's really great that
SUSE does things like this, letting us work in different projects for a week,
to learn, to grow or to just explore different paths.&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/IxscORgeqOY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen&gt;&lt;/iframe&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Tue, 03 Jan 2023 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2023-01-03:/hackweek22.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>ink</category><category>python</category></item><item><title>The end of 2022</title><link>https://danigm.net/2022.html</link><description>&lt;p class="img"&gt;
    &lt;img src="/pictures/2023.png" /&gt;
&lt;/p&gt;

&lt;p&gt;Is the end of 2022 and the beginning of 2023, so it's the right time to look
back and see what great things happened during the year, and also it's the time
to plan some new year resolutions.&lt;/p&gt;
&lt;h2&gt;My contribution to GNOME in 2022&lt;/h2&gt;
&lt;p&gt;I've been focused this year on the &lt;a href="https://gitlab.gnome.org/GNOME/gtranslator"&gt;GNOME Translation Editor&lt;/a&gt;, migrating it
to Gtk4. It's not ready yet, but I hope I will be able to have a working
version soon™.&lt;/p&gt;
&lt;p&gt;It started this summer with one intern from &lt;a href="https://www.outreachy.org/outreachy-may-2022-internship-round/#gnome-migrate-gnome-translation-editor-to-gtk4"&gt;Outreachy&lt;/a&gt;, that did some
initial work, building with the new Gtk4, and after the summer I started to
clean the code and fixing issues, and lately, I'm trying to replace some
deprecations for the next Gtk release.&lt;/p&gt;
&lt;p&gt;so I'm working on the code, modernizing it, and replacing every usage of
&lt;code&gt;GtkDialog&lt;/code&gt; and &lt;code&gt;GtkTreeView&lt;/code&gt;, and trying to follow the &lt;a href="https://developer.gnome.org/hig/"&gt;GNOME HIG&lt;/a&gt; as much
as possible.&lt;/p&gt;
&lt;h3&gt;Live coding Streaming&lt;/h3&gt;
&lt;p&gt;I started the year spending a lot of time working on Gtk on live stream on
&lt;a href="https://www.twitch.tv/abentogil/"&gt;Twitch&lt;/a&gt;, but after the summer I was spending less time... I didn't find the
time or the energy to do it regularly.&lt;/p&gt;
&lt;h2&gt;Changes in the business&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/endless-photo.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;This year was also a year of changes in my work life. After the summer I left
Endless, after three years of working there, to join SUSE.&lt;/p&gt;
&lt;p&gt;I really enjoy my time at &lt;a href="https://www.endlessos.org/"&gt;EndlessOS&lt;/a&gt;, the first years working on the Hack
Computer and the last year working on the Endless Key. I really like the
EndlessOS mission and what I was doing there, with a lot of great people.&lt;/p&gt;
&lt;p&gt;But I was looking for something more in my career path, and I had the
opportunity to join SUSE. Since September, I'm part of the Python packaging
team at SUSE and I've to say that I really love this job. It's a bit different
from what I have been doing before, but the maintainer life is something that I
enjoy, having the opportunity to contribute to a lot of different projects and
debugging and fixing random bugs is one of the most rewarding tasks to do (when
you are able to find the problem).&lt;/p&gt;
&lt;p&gt;Tumbleweed is now my favourite GNU/Linux distribution and the future of
&lt;a href="https://news.opensuse.org/2022/12/22/second-prototype-advances-alp/"&gt;SUSE ALP&lt;/a&gt; looks really promising.&lt;/p&gt;
&lt;h2&gt;Changes in life&lt;/h2&gt;
&lt;p&gt;This year comes also with a lot of changes in my personal life too! At the
beginning of the year I was able to bought a house, so I've now a permanent
residency, after a lot of years of changing from one rent house to another one.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/blackbelt.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;And this year was also the year that I was able to get the kickboxing black
belt, after almost 8 years of practicing. This is the end of a learning path,
and also the beginning of a different one, trying to master this fighting
sport.&lt;/p&gt;
&lt;h2&gt;New year resolutions&lt;/h2&gt;
&lt;p&gt;2022 was great, but we can make 2023 even better, I'm looking always to learn
and improve, so it's good to do some new year resolutions to try to complete
during the next year.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complete the Gtranslator migration to gtk4 and GNOME HIG improvements!&lt;/li&gt;
&lt;li&gt;Be more regular with the live coding streams&lt;/li&gt;
&lt;li&gt;Give some love to the &lt;a href="https://www.bassi.io/articles/2022/12/02/on-pygobject/"&gt;PyGObject&lt;/a&gt; project&lt;/li&gt;
&lt;li&gt;Do more serious kickboxing training and loose 10Kg&lt;/li&gt;
&lt;li&gt;Play more chess games&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's all! Happy new year and Have a lot of fun...&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 30 Dec 2022 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2022-12-30:/2022.html</guid><category>blog</category><category>gnome</category><category>work</category><category>2022</category><category>newyear</category></item><item><title>SUSE is my new distribution (new job)</title><link>https://danigm.net/suse.html</link><description>&lt;p class="img"&gt;
    &lt;a target="_blank" href="https://suse.com"&gt;
        &lt;img src="/pictures/Poster-Always-Changing.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;This week I've started to work at &lt;a href="https://suse.com/"&gt;SUSE&lt;/a&gt;. I'll be working as Python
Specialist, in the packaging team, so I will go back to work on packaging and
distribution after more than ten years. My first job in 2008 was working on a
Ubuntu based local distribution, &lt;a href="https://en.wikipedia.org/wiki/Guadalinex"&gt;Guadalinex&lt;/a&gt;, so packaging and distribution
work is not something new for me.&lt;/p&gt;
&lt;h2&gt;Python&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.python.org/"&gt;Python&lt;/a&gt; was the first language that I fell in love. I learned to write code
with C and C++, but when I discovered Python, in 2006, I found a really nice
language to be able to create amazing things really fast and with a great
community behind.&lt;/p&gt;
&lt;p&gt;I'm very happy for this new opportunity to be able to collaborate to the Python
distribution in all the SUSE flavours, and also to be able to collaborate in
the creation of one of the most famous and used Linux distributions.&lt;/p&gt;
&lt;h2&gt;Tumbleweed&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;a target="_blank" href="https://www.opensuse.org/#Tumbleweed"&gt;
        &lt;img src="/pictures/tumbleweed.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;As part of this job change I've also installed &lt;a href="https://www.opensuse.org/#Tumbleweed"&gt;SUSE Tumbleweed&lt;/a&gt; for the
first time. Tumbleweed is a rolling release distribution with the latests
packages. In the past I was using other rolling releases distributions like
Arch, but this one looks more user friendly.&lt;/p&gt;
&lt;p&gt;I've not spent a lot of time here, but from the point of view of a GNOME
developer, I can say that it's a great distribution for development with
updated packages, and it looks "stable". You can choose the desktop to use on
installation and the GNOME desktop is there without any customization that I've
detected, so it looks like it's a good vanilla GNOME desktop distribution.&lt;/p&gt;
&lt;h2&gt;Endless, it's not the end&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;a target="_blank" href="https://endlessos.org"&gt;
        &lt;img src="/pictures/endless-farewell.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;I'm not working for &lt;a href="https://endlessos.org"&gt;EndlessOS&lt;/a&gt; now, but it's not the end. I've been working
here for almost 4 years. At first I worked on the &lt;a href="https://hack-computer.com/"&gt;Hack Computer&lt;/a&gt; and after
that project didn't work, I was working on the &lt;a href="https://www.endlessos.org/key"&gt;Endless Key&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;During this time I've also collaborated a bit with the EndlessOS distribution,
and I can say that's a really nice distribution to use, the ostree usage for
the whole filesystem is a great idea, and the amount of content that comes with
the installation is really good.&lt;/p&gt;
&lt;p&gt;The EndlessOS Foundation Goal is to reduce the digital divide, providing
content and tools for offline people, centered on kids. This is a great mission
and in the future, if I find the opportunity to help my local community, I'll
try to use the EndlessOS tools and content to provide good learning content for
kids without online access.&lt;/p&gt;
&lt;p&gt;I was very happy these years at Endless, and I've learned a lot from different
great people. It's incredible the number of talented software engineers that
are related to Endless, and for me it was a real privilege to be able to share
this space and mission for a few years.&lt;/p&gt;
&lt;h2&gt;The future!&lt;/h2&gt;
&lt;p&gt;So there we go, I'm exited for this change, and also sad about leaving a great
project, but life is change and we should go ahead and think about the future!
And my future is green now.&lt;/p&gt;
&lt;p&gt;And if you don't know how to pronounce it, here you've a music video:&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/nLdexZlVkAY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 18 Sep 2022 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2022-09-18:/suse.html</guid><category>blog</category><category>gnome</category><category>work</category><category>endless</category><category>suse</category></item><item><title>Endless Orange Week: Hack content creators platform (2)</title><link>https://danigm.net/hack-content-creators-1.html</link><description>&lt;p&gt;The past Friday was the last day of the &lt;a href="http://danigm.net/hack-content-creators.html"&gt;Endless Orange Week&lt;/a&gt;. It was a nice
and fun experience, and even if I was not able to do as much as I wanted, we
were able to make something that "works" in the Hack project.&lt;/p&gt;
&lt;h2&gt;The Hack Quest editor&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/clubhouse-custom-quests-1.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The first step to have custom quests on the Hack app was to complete the
&lt;a href="https://www.inklestudios.com/ink/"&gt;Ink language&lt;/a&gt; support. We started to work on this some time ago, but never
completed the functionality.&lt;/p&gt;
&lt;p&gt;I worked on that the first three days, updating the ink library and building
the missing pieces to be able to load quests from random paths. I've
implemented that in a way that the Hack application is able to receive a path
to a &lt;code&gt;.ink&lt;/code&gt; file, and it's able to build and run the quets.&lt;/p&gt;
&lt;p&gt;The Quests are not just the script, but they have some metadata, like title,
subtitle, description, difficulty and the card image to show on the interface.
To solve that I defined a "custom quest bundle format", that's bassically a
folder with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;questId&lt;/li&gt;
&lt;li&gt;quest.jpg&lt;/li&gt;
&lt;li&gt;metadata.json&lt;/li&gt;
&lt;li&gt;quest.ink&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I also added the functionality to import a bundle zip file and export with
the quest information.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/clubhouse-custom-quests-2.png" /&gt;
&lt;/p&gt;

&lt;p&gt;I created some command line options to use this new functionality:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ink&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;FULL_INK_FILE_PATH&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ink&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;import&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PATH_TO_BUNDLE_OR_INK_FILE&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;Import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ink&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_QUEST_ID&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bundle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Quest creation interface and the Inky Editor&lt;/h3&gt;
&lt;p&gt;The first idea was to try to provide a full quest creation experience in the
app, but that was too much, so we decided to simplify the way to create quests
and depend on the &lt;a href="https://flathub.org/apps/details/com.inklestudios.Inky"&gt;Inky editor&lt;/a&gt; external tool. Manuel Quiñones took some time
to update the flatpak application with the latests ink version, so we can use
to create custom quests.&lt;/p&gt;
&lt;p&gt;The Inky editor provides help about the language, syntax highlighting and a
simple way to test the script, so it's a nice tool. The main problem with this
tool is that it doesn't provide a way to launch it with a file path so it's
not possible to integrate with the Hack app.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/clubhouse-custom-quests-3.png" /&gt;
&lt;/p&gt;

&lt;p&gt;So at the end, the Quest creation dialog is just a way to define the metadata
and to select the Quest ink files from your filesystem. How the ink script is
created is a decision to make for the content creator.&lt;/p&gt;
&lt;h3&gt;The future&lt;/h3&gt;
&lt;p&gt;We've no time to complete all we wanted to do, and I didn't create a new
release, so this new functionality is still not there. But we'll try to do a
release soon.&lt;/p&gt;
&lt;p&gt;Simon is working on some interface improvements and also on a new tutorial
Quest, so we can introduce the Custom Quest creation tool in the same app.&lt;/p&gt;
&lt;h2&gt;The Character editor&lt;/h2&gt;
&lt;p&gt;The other part of this week planning was the character editor. Joana did a
really nice work designing the application, the initial assets and the user
experience, but I had not too much time to work on the implementation.  So I
spent just one day working on this.&lt;/p&gt;
&lt;p&gt;The main idea was to create a new independent app, and then provide a way to
integrate with the Hack application and the custom Quest creation dialog. And
it'll be a simple application so maybe it could be useful or interesting for
other people, it's a fun way to play around and create random faces.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/avatar-creator-1.png" /&gt;
&lt;/p&gt;

&lt;p&gt;We just created the application &lt;a href="https://github.com/endlessm/avatar-creator/"&gt;Avatar Creator&lt;/a&gt;. I created a simple python
Gtk4 application and worked a bit on the basic functionality. So right now it
loads a list of svg assets and provide the 3x3 grid. You can click on a grid
cell and then choose what basic image should go there.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/avatar-creator-2.png" /&gt;
&lt;/p&gt;

&lt;p&gt;I added the initial set of basic images, created by Joana, to create this funny
robot faces, but the format is simple enough to extend with different "avatar
libraries" in the future.&lt;/p&gt;
&lt;p&gt;Right now it's also possible to export to png, so the app is functional, but it
needs a bit more work.&lt;/p&gt;
&lt;p&gt;My idea is to work a bit more in the following weeks, when I have some time, on
weekends or holidays and at some point, publish it in flathub. And lets see if
there are more developers interested on this app so it can grow.&lt;/p&gt;
&lt;p&gt;The application is simple enough to be a good place for GNOME newcomers and it's
also a fun project to work on. A simple toy app to create faces that could
have some potential, some future ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;"Smart" random faces generator&lt;/li&gt;
&lt;li&gt;Configurable grid: Maybe is interesting to make it bigger or smaller to play
   around&lt;/li&gt;
&lt;li&gt;Programmed simple base image manipulations, like rotation, mirror, color&lt;/li&gt;
&lt;li&gt;Animation creation, maybe be able to export to gif&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The Endless Orange Week experience&lt;/h2&gt;
&lt;p&gt;This week was a really nice experience, because we were working in a "personal"
chosen project, that we liked and without the day to day meetings, times
schedules and other related work stuff.&lt;/p&gt;
&lt;p&gt;But that was not all. In Endless we've different teams that work mostly
isolated, because we're working on different fields, we've some overlapping,
but we work day to day as small teams, and this week we were all using the same
slack channel to show our progress, and it was nice.&lt;/p&gt;
&lt;p&gt;Maybe now that we're not a big organization with a lot of workers, we can do
something like this more often, it's always good to know more about other
coworkers and to learn something that maybe it's not related with your main
project, but it could be interesting.&lt;/p&gt;
&lt;p&gt;I'm really happy that we did this Endless Orange Week, it's sad that it ended
too soon, I'm waiting to learn from my coworkers what amazing things they do
during this week and I'm looking forward the next year Orange Week!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 15 Nov 2021 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2021-11-15:/hack-content-creators-1.html</guid><category>blog</category><category>hack</category><category>endless</category><category>orangeweek</category><category>work</category><category>gnome</category><category>software</category></item><item><title>Endless Orange Week: Hack content creators platform</title><link>https://danigm.net/hack-content-creators.html</link><description>&lt;p&gt;This week (Nov 8 – 12) I am participating in Endless Orange Week, a program
where the entire &lt;a href="https://www.endlessos.org/"&gt;Endless&lt;/a&gt; team engages in projects designed to grow our
collective learning related to our skills, work and mission.&lt;/p&gt;
&lt;p&gt;We propose a project, that could be anything, and then work during the whole
week, without distraction. I've choosed to work on the &lt;a href="https://www.hack-computer.com/"&gt;Hack project&lt;/a&gt;, that's a
really nice project that needs some love, because since the past year, we have
&lt;a href="https://www.endlessos.org/key"&gt;other priorities&lt;/a&gt;, so there's no time to improve the Hack app.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/clubhouse.png"&gt;
        &lt;img src="/pictures/clubhouse.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;The project: Hack content creators platform&lt;/h2&gt;
&lt;p&gt;The Hack application is a "Quest" launcher, and each Quest is an interactive
learning experience, a guided introduction to some technology or topic.&lt;/p&gt;
&lt;p&gt;Quests are just python scripts, with a simple library to expose messages to the
user, ask questions, or wait for desktop events, like launch an application,
focus an application, etc. And all these Quests are inside the application, and
are created by the Hack team and released with a new Hack app flatpak.&lt;/p&gt;
&lt;p&gt;The main idea of the project is to provide a simple Quest editor to allow any
Hack user to create and share their our Quests.&lt;/p&gt;
&lt;p&gt;To have this Hack content creators platform we'll need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;To simplify the way we create Quests, instead of a python script, we'll uses
   a Domain Specific Language, called &lt;a href="https://www.inklestudios.com/ink/"&gt;Ink&lt;/a&gt;. We started to work on this, but
   we never ended the support.&lt;/li&gt;
&lt;li&gt;To create the interface to be able to import and export custom Quests, that
   could be zip bundles, with the Ink script and some images.&lt;/li&gt;
&lt;li&gt;To create the interface to write the actual Quests and save or bundle.&lt;/li&gt;
&lt;li&gt;Create some introductory Quest to explain "how to create your own Quests!".&lt;/li&gt;
&lt;li&gt;Create an character editor, to be able to "design" new characters for Quests.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;The Quest editor&lt;/h3&gt;
&lt;p&gt;The Quests will be written using the Ink language, and there's &lt;a href="https://flathub.org/apps/details/com.inklestudios.Inky"&gt;something done before&lt;/a&gt;.
The first idea is to just provide a text editor and some helpful information
about the format, and maybe a button to validate. But if there's time we can
use something advanced or even integrate the &lt;a href="https://flathub.org/apps/details/com.inklestudios.Inky"&gt;Inky&lt;/a&gt; editor.&lt;/p&gt;
&lt;h3&gt;The Character editor&lt;/h3&gt;
&lt;p&gt;Each Quest has a main character, and we've five in the Hack app right now, but
it could be great to be able to define new ones for custom Quests. That's the
idea of this part of the project.&lt;/p&gt;
&lt;p&gt;The initial idea is to have a library of character parts to combine, and the
editor will allow the user to combine this parts and maybe change colors, to be
able to create unique characters for your Quests.&lt;/p&gt;
&lt;h3&gt;The Team&lt;/h3&gt;
&lt;p&gt;I'm not working alone in this "side" project during the Endless Orange Week,
Simon Schampijer and Joana Filizola will be working on this too, so this is a
big task but we've a great team. Let's see how far we are able to go during
just one week.&lt;/p&gt;
&lt;h3&gt;The impact&lt;/h3&gt;
&lt;p&gt;This is just a project to try to keep alive more time the Hack application,
without a lot of effort or a whole team behind it. We are not able to put more
content there periodically, so if there's a way to create new content easily
and (maybe in the future) a way to publish, it'll be possible to create a
community around the project.&lt;/p&gt;
&lt;p&gt;And we have also new possibilities, in the near future, we can add some Hack
content to the Endless Key, and using the Ink language, so this editor could
help to bring more content there easily.&lt;/p&gt;
&lt;p&gt;And the final piece, the Character editor, could be an independent application,
a nice simple application that could be used to create your character for your
profile photo, or to generate random character pics.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 08 Nov 2021 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2021-11-08:/hack-content-creators.html</guid><category>blog</category><category>hack</category><category>endless</category><category>orangeweek</category><category>work</category><category>gnome</category><category>software</category></item><item><title>EndlessOS dual boot with Fedora</title><link>https://danigm.net/endlessos-dual-boot.html</link><description>&lt;p&gt;I've a &lt;em&gt;ThinkPad X1 Yoga&lt;/em&gt;, that's basically a &lt;em&gt;ThinkPad X1 Carbon 4th&lt;/em&gt; but
with a touch screen with a pencil that works like a wacom tablet.&lt;/p&gt;
&lt;p&gt;I've this laptop since 2016. The first thing that I did when I received it
was install a GNU/Linux operating system. I'm a GNU/Linux user since the
year 2000 going through a lot of distributions, Debian, Ubuntu, Archlinux, etc.&lt;/p&gt;
&lt;p&gt;When I received this computer I've a customized Archlinux there, and I wanted
to &lt;code&gt;dd&lt;/code&gt; my harddisk and boot, but I was unable to do that. I didn't know
nothing about UEFI and I was unable to boot the Archlinux installer.&lt;/p&gt;
&lt;p&gt;So I decided to go ahead and change my main distribution. I installed Fedora
and almost all the hardware worked so I keep that one and was happy, until
today :P&lt;/p&gt;
&lt;h2&gt;OStree, the new way of distribute GNU/Linux&lt;/h2&gt;
&lt;p&gt;With OStree and flatpak, there's a new way to distribute GNU/Linux, instead of
use directly a package manager and update each package, we can use OStree and
mount the root filesystem as read only and do full OS upgrades without broken
packages and dependencies and so. The operating system go as is and the user
should try hard to break it.&lt;/p&gt;
&lt;p&gt;The other great thing about OStree is that it's like a git repository, so you
can have different branches and a history, so you can easily go back and forward,
it's really easy to test the beta and go back without breaking your system.&lt;/p&gt;
&lt;p&gt;The main problem is that you &lt;em&gt;can't&lt;/em&gt; install anything on your OS, you should
use contained apps like flatpak or install by hand, you can't use &lt;code&gt;apt-get&lt;/code&gt;.
But that's okay for a day to day user, a power user always can &lt;code&gt;unlock&lt;/code&gt; the OS
and use it as a normal GNU/Linux distribution.&lt;/p&gt;
&lt;p&gt;I wanted to try one of these distributions. The logical choice was &lt;a href="https://silverblue.fedoraproject.org/"&gt;Silverblue&lt;/a&gt;
because it's a Fedora and I'm using it for three years now, but there's another
option, &lt;a href="https://endlessos.com/"&gt;EndlessOS&lt;/a&gt; is also OStree based, and &lt;a href="http://danigm.net/endless.html"&gt;I'm working with this OS&lt;/a&gt;,
so I should give a try and use EndlessOS.&lt;/p&gt;
&lt;h2&gt;The EndlessOS install process&lt;/h2&gt;
&lt;p&gt;Like all the new modern GNU/Linux distros, EOS comes with a easy to use installer,
you only need to boot from the USB and click next until it's done...&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/eos/endless-install-2.jpg"&gt;
        &lt;img src="/pictures/eos/endless-install-2.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;But here we've the first problem. I've more than one partition in my disk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;/dev/sda1: UEFI&lt;/li&gt;
&lt;li&gt;/dev/sda3: Fedora /&lt;/li&gt;
&lt;li&gt;/dev/sda8: Swap&lt;/li&gt;
&lt;li&gt;/dev/sda4: Fedora /boot&lt;/li&gt;
&lt;li&gt;/dev/sda6: /home&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I want to keep my Fedora (who knows if something bad happens) and try to use the
same home partition for my new EOS. But the installer only give me the option
to erase all and have a clean system. But that won't stop me.&lt;/p&gt;
&lt;p&gt;Let's go back and instead of reformat I will click on &lt;em&gt;Try Endless OS&lt;/em&gt;:&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/eos/EndlessOS-Installation.png"&gt;
        &lt;img src="/pictures/eos/EndlessOS-Installation.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;What we need to do, Robert McQueen gave me some directions:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The constraints for booting Endless are 1) you use our grub, and 2) the root
partition is labelled "ostree"&lt;/p&gt;
&lt;p&gt;So if you have an EFI system, you can copy our EFI binaries into the ESP, and
create a new partition for Endless, then dd the endless ostree filesystem into
it&lt;/p&gt;
&lt;p&gt;Then you should be able to boot, if you add a boot entry for the endless grub
to your firmware, or make it the default (by providing the fallback boot64.efi
or whatever it's called), or chain load it from another Linux loader&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Install EOS with other linux (EFI system)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Boot from USB, select try&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Launch the gnome-disk-utility and prepare a partition. I've not free space,
but I was able resize my Fedora partition and I split in two of the same size,
now I've a new ext4 partition &lt;code&gt;/dev/sda7&lt;/code&gt; with 25GB.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the endless ostree:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;su
&lt;span class="c1"&gt;# dd if=/dev/mapper/endless/image3 /dev/sda7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Copy endless grub to EFI. I mounted all partitions in /tmp, the first
partition in &lt;code&gt;/tmp/sda1&lt;/code&gt; and the EOS efi in the &lt;code&gt;/tmp/EOS&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# mkdir /tmp/sda1 /tmp/EOS
# mount /dev/sda1 /tmp/sda1
# mount /dev/mapper/endless-image1 /tmp/EOS
# cp -rf /tmp/EOS/EFI/endless/ /tmp/sda1/EFI
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Add the new boot entry:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# efibootmgr -c -d /dev/sda -p 1 -L EOS -l \\EFI\\endless\\grubx64.efi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Set as default boot:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# cp /tmp/EOS/EFI/endless/grubx64.efi /tmp/sda1/EFI/Boot/bootx64.efi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Reboot and create my default user. Then I add my home partition to the &lt;code&gt;/etc/fstab&lt;/code&gt;
file:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;UUID=c885e171-1a03-4afb-8519-f9fe26fe92b7 /sysroot/home ext4 defaults 1 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And because the first user in EOS is the shared account, with UID 1000, I've to
change the UID of my user editing the file in &lt;code&gt;/etc/passwd&lt;/code&gt;. Then I rebooted
again and all works. I've all my flatpak apps installed in the user space working.&lt;/p&gt;
&lt;p&gt;So here we're, with a shiny new OS working like a charm:&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/eos/screenshot.png"&gt;
        &lt;img src="/pictures/eos/screenshot.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;The EFI and efibootmgr (who needs grub to select the OS?)&lt;/h2&gt;
&lt;p&gt;I didn't know much about UEFI and I was very impressed about how easy is to
update this from GNU/Linux. There's a tool called &lt;code&gt;efibootmgr&lt;/code&gt; that does all
the work, and you can mount the partition, that's a FAT32, and put files there.&lt;/p&gt;
&lt;p&gt;In my ThinkPad, I can boot directly to the UEFI boot menu pressing F12 during
the boot, and that menu can be changed using the &lt;code&gt;efibootmgr&lt;/code&gt; so it's not
needed anymore to use the grub2 OS selection interface, I can use the UEFI
menu for that!&lt;/p&gt;
&lt;p&gt;This has some disadvantages, if you remove files from the UEFI partition, you
can break the whole boot, so review all before any change.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 25 May 2019 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2019-05-25:/endlessos-dual-boot.html</guid><category>blog</category><category>gnome</category><category>work</category><category>endless</category><category>fedora</category></item><item><title>I'm a hacker</title><link>https://danigm.net/endless.html</link><description>&lt;h2&gt;I've the strength of the one that fails, trains and returns&lt;/h2&gt;
&lt;p&gt;Some time ago I wrote &lt;a href="http://danigm.net/gnome-gtk-developer.html"&gt;about my interview process&lt;/a&gt; trying to get a job at
GNOME. After this blog post was published in the GNOME planet, I received a lot
of comments from the &lt;em&gt;Great&lt;/em&gt; GNOME community.&lt;/p&gt;
&lt;p&gt;This guided me to take a look to the companies that was looking for GNOME
developers and after some interviews I finally get an offer to work on
&lt;a href="https://endlessos.com/"&gt;Endless&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All the process was online, I've been working from home since 2011 and I want
to continue like this. I'm living in Málaga, the south of Spain and I was
looking for a remote job.&lt;/p&gt;
&lt;p&gt;I've a very nice interview process, talking with developers that I knew about
from their contributions to free software and these interviews weren't
technical, that's a good thing about the free software contribution and
the community, if someone wants to know my technical skills, he only need to
look to my gitlab or github and he will find a lot of code. These interviews
were personal and with some management questions, to know if I'll fit in the
team and the company.&lt;/p&gt;
&lt;p&gt;I did the interview to work directly on the Endless OS, in the desktop team,
but after some interviews I ended in other team, working with the Endless OS
and all GNOME technology, but in the &lt;a href="https://hack-computer.com/"&gt;Hack Computer&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The hack computer&lt;/h2&gt;
&lt;p&gt;The hack computer is an educational project. The main idea is to provide a
fully functional computer for kids to be their first personal computer and also
provide a way to teach kids to &lt;em&gt;hack&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The computer is a usual laptop, with an Endless OS running, and with some extra
applications that try to guide kids to explore, modify and finally hack the
computer learning in the process about GNU/Linux, the code and that any part
of your software can be hacked to make it better, an introduction to the
free software and the great world of open source code that you can modify to
learn, play or simply because you can.&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/SN7tC4XnGko" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;The way to guide kids to learn is like a video game, with characters that will
appears in your desktop and will guide you with tips and challenges and after
each quest completed the kid will learn something, playing with his computer.&lt;/p&gt;
&lt;p&gt;If you like this and want to collaborate, &lt;a href="https://jobs.lever.co/endless"&gt;we're hiring&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Endless OS&lt;/h2&gt;
&lt;p&gt;The hack computer is built on top of the Endless OS. Endless OS is based on
debian and the desktop is a modified gnome shell, but it's not the usual debian
derivative, it's based on &lt;a href="https://ostree.readthedocs.io/en/latest/"&gt;OSTree&lt;/a&gt;. The main difference is that the root
filesystem is read only and updates are managed with ostree, that's like a git
repository.&lt;/p&gt;
&lt;p&gt;This kind of Operating System is easier to maintain, because the user &lt;em&gt;can't&lt;/em&gt;
modify the base system, so this means that he was unable to &lt;em&gt;break it&lt;/em&gt;. All user
applications are installed via flatpak, so are &lt;em&gt;independent&lt;/em&gt; of the &lt;em&gt;OS&lt;/em&gt;
version and because of flathub you can install latests version of apps without
the need to update the full operating system.&lt;/p&gt;
&lt;p&gt;This is the way that &lt;a href="https://silverblue.fedoraproject.org/"&gt;Fedora SilverBlue&lt;/a&gt; is trying to follow and is a &lt;em&gt;new&lt;/em&gt;
way to build and distribute GNU/Linux.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/hack-mount-tree.png"&gt;
        &lt;img src="/pictures/hack-mount-tree.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;The end of an Era&lt;/h2&gt;
&lt;p&gt;I've been working in &lt;a href="https://wadobo.com"&gt;Wadobo&lt;/a&gt; since 2011. I created that company with two
college friends to try to continue hacking like we were hacking in the Seville
LUG &lt;a href="https://sugus.eii.us.es/"&gt;SUGUS&lt;/a&gt; and earn money from that, and we did it for a long time.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/wadobo-old-2.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;We've been working in free software projects and with free software technology,
contributing to the community as much as we can and always trying to free our
work.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/wadobo-old-1.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;We created some projects that grow up and follow its own path, like the
agora voting system, that Edulix (Eduardo Robles) converts in &lt;a href="https://nvotes.com/"&gt;nvotes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The self employment was a really good experience. I've been doing was I want
for a long time, taking time to contribute to GNOME and other projects when
I need it, because I was the one deciding what I want to do. But in the other
hand, I've been stuck in the local consultancy market for a long time.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/wadobo-old-3.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;I'm not a business man, I'm a developer and I'm based in Spain, where there
is no money inverted in innovation or we was unable to find that money, so we
were doing django web apps for a living and spending some time in our interests
in the extra time we've. So when I found the possibility to work full time in
an innovative project, I've no choice.&lt;/p&gt;
&lt;p&gt;We'll try to continue with the &lt;strong&gt;Wadobo&lt;/strong&gt; idea, like a group of people
interested in free software and new technologies, maybe this will derive into
a Linux User Group or maybe in the future someone takes the initiative and
build a business around this again.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/wadobo-old-4.jpg" /&gt;
&lt;/p&gt;

&lt;h2&gt;Hacking&lt;/h2&gt;
&lt;p&gt;I'm really happy with this change. Endless OS and the hack computer are really
great projects with a lot of bleeding edge technology and a really great group
of people, and I'm really exited to be able to work with people all around the
world in a project with a global vision.&lt;/p&gt;
&lt;p&gt;I don't want to leave the roots I've here with my Wadobo friends and the local
community and local technology ecosystem. This is also related with the Endless
vision. Spain, and here in the south, in Andalucía, we've a technological
breach that we try to fill with free software.&lt;/p&gt;
&lt;p&gt;I'll continue working with the Seville University, because they give me a lot
and I think it's a talent pool, we only need to guide those students to the
GNOME community or to other free software communities out there, to &lt;em&gt;save&lt;/em&gt;
their souls from the privative software and the dark side.&lt;/p&gt;
&lt;p&gt;I'll continue supporting initiatives like the &lt;a href="http://concursosoftwarelibre.org/"&gt;Free Software Contest&lt;/a&gt;&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;a href="http://concursosoftwarelibre.org/"&gt;
    &lt;img src="http://concursosoftwarelibre.org/1819/files/images/banners/cusl2_500x455.png" /&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;By the way, I'll be talking about rust in the Seville University the next
Tuesday 5th of March 2019, if you're in Seville, come to talk with me :D&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 17 Feb 2019 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2019-02-17:/endless.html</guid><category>blog</category><category>gnome</category><category>work</category><category>endless</category><category>hack</category></item><item><title>GNOME Gtk Developer</title><link>https://danigm.net/gnome-gtk-developer.html</link><description>&lt;h2&gt;I tried and I failed.&lt;/h2&gt;
&lt;p&gt;This summer, during the GUADEC 2018, the GNOME foundation announces some job
positions. One of that job was for a &lt;a href="https://www.gnome.org/foundation/careers/gtk-core-developer/"&gt;Gtk+ core developer&lt;/a&gt;. I tried to get
that job and after a long period I was rejected.&lt;/p&gt;
&lt;p&gt;The final developer selected for this possition is &lt;a href="https://mail.gnome.org/archives/foundation-list/2018-December/msg00000.html"&gt;Emmanuel Bassi&lt;/a&gt;, a very
active developer in the core of GNOME and the one that's behind the great
&lt;a href="https://www.bassi.io/articles/2018/10/25/the-history-of-gnome/"&gt;The History of GNOME Podcast&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To be honest, I really wanted that job. It's a dream job for me, working
fulltime in a free software project, by a foundation, with the great GNOME
technology and community.&lt;/p&gt;
&lt;p&gt;But I've to say that just when I saw the foundation announcement about this
position I thought about ebassi, because as far as I know, he's the best one to
do that job. In any case, I wanted to give a try and go for that job, I didn't
know about other people going for it, so maybe I can do it.&lt;/p&gt;
&lt;h2&gt;Some background&lt;/h2&gt;
&lt;p&gt;I'm working in my &lt;a href="https://wadobo.com"&gt;own little company&lt;/a&gt; since 2010. We're three coworkers
with the same percentage of the company, like a cooperative and we work mainly
as external consultant for bigger companies. We do a lot of work related with
GNU/Linux and free software, but lately we mainly do web apps with python
and react, because that's what our current clients ask for.&lt;/p&gt;
&lt;p&gt;But the first paid project for wadobo was a GNOME project, I started the
company with a small project to improve accessibility in PDF documents, working
directly in evince. And then we worked with Qt, QML and other technologies, but
I wasn't able to get a paid work on GNOME or Gtk+ since that initial work.&lt;/p&gt;
&lt;p&gt;In any case, I continued working in GNOME in my spare time, trying to
contribute, first with &lt;a href="https://gitlab.gnome.org/gnome/libgepub"&gt;libgepub&lt;/a&gt;, trying to bring epub support to evince,
and then to GNOME Books. And the last year I became more active because of
&lt;a href="https://gitlab.gnome.org/World/fractal"&gt;Fractal&lt;/a&gt; and &lt;a href="https://gitlab.gnome.org/gnome/gtranslator"&gt;Gnome Translation Editor (gtranslator)&lt;/a&gt;. And I've been
mentor for the GSoC 2018 and now I've two interns in the Outreachy program.&lt;/p&gt;
&lt;p&gt;I've some time to spend in GNOME, but I'm not making money from that, so now
I'm starting to look for that actively, because I really want to have more time
to spend working with free software.&lt;/p&gt;
&lt;p&gt;So, I talked with my coworkers, to be honest with them, and I told them that
I was going to try to get the Gtk+ core developer position.&lt;/p&gt;
&lt;h2&gt;The process&lt;/h2&gt;
&lt;p&gt;This was a long process, I think that it was long because there was a lot of
people for that position.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Email&lt;/strong&gt;: I sent the initial email in mid July, with a long description
   about me and my work in gnome and free software, with a little hope in my
   heart.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Survey&lt;/strong&gt;: Then I received an email with a link to a survey to complete with
   more information. That was great, because it sounds like I've passed the
   first cut.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Interview&lt;/strong&gt;: At the end of August I received a conglatulations email. My
   resume was positively reviewed and I'll have a personal interview.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That was really nice and I started to think that maybe it was possible after
   all.&lt;/p&gt;
&lt;p&gt;At the mid of September, I've a video conference meeting with Carlos Soriano
   and Matthias Clasen. For me was a great interview, talking about my experience,
   GNOME and Gtk+. Maybe the interview was a disaster and they are just a very
   nice people being nice with a poor developer, but at the end I thought that it
   was well and I was very exited about this.&lt;/p&gt;
&lt;h3&gt;The failure&lt;/h3&gt;
&lt;p&gt;After a long time without knowing anything, I received the email that I was
waiting for. I wasn't selected for the position. The next week, the foundation
announces the new staff member and in that moment I noticed that I've had no
chance to get the job. He's the better candidate and I'm really happy because
this is really good for GNOME.&lt;/p&gt;
&lt;h2&gt;And now what?&lt;/h2&gt;
&lt;p&gt;At the end of the process, I think that this was a great experience for me,
because this forces me to think about my career, what I want to do in the
future and I went through a full selection process, something that I've not done
since 2009.&lt;/p&gt;
&lt;p&gt;I will continue trying to find the way to work in GNOME or something realated
with the GNU/Linux desktop or core technologies.&lt;/p&gt;
&lt;p&gt;I did a lot of web development, I've a lot of experience and I'm really good doing
web with django, but I really want to go back and work with other technologies,
programming in C, the new Rust language and with some low level technologies.&lt;/p&gt;
&lt;p&gt;If someone need help, I'm here and I can work as a contractor. For now I'll
continue working in Wadobo, trying to find clients that requires desktop or
low level work.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 05 Dec 2018 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2018-12-05:/gnome-gtk-developer.html</guid><category>blog</category><category>gnome</category><category>gtk+</category><category>work</category><category>wadobo</category></item></channel></rss>