<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<title>Nskm</title>
	<subtitle>Never stray from the way.</subtitle>
	<link href="https://nskm.xyz/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="https://nskm.xyz"/>
	<generator uri="https://www.getzola.org/">Zola</generator>
	<updated>2024-01-20T00:00:00+00:00</updated>
	<id>https://nskm.xyz/atom.xml</id>
	<entry xml:lang="en">
		<title>C Pointers (WIP)</title>
		<published>2024-01-20T00:00:00+00:00</published>
		<updated>2024-01-20T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/ptrs/" type="text/html"/>
		<id>https://nskm.xyz/posts/ptrs/</id>
		<content type="html">&lt;p&gt;In my &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;&quot;&gt;last&lt;&#x2F;a&gt; post, I&#x27;ve written about lots of things but not about C pointers. I tought the topic deserves a post in itself because it&#x27;s one of the most important feature of the C language.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with some &lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=24ntpKNiUMs&quot;&gt;music&lt;&#x2F;a&gt; please.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 550px&quot; src=&quot;&#x2F;assets&#x2F;pointers.png&quot; alt=&quot;C Pointers&quot; title=&quot;C Pointers&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#i&quot;&gt;Introduction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#d&quot;&gt;Declaration &amp;amp; initialization&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#o&quot;&gt;Operators&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#u&quot;&gt;Use cases&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#a&quot;&gt;Arrays &amp;amp; strings manipulation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#p&quot;&gt;Pass by reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#m&quot;&gt;Memory allocation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#s&quot;&gt;Data structure implementation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#f&quot;&gt;Functions pointers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#h&quot;&gt;Hardware interface&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#g&quot;&gt;Going further&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;i&quot;&gt;Introduction:&lt;&#x2F;h2&gt;
&lt;p&gt;A pointer is a variable that contains the memory address of another variable. A pointer allows
us to &lt;em&gt;indirectly&lt;&#x2F;em&gt; access and manipulate the value of the variable that is pointed to. Like other variables, C pointers have a type.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img
    style=&quot;display: block; margin: 0 auto; width: 600px&quot;
    src=&quot;&#x2F;assets&#x2F;pointers_repr.png&quot;
    alt=&quot;Pointers&quot;
    title=&quot;Pointers&quot;&#x2F;&gt;&lt;&#x2F;p&gt;
&lt;center&gt;
    &lt;a href=&quot;https:&#x2F;&#x2F;codeforwin.org&quot;&gt;Source&lt;&#x2F;a&gt;
  &lt;&#x2F;center&gt;
&lt;h2 id=&quot;d&quot;&gt;Declaration and initialization:&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main () {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; foo = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; bar = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;83&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int *&lt;&#x2F;span&gt;&lt;span&gt;ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;foo;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Pointer variable of type int*
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int **&lt;&#x2F;span&gt;&lt;span&gt;ptrptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;ptr; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; pointer to a pointer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of foo: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, foo);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptr is: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, and ptr is pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptrptr is: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; &amp;amp; ptrptr is pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptrptr, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of foo after modification via ptr: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, foo);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;ptrptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of foo after modification via ptr to ptr: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, foo);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bar;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptr is now: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, and ptr is now pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptrptr, still: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; &amp;amp; ptrptr is now pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptrptr, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the output of the previous program is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;Value of foo: 42
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptr is: 0x7ffc6155fd60, and ptr is pointing to: 42
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptrptr is: 0x7ffc6155fd68 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;ptrptr is pointing to: 0x7ffc6155fd60
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Value of foo after modification via ptr: 12
&lt;&#x2F;span&gt;&lt;span&gt;Value of foo after modification via ptr to ptr: 13
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptr is now: 0x7ffc6155fd64, and ptr is now pointing to: 83
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptrptr, still: 0x7ffc6155fd68 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;ptrptr is now pointing to: 0x7ffc6155fd64
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;o&quot;&gt;C pointer operators:&lt;&#x2F;h2&gt;
&lt;p&gt;C offers operators for pointer manipulation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Address-of operator (&amp;amp;): to return the memory address of a variable&lt;&#x2F;li&gt;
&lt;li&gt;Dereference operator (*): to access the value stored at the memory address pointed to&lt;&#x2F;li&gt;
&lt;li&gt;Arithmetic operators: to perform arithmetic operations on C pointers, addition (+), subtraction (-), increment (++), and decrement (--)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;u&quot;&gt;Use cases for C pointers:&lt;&#x2F;h2&gt;
&lt;p&gt;All modern programming languages have pointers in some form or other. Pointers are used everywhere there is a program, even when we don&#x27;t see them. Let&#x27;s explore some of those use cases.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a&quot;&gt;Manipulating array and string elements:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers can be used to access and manipulate elements in arrays and strings. C Pointers provide a way to efficiently iterate over arrays and perform operations on each item of the sequence.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; arr[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int *&lt;&#x2F;span&gt;&lt;span&gt;aptr = arr;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print items of the sequence using array indices
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, arr[i]);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print elements of the array using pointer
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;aptr);
&lt;&#x2F;span&gt;&lt;span&gt;  aptr++;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print items of the sequence using pointer arithmetic
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and the fact that arr is actually a pointer to the first item of the arr
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;arr+i);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; an array of characters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; str[] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello world from West Africa&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;sptr = str; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a pointer to the first element of the array
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt;(i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;28&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; while i is less than 28, print the character at i-th index 
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, str[i]);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; increment i to go to the next index
&lt;&#x2F;span&gt;&lt;span&gt;  i++;
&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; while the value that is pointed to is different from the &amp;quot;\0&amp;quot; character
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;sptr != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print the char
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;sptr);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; increment pointer (to go to the next character)
&lt;&#x2F;span&gt;&lt;span&gt;  sptr = sptr + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; m = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt;(m &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;28&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; str is actually a pointer to the first item of the object
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; so str+m is the address of the m-ieth item of the object
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;(str+m));
&lt;&#x2F;span&gt;&lt;span&gt;  m++;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; array of pointers to characters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;names[] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Alice&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bob&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Charlie&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;David&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Emma&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Pointer to the first element of the first element of the array of strings
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char **&lt;&#x2F;span&gt;&lt;span&gt;ptr_names = names; 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; j = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; j &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; j++) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Print elements of the array of strings using indices
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, names[j]);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; x &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; x++) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Print the element currently pointed to
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr_names);
&lt;&#x2F;span&gt;&lt;span&gt;  ptr_names = ptr_names + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;p&quot;&gt;Passing arguments by reference:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers can be used to pass arguments by reference to functions, allowing the function to modify the value of the original variable. This is particularly useful in the following situations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;working with large data structures &lt;&#x2F;li&gt;
&lt;li&gt;you need to modify the value of a variable in a function&lt;&#x2F;li&gt;
&lt;li&gt;you need to optimize code by reducing the number of copies of data that need to be made&lt;&#x2F;li&gt;
&lt;li&gt;you need to return more than one value&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Examples:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;m&quot;&gt;Allocating memory:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers are also used to allocate memory dynamically at run-time using functions like &lt;a href=&quot;#&quot;&gt;malloc()&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;calloc()&lt;&#x2F;a&gt;, and &lt;a href=&quot;#&quot;&gt;realloc()&lt;&#x2F;a&gt;. Examples:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;s&quot;&gt;Implementing data structures:&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;#&quot;&gt;Linked lists&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Stacks&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Queues&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Trees&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Graphs&lt;&#x2F;a&gt; and many other data structures are implemented using C Pointers. Examples:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;f&quot;&gt;Calling functions:&lt;&#x2F;h3&gt;
&lt;p&gt;A function pointer, is a pointer which point to the memory address of a function instead of pointing to the address of a data object. They are used to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;store functions in data structures&lt;&#x2F;li&gt;
&lt;li&gt;pass functions as arguments to other functions&lt;&#x2F;li&gt;
&lt;li&gt;call functions dynamically at runtime&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here are three examples of using function pointers in C:&lt;&#x2F;p&gt;
&lt;!-- 1. Passing a function as an argument to another function: --&gt;
&lt;!-- ```c --&gt;
&lt;!-- #include &lt;stdio.h&gt; --&gt;
&lt;!-- void myFunction(int x) { --&gt;
&lt;!--     printf(&quot;Value is: %d\n&quot;, x); --&gt;
&lt;!-- } --&gt;
&lt;!-- void callFunction(void (*fn)(int), int value) { --&gt;
&lt;!--     fn(value); --&gt;
&lt;!-- } --&gt;
&lt;!-- int main() { --&gt;
&lt;!--     callFunction(myFunction, 10); --&gt;
&lt;!--     return 0; --&gt;
&lt;!-- } --&gt;
&lt;!-- ``` --&gt;
&lt;!-- 2. Storing functions in an array: --&gt;
&lt;!-- ```c --&gt;
&lt;!-- #include &lt;stdio.h&gt; --&gt;
&lt;!-- void func1() { --&gt;
&lt;!--     printf(&quot;Function 1\n&quot;); --&gt;
&lt;!-- } --&gt;
&lt;!-- void func2() { --&gt;
&lt;!--     printf(&quot;Function 2\n&quot;); --&gt;
&lt;!-- } --&gt;
&lt;!-- int main() { --&gt;
&lt;!--     void (*funcArray[2])() = {func1, func2}; --&gt;
&lt;!--     funcArray[0](); --&gt;
&lt;!--     funcArray[1](); --&gt;
&lt;!--     return 0; --&gt;
&lt;!-- } --&gt;
&lt;!-- ``` --&gt;
&lt;!-- 3. Using function pointers to implement a simple callback mechanism: --&gt;
&lt;!-- ```c --&gt;
&lt;!-- #include &lt;stdio.h&gt; --&gt;
&lt;!-- void callback1() { --&gt;
&lt;!--     printf(&quot;Callback 1\n&quot;); --&gt;
&lt;!-- } --&gt;
&lt;!-- void callback2() { --&gt;
&lt;!--     printf(&quot;Callback 2\n&quot;); --&gt;
&lt;!-- } --&gt;
&lt;!-- void performTask(void (*callback)()) { --&gt;
&lt;!--     printf(&quot;Performing task...\n&quot;); --&gt;
&lt;!--     callback(); --&gt;
&lt;!-- } --&gt;
&lt;!-- int main() { --&gt;
&lt;!--     performTask(callback1); --&gt;
&lt;!--     performTask(callback2); --&gt;
&lt;!--     return 0; --&gt;
&lt;!-- } --&gt;
&lt;!-- ``` --&gt;
&lt;!-- These examples demonstrate the flexibility and power of function pointers in C programming. They allow for dynamic and flexible function invocation, making the code more modular and easier to maintain. --&gt;
&lt;h3 id=&quot;h&quot;&gt;Interfacing with hardware:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers are often used in low-level programming to interact with hardware devices and memory-mapped registers. They provide a way to access specific memory addresses and manipulate hardware directly.&lt;&#x2F;p&gt;
&lt;!-- - Study the syntax for declaring and initializing pointers. --&gt;
&lt;!-- - Learn the difference between the pointer type and the pointed-to type. --&gt;
&lt;!-- - Understand the significance of the &#x27;*&#x27; symbol in pointer declarations. --&gt;
&lt;!-- 3. Pointer Arithmetic: --&gt;
&lt;!--    - Explore how pointer arithmetic works in C. --&gt;
&lt;!--    - Learn how to perform arithmetic operations like addition, subtraction, and comparison on pointers. --&gt;
&lt;h2 id=&quot;g&quot;&gt;Going further:&lt;&#x2F;h2&gt;
&lt;p&gt;To learn more about C pointers, we recommend the following &lt;strong&gt;pointers&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;i.imgur.com&#x2F;SIN2jJm.png&quot;&gt;0x7ffc6155fd68&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pointer_(dog_breed)&quot;&gt;0x7ffc6155fd69&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pointer_(computer_programming)&quot;&gt;0x7ffc6155fd70&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;playlist?list=PLdo5W4Nhv31a8UcMN9-35ghv8qyFWD9_S&quot;&gt;0x7ffc6155fd71&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 550px&quot; src=&quot;&#x2F;assets&#x2F;ptrs.jpg&quot; alt=&quot;Pointers&quot; title=&quot;Pointers&quot;&#x2F;&gt;
&lt;!-- [Pointer](https:&#x2F;&#x2F;tsusports.com&#x2F;sports&#x2F;mens-basketball&#x2F;roster&#x2F;coaches&#x2F;pointer-williams&#x2F;21) --&gt;
&lt;!-- https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;ProgrammerHumor&#x2F;comments&#x2F;9rcri0&#x2F;i_would_make_a_joke_about_pointers&#x2F; --&gt;
&lt;!-- https:&#x2F;&#x2F;www.quora.com&#x2F;What-is-a-pointer-joke --&gt;
&lt;!-- https:&#x2F;&#x2F;www.kernel.org&#x2F;doc&#x2F;Documentation&#x2F;process&#x2F;coding-style.rst --&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>C</title>
		<published>2023-09-25T00:00:00+00:00</published>
		<updated>2023-09-25T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/cp/" type="text/html"/>
		<id>https://nskm.xyz/posts/cp/</id>
		<content type="html">&lt;p&gt;I spent some time adding &lt;a href=&quot;https:&#x2F;&#x2F;www.logilab.fr&#x2F;blogentry&#x2F;13884378&quot;&gt;type annotations&lt;&#x2F;a&gt; to some Python code. Shoutout to all the people at &lt;a href=&quot;https:&#x2F;&#x2F;logilab.fr&quot;&gt;Logilab&lt;&#x2F;a&gt;, a really awesome team doing really awesome things. All those type annotations made me more and more interested in static typing... and in C programming.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Target audience&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;: people who already have an experience with programming. People who may have written some C programs in the past and who want to refresh their memory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Context&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;: I&#x27;m working on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I&#x27;m working on &lt;code&gt;Linux 5.13.0-52-generic #59-Ubuntu SMP Wed Jun 15 20:17:13 UTC 2022 x86_64&lt;&#x2F;code&gt; &lt;&#x2F;li&gt;
&lt;li&gt;And I&#x27;m using &lt;code&gt;GCC (Ubuntu 11.2.0-7ubuntu2) 11.2.0&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=6YSNKq-6SjM&quot;&gt;Music please&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;assets&#x2F;force.jpg&quot; alt=&quot;Force&quot; title=&quot;Force&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#setup&quot;&gt;Setup&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#primitive&quot;&gt;Primitive types&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#integers&quot;&gt;integers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#floats&quot;&gt;floats&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#bool&quot;&gt;booleans&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#void&quot;&gt;void&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#composite&quot;&gt;Composite types&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#structs&quot;&gt;structs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#enums&quot;&gt;enums&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#unions&quot;&gt;unions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#arrays&quot;&gt;arrays&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#strings&quot;&gt;strings&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#constants&quot;&gt;Constants&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setup&quot;&gt;The setup:&lt;&#x2F;h2&gt;
&lt;p&gt;To write C programs, we need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;a href=&quot;#&quot;&gt;operating system&lt;&#x2F;a&gt; that respect your freedom and privacy.&lt;&#x2F;li&gt;
&lt;li&gt;A C compiler such as &lt;a href=&quot;https:&#x2F;&#x2F;gcc.gnu.org&#x2F;&quot;&gt;gcc&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;clang.llvm.org&#x2F;&quot;&gt;clang&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;&quot;&gt;text editor&lt;&#x2F;a&gt; that &lt;a href=&quot;&#x2F;images&#x2F;trollface.jpg&#x2F;&quot;&gt;&lt;em&gt;respects&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; your freedom and privacy.&lt;&#x2F;li&gt;
&lt;li&gt;(Optional) a Bash script to generate the project &lt;a href=&quot;&#x2F;snips&#x2F;scfldc&#x2F;&quot;&gt;boilerplate&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;(Optional) a &lt;a href=&quot;&#x2F;snips&#x2F;scfldc&#x2F;&quot;&gt;Makefile&lt;&#x2F;a&gt; to format, build, install and run the program quickly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h2 id=&quot;types&quot;&gt;Types:&lt;&#x2F;h2&gt;
&lt;p&gt;Variable, a named location in the computer&#x27;s memory where data can be stored and accessed. Type, define the size, the format, the behavior, the operations that can be performed on the variable. Let&#x27;s talk about the common types in C programming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;primitive&quot;&gt;Primitive types:&lt;&#x2F;h2&gt;
&lt;p&gt;Primitive data types, or &amp;quot;basic data types&amp;quot; or &amp;quot;fundamental data types&amp;quot; are the most basic data types that can be used for representing simple values such as numbers, characters, etc... The primitive data types are...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;integers&quot;&gt;Integer types&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;char: represents a single character (usually 1 byte)&lt;&#x2F;li&gt;
&lt;li&gt;short: represents a small integer&lt;&#x2F;li&gt;
&lt;li&gt;int: represents an integer&lt;&#x2F;li&gt;
&lt;li&gt;long: represents a long integer&lt;&#x2F;li&gt;
&lt;li&gt;long long: represents a very long integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned short: represent a small positive integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned int: represents a positive integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned long: represents a long positive integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned long long: represents a very long positive integer&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This list is not exhaustive, there is also what we call &lt;strong&gt;fixed width integer types&lt;&#x2F;strong&gt; and what we call &lt;strong&gt;minimum width integer types&lt;&#x2F;strong&gt;. We won&#x27;t talk about them here, please browse this &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;stdint.h.html&quot;&gt;link&lt;&#x2F;a&gt; for reference.&lt;&#x2F;p&gt;
&lt;p&gt;To find the range of a particular type, we can look for the &lt;code&gt;limits.h&lt;&#x2F;code&gt; file  &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;limits.h.html&quot;&gt;online&lt;&#x2F;a&gt;. Or, we can also look for the same file inside our computer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt; find &#x2F;usr -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;limits.h&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-51&#x2F;include&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-51&#x2F;include&#x2F;uapi&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-51&#x2F;include&#x2F;vdso&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-52&#x2F;include&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-52&#x2F;include&#x2F;uapi&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-52&#x2F;include&#x2F;vdso&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;c++&#x2F;11&#x2F;tr1&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;gcc&#x2F;x86_64-linux-gnu&#x2F;11&#x2F;include&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;perl5&#x2F;5.32&#x2F;Tk&#x2F;pTk&#x2F;compat&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;llvm-13&#x2F;lib&#x2F;clang&#x2F;13.0.0&#x2F;include&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we open, let&#x27;s say, the file &lt;code&gt;&#x2F;usr&#x2F;include&#x2F;limits.h&lt;&#x2F;code&gt;, we can see interesting informations like :&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define CHAR_MAX     UCHAR_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  else
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define CHAR_MIN     SCHAR_MIN
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define CHAR_MAX     SCHAR_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  endif
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Minimum and maximum values a `signed short int&amp;#39; can hold.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define SHRT_MIN      (&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;32768&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define SHRT_MAX      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;32767
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Maximum value an `unsigned short int&amp;#39; can hold.  (Minimum is 0.)  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define USHRT_MAX     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65535
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Minimum and maximum values a `signed int&amp;#39; can hold.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define INT_MIN       (&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;INT_MAX &lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define INT_MAX       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2147483647
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Maximum value an `unsigned int&amp;#39; can hold.  (Minimum is 0.)  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define UINT_MAX      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4294967295&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;U
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Minimum and maximum values a `signed long int&amp;#39; can hold.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  if __WORDSIZE == 64
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define LONG_MAX     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;9223372036854775807&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;L
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  else
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define LONG_MAX     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2147483647&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;L
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;floats&quot;&gt;Floating-point types:&lt;&#x2F;h3&gt;
&lt;p&gt;Used to represent real numbers with decimal points. More informations &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;float.h.html&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;float: represents a single-precision floating-point number&lt;&#x2F;li&gt;
&lt;li&gt;double: represents a double-precision floating-point number&lt;&#x2F;li&gt;
&lt;li&gt;long double: represents an extended-precision floating-point number&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here is an example showing how to use float values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; input[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; radius, area;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter the radius of the circle: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; input, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    radius = strtof(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    area = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius;
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Area of the circle: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, area);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;!-- Here are some examples of using floating-point types in C: --&gt;
&lt;!-- 1. `float` type: --&gt;
&lt;!-- ```c --&gt;
&lt;!-- #include &lt;stdio.h&gt; --&gt;
&lt;!-- int main(){ --&gt;
&lt;!--   float num1 = 3.14f;  &#x2F;&#x2F; Declaration and initialization of a float variable --&gt;
&lt;!--   float num2 = 2.5e-3; &#x2F;&#x2F; Scientific notation: 2.5 * 10^(-3) --&gt;
&lt;!--   printf(&quot;%f\n&quot;, num1);  &#x2F;&#x2F; Output: 3.140000 --&gt;
&lt;!--   printf(&quot;%.2f\n&quot;, num2);  &#x2F;&#x2F; Output: 0.00 --&gt;
&lt;!--   double num3 = 123.456;  &#x2F;&#x2F; Declaration and initialization of a double variable --&gt;
&lt;!--   double num4 = 1e10;     &#x2F;&#x2F; Scientific notation: 1 * 10^10 --&gt;
&lt;!--   printf(&quot;%lf\n&quot;, num3);  &#x2F;&#x2F; Output: 123.456000 --&gt;
&lt;!--   printf(&quot;%e\n&quot;, num4);   &#x2F;&#x2F; Output: 1.000000e+10 --&gt;
&lt;!--   long double num5 = 1.23e-15;  &#x2F;&#x2F; Declaration and initialization of a long double variable --&gt;
&lt;!--   printf(&quot;%Lf\n&quot;, num5);  &#x2F;&#x2F; Output: 0.000000000000001 --&gt;
&lt;!-- } --&gt;
&lt;!-- ``` --&gt;
&lt;p&gt;I have found the file containing all the constants definitions for float values, but I am not (yet) able to correctly understand what&#x27;s going on in this header file:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt; find &#x2F;usr -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;float.h&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;tcl8.6&#x2F;tcl-private&#x2F;compat&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;c++&#x2F;11&#x2F;tr1&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;gcc&#x2F;x86_64-linux-gnu&#x2F;11&#x2F;include&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;llvm-13&#x2F;lib&#x2F;clang&#x2F;13.0.0&#x2F;include&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here is a snippet of things that may be of interest for anyone looking for the ranges:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;defined&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt; __STDC_VERSION__ &amp;amp;&amp;amp; __STDC_VERSION__ &amp;gt; 201710L
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Maximum finite positive value with MANT_DIG digits in the
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;   significand taking their maximum value.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef FLT_NORM_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef DBL_NORM_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef LDBL_NORM_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define FLT_NORM_MAX    __FLT_NORM_MAX__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define DBL_NORM_MAX    __DBL_NORM_MAX__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define LDBL_NORM_MAX   __LDBL_NORM_MAX__
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Whether each type matches an IEC 60559 format (1 for format, 2 for
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;   format and operations).  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef FLT_IS_IEC_60559
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef DBL_IS_IEC_60559
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef LDBL_IS_IEC_60559
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define FLT_IS_IEC_60559        __FLT_IS_IEC_60559__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define DBL_IS_IEC_60559        __DBL_IS_IEC_60559__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define LDBL_IS_IEC_60559       __LDBL_IS_IEC_60559__
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;bool&quot;&gt;Boolean type:&lt;&#x2F;h3&gt;
&lt;p&gt;The data type that can have two possible values: true or false. Include the &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;stdbool.h.html&quot;&gt;&amp;quot;stdbool.h&amp;quot;&lt;&#x2F;a&gt; header file in your program to use this data type. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdbool.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;strtobool(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const char* &lt;&#x2F;span&gt;&lt;span&gt;str) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;true&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;|| strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else if &lt;&#x2F;span&gt;&lt;span&gt;(strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;false&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;|| strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return false&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    fprintf(stderr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Invalid input: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, str);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; answer[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; is_learning;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter your name: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(name, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; name, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Your name is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Are you learning C programming: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(answer, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; answer, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    is_learning = strtobool(answer);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(is_learning)
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Very good, keep learning.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;You should learn C programming.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;!-- ### character types: --&gt;
&lt;!-- In C programming, `wchar_t` is a data type used to represent wide characters. It is typically used for handling Unicode and other wide character encodings that cannot be represented by the regular `char` data type. Here are three examples of how `wchar_t` can be used: --&gt;
&lt;!-- 1. Reading and printing wide characters: The `wint_t` data type is often used in conjunction with `wchar_t` to read and print wide characters. For example, the `wgetwc()` function can be used to read a wide character from standard input, and the `wprintf()` function can be used to print a wide character to the standard output. --&gt;
&lt;!--    ```c --&gt;
&lt;!--    #include &lt;wchar.h&gt; --&gt;
&lt;!--    #include &lt;stdio.h&gt; --&gt;
&lt;!--    int main() { --&gt;
&lt;!--        wchar_t c = L&#x27;Ã¤&#x27;; --&gt;
&lt;!--        wprintf(L&quot;The wide character is %lc\n&quot;, c); --&gt;
&lt;!--        return 0; --&gt;
&lt;!--    } --&gt;
&lt;!--    ``` --&gt;
&lt;!-- 2. Wide character string manipulation: `wchar_t` can be used to handle wide strings. The `&lt;wchar.h&gt;` header provides functions specifically designed to work with wide strings, such as `wcslen()` (to get the length of a wide string) and `wcscpy()` (to copy one wide string to another). --&gt;
&lt;!--    ```c --&gt;
&lt;!--    #include &lt;wchar.h&gt; --&gt;
&lt;!--    #include &lt;stdio.h&gt; --&gt;
&lt;!--    int main() { --&gt;
&lt;!--        wchar_t str1[] = L&quot;Hello&quot;; --&gt;
&lt;!--        wchar_t str2[10]; --&gt;
&lt;!--        wcslen(str1);        &#x2F;&#x2F; Returns the length of str1 --&gt;
&lt;!--        wcscpy(str2, str1);  &#x2F;&#x2F; Copies str1 to str2 --&gt;
&lt;!--        wprintf(L&quot;The copied string is %ls\n&quot;, str2); --&gt;
&lt;!--        return 0; --&gt;
&lt;!--    } --&gt;
&lt;!--    ``` --&gt;
&lt;!-- 3. Wide character I&#x2F;O: `wchar_t` can be used for reading and writing to files containing wide characters. The `wifstream` and `wofstream` classes in C++ provide support for wide character I&#x2F;O, allowing you to read and write wide characters directly from&#x2F;to files. --&gt;
&lt;!--    ```c --&gt;
&lt;!--    #include &lt;wchar.h&gt; --&gt;
&lt;!--    #include &lt;stdio.h&gt; --&gt;
&lt;!--    #include &lt;locale.h&gt; --&gt;
&lt;!--    int main() { --&gt;
&lt;!--        setlocale(LC_ALL, &quot;&quot;); --&gt;
&lt;!--        FILE* file = fopen(&quot;example.txt&quot;, &quot;w&quot;); --&gt;
&lt;!--        if (file != NULL) { --&gt;
&lt;!--            wchar_t str[] = L&quot;This is a wide character string.&quot;; --&gt;
&lt;!--            fwprintf(file, L&quot;%ls\n&quot;, str); --&gt;
&lt;!--            fclose(file); --&gt;
&lt;!--        } --&gt;
&lt;!--        return 0; --&gt;
&lt;!--    } --&gt;
&lt;!--    ``` --&gt;
&lt;!-- Note that when working with wide characters and strings, you need to ensure that your environment and compiler settings support the Unicode encoding required for the wide characters you are using. --&gt;
&lt;!--   - wchar_t (stddef.h): --&gt;
&lt;!--     - represents a wide character. --&gt;
&lt;!--     - designed to handle char from Unicode --&gt;
&lt;h3 id=&quot;void&quot;&gt;Void type:&lt;&#x2F;h3&gt;
&lt;p&gt;Void is a keyword to use as a placeholder where you would put a data type, to represent &amp;quot;no data&amp;quot;. The void data type represents the absence of type. Void types are used in the following situations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;to state that the specific type of the variable is not known &lt;em&gt;yet&lt;&#x2F;em&gt; (void pointers). &lt;&#x2F;li&gt;
&lt;li&gt;to state that the function returns no result (void functions).&lt;&#x2F;li&gt;
&lt;li&gt;to state that the function has no parameters.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT: We can&#x27;t directly dereference void pointers because the compiler doesn&#x27;t know the size or type of data being pointed to. We need to explicitly cast them to the correct type before dereferencing.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Here&#x27;s an example to illustrate the usage of void type:&lt;&#x2F;p&gt;
&lt;!-- ```c --&gt;
&lt;!-- #include &lt;stdio.h&gt; --&gt;
&lt;!-- &#x2F;&#x2F; Type is something that is either CHAR, either INTEGER, either FLOAT --&gt;
&lt;!-- typedef enum { --&gt;
&lt;!--     CHAR, --&gt;
&lt;!--     INTEGER, --&gt;
&lt;!--     FLOAT, --&gt;
&lt;!-- } Type; --&gt;
&lt;!-- &#x2F;&#x2F; Object is a structure, something with 2 attributes, a value and a type --&gt;
&lt;!-- typedef struct { --&gt;
&lt;!--     &#x2F;&#x2F; value is a pointer that will point to something, we don&#x27;t know yet what exactly --&gt;
&lt;!--     void* value; --&gt;
&lt;!--     Type type; --&gt;
&lt;!-- } Object;  --&gt;
&lt;!-- &#x2F;&#x2F; print is a function that does not return anything --&gt;
&lt;!-- &#x2F;&#x2F; print function takes a pointer to an Object as argument --&gt;
&lt;!-- void print(Object* o) { --&gt;
&lt;!--   Type type = o-&gt;type; --&gt;
&lt;!--   void* value = o-&gt;value; --&gt;
&lt;!--   switch (type) { --&gt;
&lt;!--   case CHAR: --&gt;
&lt;!--     &#x2F;&#x2F; explicit cast to the correct type before dereferencing. --&gt;
&lt;!--     printf(&quot;char item of value: %c\n&quot;, *((char*)value)); --&gt;
&lt;!--     break; --&gt;
&lt;!--   case INTEGER: --&gt;
&lt;!--     &#x2F;&#x2F; explicit cast to the correct type before dereferencing. --&gt;
&lt;!--     printf(&quot;int item of value: %d\n&quot;, *((int*)value)); --&gt;
&lt;!--     break; --&gt;
&lt;!--   case FLOAT: --&gt;
&lt;!--     &#x2F;&#x2F; explicit cast to the correct type before dereferencing. --&gt;
&lt;!--     printf(&quot;float item of value: %f\n&quot;, *((float*)value)); --&gt;
&lt;!--     break; --&gt;
&lt;!--   default: --&gt;
&lt;!--     printf(&quot;Invalid type.\n&quot;); --&gt;
&lt;!--   } --&gt;
&lt;!-- } --&gt;
&lt;!-- void bar(){ --&gt;
&lt;!--   int int_value = 42; --&gt;
&lt;!--   float float_value = 3.14; --&gt;
&lt;!--   char char_value = &#x27;A&#x27;; --&gt;
&lt;!--   Object o1; --&gt;
&lt;!--   o1.value = &amp;int_value; --&gt;
&lt;!--   o1.type = INTEGER; --&gt;
&lt;!--   Object o2 = {.value = &amp;float_value, .type = FLOAT}; --&gt;
&lt;!--   Object o3 = {&amp;char_value, CHAR}; --&gt;
&lt;!--   print(&amp;o1); --&gt;
&lt;!--   print(&amp;o2); --&gt;
&lt;!--   print(&amp;o3); --&gt;
&lt;!-- } --&gt;
&lt;!-- int main() { --&gt;
&lt;!--   bar(); --&gt;
&lt;!--   return 0; --&gt;
&lt;!-- } --&gt;
&lt;!-- ``` --&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; greet is a function that
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; returns no result
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and takes an unkown&#x2F;undefined list of arguments
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; notice how we can pass all the arguments we want
&lt;&#x2F;span&gt;&lt;span&gt;  greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A function declared with the void data type can&#x27;t return a value, we cannot use the return keyword inside a void function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;cscripts  &amp;gt;&amp;gt; gcc main.c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;.&#x2F;a.out 
&lt;&#x2F;span&gt;&lt;span&gt;main.c: In function ‘greet’:
&lt;&#x2F;span&gt;&lt;span&gt;main.c:57:10: warning: ‘return’ with a value, in function returning void
&lt;&#x2F;span&gt;&lt;span&gt;   57 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|   return&lt;&#x2F;span&gt;&lt;span&gt; 5432&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|          &lt;&#x2F;span&gt;&lt;span&gt;^~~~
&lt;&#x2F;span&gt;&lt;span&gt;main.c:56:6: note: declared here
&lt;&#x2F;span&gt;&lt;span&gt;   56 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;void greet(void){
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|      &lt;&#x2F;span&gt;&lt;span&gt;^~~~~~
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; greet is a function that
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; returns an int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and takes no arguments
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5432&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Because greet returns a result, I can retrieve and print it
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Greet returned the value: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, greet());
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}                                                                                                            
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we try to pass an argument to the greet function, we will receive an error message:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;cscripts  &amp;gt;&amp;gt; gcc main.c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;.&#x2F;a.out 
&lt;&#x2F;span&gt;&lt;span&gt;main.c: In function ‘main’:
&lt;&#x2F;span&gt;&lt;span&gt;main.c:57:44: error: too many arguments to function ‘greet’
&lt;&#x2F;span&gt;&lt;span&gt;   57 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|   &lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Greet returned the value: %d\n&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|                                            &lt;&#x2F;span&gt;&lt;span&gt;^~~~~
&lt;&#x2F;span&gt;&lt;span&gt;main.c:52:5: note: declared here
&lt;&#x2F;span&gt;&lt;span&gt;   52 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;int greet(void){
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|     &lt;&#x2F;span&gt;&lt;span&gt;^~~~~
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Last example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; age = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5432&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char*&lt;&#x2F;span&gt;&lt;span&gt; name = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Nsukami_&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; foo is a pointer that point to a not yet knwon data type
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void*&lt;&#x2F;span&gt;&lt;span&gt; foo;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s point to an integer
&lt;&#x2F;span&gt;&lt;span&gt;  foo = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;age;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; explicit cast to the correct type before dereferencing
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;age is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int*&lt;&#x2F;span&gt;&lt;span&gt;)foo));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s point to something else, for ex, a string
&lt;&#x2F;span&gt;&lt;span&gt;  foo = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;name;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; explicit cast to the correct type before dereferencing
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Name is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char**&lt;&#x2F;span&gt;&lt;span&gt;)foo));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;composite&quot;&gt;Composite types&lt;&#x2F;h2&gt;
&lt;p&gt;Any data type which can be constructed using the language&#x27;s primitive data types and other composite types.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;structs&quot;&gt;Structures:&lt;&#x2F;h3&gt;
&lt;p&gt;Structs (short for structure), a user-defined data type that allows us to group together related data items of different types. Those data items are known as members or fields. &lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; An address is something with 2 attributes
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a city street AND an house number
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; address {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; citystreet[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; housenumber;
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Address&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  Address my_address = {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Planet 42, Rue de la Liberté&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5432&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  };
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;I live in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. My house number is: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, my_address.citystreet, my_address.housenumber);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; how to update one of the fields
&lt;&#x2F;span&gt;&lt;span&gt;  my_address.housenumber = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;443&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;I live in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. My house number is now: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, my_address.citystreet, my_address.housenumber);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;enums&quot;&gt;Enum data type:&lt;&#x2F;h3&gt;
&lt;p&gt;An enumeration is a &lt;em&gt;special kind&lt;&#x2F;em&gt; of data type defined by the user. An enumeration consists of a set of constant &lt;em&gt;integers&lt;&#x2F;em&gt; that are named by the user. &lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef enum&lt;&#x2F;span&gt;&lt;span&gt; Level {
&lt;&#x2F;span&gt;&lt;span&gt;  LOW = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  MEDIUM,
&lt;&#x2F;span&gt;&lt;span&gt;  HIGH
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Level&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  Level level = MEDIUM;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;switch &lt;&#x2F;span&gt;&lt;span&gt;(level) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Low level&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Medium level&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;High level&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Unkown level value&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;} 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We said earlier an enumeration is a &lt;em&gt;special kind&lt;&#x2F;em&gt; of data type because.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;unions&quot;&gt;Unions:&lt;&#x2F;h3&gt;
&lt;!-- https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;252552&#x2F;why-do-we-need-c-unions --&gt;
&lt;p&gt;An union is a user-defined data type that allows different data types to be stored in the same memory location. It enables us to create a variable that can hold different types of data, but only one type at a time.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Struct that combines an enum and a union
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; The type of our object could be either INT, either FLOAT, either STRING
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    INT,
&lt;&#x2F;span&gt;&lt;span&gt;    FLOAT,
&lt;&#x2F;span&gt;&lt;span&gt;    STRING
&lt;&#x2F;span&gt;&lt;span&gt;  } type;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; all 3 values share the same memory location, only one can be set
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; value can be a int OR a float OR a string
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;union &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; intValue;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; floatValue;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; stringValue[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  } value;
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Object&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Function to print the object based on its type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;print(Object o) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; check the type of our object 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;switch&lt;&#x2F;span&gt;&lt;span&gt;(o.type) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span&gt;INT:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; then access the correct value
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Integer: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, o.value.intValue);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span&gt;FLOAT:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Float: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, o.value.floatValue);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case&lt;&#x2F;span&gt;&lt;span&gt; STRING:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;String: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, o.value.stringValue);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Creating objects of different types
&lt;&#x2F;span&gt;&lt;span&gt;  Object o1, o2, o3;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  o1.type = INT;
&lt;&#x2F;span&gt;&lt;span&gt;  o1.value.intValue = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  o2.type = FLOAT;
&lt;&#x2F;span&gt;&lt;span&gt;  o2.value.floatValue = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  o3.type = STRING;
&lt;&#x2F;span&gt;&lt;span&gt;  strcpy(o3.value.stringValue, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Printing the data objects
&lt;&#x2F;span&gt;&lt;span&gt;  print(o1);
&lt;&#x2F;span&gt;&lt;span&gt;  print(o2);
&lt;&#x2F;span&gt;&lt;span&gt;  print(o3);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;arrays&quot;&gt;Arrays:&lt;&#x2F;h3&gt;
&lt;p&gt;A type consisting of nonempty items of the same nature stored using contiguous memory location. The number of items (the size) never changes during the array lifetime. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; numbers[] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2.5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4.2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1.9&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5.6&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; size = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(numbers) &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(numbers[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; sum = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;, average;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; size; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;        sum += numbers[i];
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    average = sum &#x2F; size;
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Average: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, average);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;strings&quot;&gt;Strings:&lt;&#x2F;h3&gt;
&lt;p&gt;A string is just a sequence of characters stored inside an array and ending with the null character: &#x27;\0&#x27;. We don&#x27;t have strings as we have them in Python programming.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter your name: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(name, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; name, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Your name is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To know what are the functions available for string manipulation, Python developers will type &lt;code&gt;help(str)&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;Help on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;str &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;module builtins:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;str(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt; |  str(object=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; str
&lt;&#x2F;span&gt;&lt;span&gt; |  str(bytes_or_buffer[, encoding[, errors]]) -&amp;gt; str
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  Create a new string object &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;the given object. If encoding &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;or
&lt;&#x2F;span&gt;&lt;span&gt; |  errors &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;is &lt;&#x2F;span&gt;&lt;span&gt;specified, then the object must expose a data buffer
&lt;&#x2F;span&gt;&lt;span&gt; |  that will be decoded using the given encoding &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;and &lt;&#x2F;span&gt;&lt;span&gt;error handler.
&lt;&#x2F;span&gt;&lt;span&gt; |  Otherwise, returns the result of object.__str__() (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;defined)
&lt;&#x2F;span&gt;&lt;span&gt; |  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;or &lt;&#x2F;span&gt;&lt;span&gt;repr(object).
&lt;&#x2F;span&gt;&lt;span&gt; |  encoding defaults to sys.getdefaultencoding().
&lt;&#x2F;span&gt;&lt;span&gt; |  errors defaults to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;strict&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  Methods defined here:
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __add__(self, value, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt; |      Return self+value.
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __contains__(self, key, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt; |      Return bool(key &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self).
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __eq__(self, value, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt; |      Return self==value.
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __format__(self, format_spec, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;C developers will look inside the &lt;code&gt;&amp;lt;string.h&amp;gt;&lt;&#x2F;code&gt; header &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;009695399&#x2F;basedefs&#x2F;string.h.html&quot;&gt;file&lt;&#x2F;a&gt;. &lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;nskm2  &amp;gt;&amp;gt; find &#x2F;usr&#x2F;include -type f -name &amp;quot;string.h&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;linux&#x2F;string.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;tcl8.6&#x2F;tcl-private&#x2F;compat&#x2F;string.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;string.h
&lt;&#x2F;span&gt;&lt;span&gt;nskm2  &amp;gt;&amp;gt; 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;They can also read the man pages, &lt;code&gt;man string&lt;&#x2F;code&gt;: &lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;STRING(3)                                  Linux Programmer&amp;#39;s Manual                                 STRING(3)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;NAME
&lt;&#x2F;span&gt;&lt;span&gt;       stpcpy,  strcasecmp, strcat, strchr, strcmp, strcoll, strcpy, strcspn, strdup, strfry, strlen, strncat,
&lt;&#x2F;span&gt;&lt;span&gt;       strncmp, strncpy, strncasecmp, strpbrk, strrchr, strsep, strspn, strstr, strtok, strxfrm, index, rindex
&lt;&#x2F;span&gt;&lt;span&gt;       - string operations
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;SYNOPSIS
&lt;&#x2F;span&gt;&lt;span&gt;       #include &amp;lt;strings.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       int strcasecmp(const char *s1, const char *s2);
&lt;&#x2F;span&gt;&lt;span&gt;              Compare the strings s1 and s2 ignoring case.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       int strncasecmp(const char *s1, const char *s2, size_t n);
&lt;&#x2F;span&gt;&lt;span&gt;              Compare the first n bytes of the strings s1 and s2 ignoring case.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       char *index(const char *s, int c);
&lt;&#x2F;span&gt;&lt;span&gt;              Return a pointer to the first occurrence of the character c in the string s.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       char *rindex(const char *s, int c);
&lt;&#x2F;span&gt;&lt;span&gt;              Return a pointer to the last occurrence of the character c in the string s.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       #include &amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       char *stpcpy(char *dest, const char *src);
&lt;&#x2F;span&gt;&lt;span&gt;              Copy a string from src to dest, returning a pointer to the end of the resulting string at dest.
&lt;&#x2F;span&gt;&lt;span&gt; Manual page string(3) line 1 (press h for help or q to quit)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;!-- ### Pointers:{#pointers} --&gt;
&lt;!-- Pointer, an object that stores the memory address of another variable or the memory address of a function as its value. To learn more about them, soon enough I will [article](#). --&gt;
&lt;!-- 2. Declaration: Pointers are declared using the `*` symbol. For example, `int* ptr;` declares a pointer `ptr` which can hold the address of an integer variable. --&gt;
&lt;!-- 3. &amp; Operator: The `&amp;` operator is used to get the address of a variable. For example, `int x = 10; int* ptr = &amp;x;` assigns the address of `x` to the pointer `ptr`. --&gt;
&lt;!-- 4. Dereferencing: Dereferencing a pointer means accessing the value stored at the memory address it points to. It is done using the `*` operator. For example, `int value = *ptr;` assigns the value stored at the memory location pointed by `ptr` to the variable `value`. --&gt;
&lt;!-- 5. Null Pointers: A null pointer is a pointer that does not point to any valid memory address. It is represented by the value `NULL` or `0`. Using a null pointer can cause a program to crash or produce unexpected results. --&gt;
&lt;!-- 6. Pointer Arithmetic: Pointers can be incremented or decremented to navigate through memory. Pointer arithmetic is done in terms of the size of the data type it points to. For example, `ptr++` will move the pointer to the next memory location based on the size of the data type. --&gt;
&lt;!-- 7. Dynamic Memory Allocation: Pointers are commonly used for dynamic memory allocation using functions like `malloc`, `calloc`, and `realloc`. These functions allow you to allocate memory during runtime and return a pointer to the allocated memory. --&gt;
&lt;!-- 8. Pointers and Arrays: In C, arrays are closely related to pointers. An array name is actually a pointer to the first element of the array. You can use pointers to iterate through array elements or pass arrays to functions. --&gt;
&lt;!-- 9. Pointers to Pointers: Pointers can also point to other pointers. This is useful in scenarios like pointer-based data structures or passing pointer addresses to functions. --&gt;
&lt;!-- 10. Memory Management: Pointers require careful memory management to avoid memory leaks and undefined behavior. You must ensure that memory is allocated and deallocated appropriately to prevent memory leaks and dangling pointers. --&gt;
&lt;!-- Understanding pointers is crucial in C programming as it allows you to efficiently manipulate memory, work with complex data structures, and interact with system resources. However, improper use of pointers can lead to difficult-to-debug errors, so it is important to be cautious and thoroughly understand how pointers work. --&gt;
&lt;!-- - holds the memory address of another variable. --&gt;
&lt;!-- - allow direct manipulation and access the memory location of a variable --&gt;
&lt;h2 id=&quot;constants&quot;&gt;Constants:&lt;&#x2F;h2&gt;
&lt;p&gt;A fixed value that cannot be, &lt;em&gt;that should not&lt;&#x2F;em&gt; be changed during the execution of a program. &lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;If we have a fixed value that is used in calculations, we can define it as a constant to avoid hard-coding the value multiple times.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s define PI as a constant
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; PI = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14159&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; radius = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s reuse our constant
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; area = PI &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Trying to modify our constant will give us an error message:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;main.c: In function ‘main’:
&lt;&#x2F;span&gt;&lt;span&gt;main.c:129:6: error: assignment of read-only variable ‘PI’
&lt;&#x2F;span&gt;&lt;span&gt;  129 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|   &lt;&#x2F;span&gt;&lt;span&gt;PI = 4.5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|      &lt;&#x2F;span&gt;&lt;span&gt;^
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Another way to use constants is this one. Instead of using arbitrary numbers directly in your code, you can define them as constants with meaningful names to improve code readability and maintainability.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; LENGTH = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; MIN_AGE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;18&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; MAX_AGE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; input[LENGTH];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; age;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter your age: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; input, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  age = strtol(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(age &amp;lt; MIN_AGE || age &amp;gt; MAX_AGE) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; is an invalid age! Please enter an age between &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; and &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, age, MIN_AGE, MAX_AGE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;When declaring an array, we can use a constant to specify its size, making it easier to modify if needed.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; In this example, `ARRAY_SIZE` is declared as a constant to specify the size of an array. By using a
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; constant, you can easily change the size of the array by modifying the constant&amp;#39;s value in a single place.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; ARRAY_SIZE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; arr[ARRAY_SIZE];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;We can also declare function parameters as &lt;code&gt;const&lt;&#x2F;code&gt; to ensure that the function does not modify the parameter:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; This helps prevent accidental modifications and indicates that the function is read-only.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int &lt;&#x2F;span&gt;&lt;span&gt;arr[], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;size) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; size; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;        printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, arr[i]);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;!-- - there are different types of constants in C: --&gt;
&lt;!--   - integer constants: whole numbers without a decimal point: 10, -5, 0 --&gt;
&lt;!--   - floating-point constants: numbers with a decimal point: 3.14, -2.5, 0.0 --&gt;
&lt;!--   - character constants: represent individual characters enclosed in single quotes: &#x27;A&#x27;, &#x27;b&#x27;, &#x27;$&#x27;. --&gt;
&lt;!--   - string constants: represent a sequence of characters enclosed in double quotes: &quot;Hello&quot;, &quot;World&quot;, &quot;123&quot; --&gt;
&lt;!-- - constants are assigned meaningful names --&gt;
&lt;!--   - using the `#define` preprocessor directive --&gt;
&lt;!--   - or using the `const` keyword --&gt;
&lt;!--     ```c --&gt;
&lt;!--     #define PI 3.14159 --&gt;
&lt;!--     const int MAX_VALUE = 100; --&gt;
&lt;!--     const char NEW_LINE = &#x27;\n&#x27;; --&gt;
&lt;!--     const char* MESSAGE = &quot;Hello, World!&quot;; --&gt;
&lt;!--     ``` --&gt;
&lt;!-- ## Operators: --&gt;
&lt;!--   - symbols that perform specific operations on operands or variables --&gt;
&lt;!--   - used to manipulate data and perform various calculations --&gt;
&lt;!--   - several types: --&gt;
&lt;!--     - arithmetic operators: --&gt;
&lt;!--       - perform basic mathematical operations such as (+) (-) (*) (&#x2F;) (%) --&gt;
&lt;!--    - comparison operators: --&gt;
&lt;!--      - compare values and determine the relationship between them. --&gt;
&lt;!--      - relational operators include (&lt;) (&gt;) (==) (!=) (&lt;=) (&gt;=) --&gt;
&lt;!--    - logical operators: --&gt;
&lt;!--      - used to combine conditions and perform logical operations --&gt;
&lt;!--      - they are AND (&amp;&amp;) OR (||) NOT (!) --&gt;
&lt;!--    - assignment operators: --&gt;
&lt;!--      - used to assign values to variables --&gt;
&lt;!--      - they are the equal sign (=) (+=) (-=) (&#x2F;=) (*=) --&gt;
&lt;!--    - increment and decrement operators: --&gt;
&lt;!--      - used to increase or decrease the value of a variable by 1 --&gt;
&lt;!--      - increment operator (++) adds 1 to a variable --&gt;
&lt;!--      - decrement operator (--) subtracts 1 --&gt;
&lt;!--    - bitwise operators: --&gt;
&lt;!--      - used to manipulate individual bits of a variable --&gt;
&lt;!--      - include AND (&amp;), OR (|), XOR (^), left shift (&lt;&lt;) right shift (&gt;&gt;) complement (~) --&gt;
&lt;!--    - conditional operator --&gt;
&lt;!--      - operator (?:) evaluates a condition &amp; returns one of 2 expressions based on the result --&gt;
&lt;!--      - similar to an if-else statement. For example, `a &gt; b ? a : b` returns the larger value between a and b. --&gt;
&lt;!-- ## Loops --&gt;
&lt;!-- ## Conditions --&gt;
&lt;!-- ## Functions --&gt;
&lt;!-- ## Preprocessing --&gt;
&lt;!-- ## Entry points --&gt;
&lt;!-- ## Let&#x27;s consider the following snippet: --&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion:&lt;&#x2F;h2&gt;
&lt;p&gt;I really hope you&#x27;ve learned something. I did \o&#x2F; In the next episode, I will try to write about header files or pointers or something else depending on the current moon, the weather and the stars alignment. Also, thanks to &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@orbifx&quot;&gt;Orbifx&lt;&#x2F;a&gt; for taking the time to answer all my questions.&lt;&#x2F;p&gt;
&lt;!-- My position is this. It is easier to learn C when you never written any program before, when you start with a soft, fresh and open mind. Learning any programming language before learning C may put you in a position where you feel like learning C is really difficult, while it&#x27;s not. It&#x27;s just that your hand have been held for too long. Python definitely held my hand for a very long time. Phew. --&gt;
&lt;!-- I think C is not a language that should be taught to beginners, Python is. But, I also think that at some point _(I need to define that point more precisely)_ every Python programmer should relearn programming using C. --&gt;
&lt;h1 id=&quot;more-on-the-topic&quot;&gt;More on the topic:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hal.inria.fr&#x2F;hal-02383654&#x2F;file&#x2F;ModernC.pdf&quot;&gt;Modern C, Jens Gustedt&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gnu-c-manual&#x2F;gnu-c-manual.pdf&quot;&gt;The GNU C Reference Manual&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;amjadmajid&#x2F;Makefile&quot;&gt;Explanation about how to write a Makefile&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.open-std.org&#x2F;jtc1&#x2F;sc22&#x2F;wg14&#x2F;www&#x2F;docs&#x2F;n2655.pdf&quot;&gt;Make false and true first-class language features v4
proposal for C23&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;on-a-completely-differnt-note&quot;&gt;On a completely differnt note:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=snvzAfYOFks&quot;&gt;Des organismes aux algorithmes, l&#x27;odyssée computationnelle du vivant | Xavier Berthet | TEDxINPENSAT&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;2023.djangocon.africa&#x2F;&quot;&gt;The first DjangoCon Africa, in Zanzibar, Tanzania.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!-- https:&#x2F;&#x2F;www.freecodecamp.org&#x2F;news&#x2F;the-c-beginners-handbook&#x2F; --&gt;
&lt;!-- https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;C_data_types --&gt;
&lt;!-- https:&#x2F;&#x2F;thephd.dev&#x2F;c23-is-coming-here-is-what-is-on-the-menu --&gt;
&lt;!-- https:&#x2F;&#x2F;www.open-std.org&#x2F;jtc1&#x2F;sc22&#x2F;wg14&#x2F;www&#x2F;docs&#x2F;n2353.htm --&gt;
&lt;!-- https:&#x2F;&#x2F;habr.com&#x2F;en&#x2F;companies&#x2F;badoo&#x2F;articles&#x2F;512802&#x2F; --&gt;
&lt;!-- https:&#x2F;&#x2F;gcc.gnu.org&#x2F;onlinedocs&#x2F;gcc&#x2F;Typeof.html#Typeof --&gt;
&lt;!-- https:&#x2F;&#x2F;www.infoq.com&#x2F;news&#x2F;2023&#x2F;05&#x2F;gcc13-c2x-features&#x2F; --&gt;
&lt;!-- https:&#x2F;&#x2F;floooh.github.io&#x2F;2019&#x2F;09&#x2F;27&#x2F;modern-c-for-cpp-peeps.html --&gt;
&lt;!-- https:&#x2F;&#x2F;github.com&#x2F;AnthonyCalandra&#x2F;modern-c-features --&gt;
&lt;!-- https:&#x2F;&#x2F;matt.sh&#x2F;howto-c --&gt;
&lt;!-- In C programming, a union is a user-defined data type that allows different data types to be stored in the same memory location. It enables you to create a variable that can hold different types of data, but only one type at a time. Here are three examples of unions in C programming: --&gt;
&lt;!-- 1. Example of a Union for Different Numeric Types: --&gt;
&lt;!-- ```c --&gt;
&lt;!-- #include &lt;stdio.h&gt; --&gt;
&lt;!-- union Number { --&gt;
&lt;!--     int integer; --&gt;
&lt;!--     float floatingPoint; --&gt;
&lt;!--     double doublePrecision; --&gt;
&lt;!-- }; --&gt;
&lt;!-- int main() { --&gt;
&lt;!--     union Number num; --&gt;
&lt;!--     num.integer = 10; --&gt;
&lt;!--     printf(&quot;Integer: %d\n&quot;, num.integer); --&gt;
&lt;!--     num.floatingPoint = 3.14; --&gt;
&lt;!--     printf(&quot;Floating Point: %f\n&quot;, num.floatingPoint); --&gt;
&lt;!--     num.doublePrecision = 2.71828; --&gt;
&lt;!--     printf(&quot;Double Precision: %lf\n&quot;, num.doublePrecision); --&gt;
&lt;!--     return 0; --&gt;
&lt;!-- } --&gt;
&lt;!-- ``` --&gt;
&lt;!-- In this example, the union `Number` can hold an integer, a floating-point, or a double precision value. However, only one of them can be stored and accessed at a time. --&gt;
&lt;!-- 2. Example of a Union for Different Data Types: --&gt;
&lt;!-- ```c --&gt;
&lt;!-- #include &lt;stdio.h&gt; --&gt;
&lt;!-- union Data { --&gt;
&lt;!--     int intValue; --&gt;
&lt;!--     float floatValue; --&gt;
&lt;!--     char stringValue[20]; --&gt;
&lt;!-- }; --&gt;
&lt;!-- int main() { --&gt;
&lt;!--     union Data data; --&gt;
&lt;!--     data.intValue = 10; --&gt;
&lt;!--     printf(&quot;Integer: %d\n&quot;, data.intValue); --&gt;
&lt;!--     data.floatValue = 3.14; --&gt;
&lt;!--     printf(&quot;Float: %f\n&quot;, data.floatValue); --&gt;
&lt;!--     strcpy(data.stringValue, &quot;Hello World&quot;); --&gt;
&lt;!--     printf(&quot;String: %s\n&quot;, data.stringValue); --&gt;
&lt;!--     return 0; --&gt;
&lt;!-- } --&gt;
&lt;!-- ``` --&gt;
&lt;!-- This example demonstrates a union `Data` that can hold an integer, a float, or a string. The `stringValue` member can store a string of up to 20 characters. --&gt;
&lt;!-- 3. Example of a Union for Bit Manipulation: --&gt;
&lt;!-- ```c --&gt;
&lt;!-- #include &lt;stdio.h&gt; --&gt;
&lt;!-- union Bits { --&gt;
&lt;!--     unsigned int value; --&gt;
&lt;!--     struct { --&gt;
&lt;!--         unsigned int bit0 : 1; --&gt;
&lt;!--         unsigned int bit1 : 1; --&gt;
&lt;!--         unsigned int bit2 : 1; --&gt;
&lt;!--         unsigned int bit3 : 1; --&gt;
&lt;!--     } bits; --&gt;
&lt;!-- }; --&gt;
&lt;!-- int main() { --&gt;
&lt;!--     union Bits bits; --&gt;
&lt;!--     bits.value = 10; --&gt;
&lt;!--     printf(&quot;Value: %u\n&quot;, bits.value); --&gt;
&lt;!--     bits.bits.bit0 = 1; --&gt;
&lt;!--     printf(&quot;Bit 0: %u\n&quot;, bits.bits.bit0); --&gt;
&lt;!--     bits.bits.bit3 = 0; --&gt;
&lt;!--     printf(&quot;Bit 3: %u\n&quot;, bits.bits.bit3); --&gt;
&lt;!--     return 0; --&gt;
&lt;!-- } --&gt;
&lt;!-- ``` --&gt;
&lt;!-- In this example, a union `Bits` is used to manipulate individual bits of an integer value. The struct inside the union represents the individual bits, and changing the values of these bits modifies the original integer value. --&gt;
&lt;!-- These examples illustrate the versatility and usage of unions in C programming, allowing you to store different types of data in a single memory location. --&gt;
&lt;!-- https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;25926862&#x2F;good-examples-using-union-with-enum --&gt;
&lt;!-- https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;252552&#x2F;why-do-we-need-c-unions --&gt;
&lt;!-- https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;117293&#x2F;does-using-const-on-function-parameters-have-any-effect-why-does-it-not-affect --&gt;
&lt;!-- https:&#x2F;&#x2F;softwareengineering.stackexchange.com&#x2F;questions&#x2F;204500&#x2F;when-and-for-what-purposes-should-the-const-keyword-be-used-in-c-for-variables --&gt;
&lt;!-- https:&#x2F;&#x2F;www.cs.dartmouth.edu&#x2F;~campbell&#x2F;cs50&#x2F;dictionary-example.c --&gt;
&lt;!-- https:&#x2F;&#x2F;www.cs.yale.edu&#x2F;homes&#x2F;aspnes&#x2F;pinewiki&#x2F;C(2f)HashTables.html?highlight=%28CategoryAlgorithmNotes%29 --&gt;
&lt;!-- https:&#x2F;&#x2F;www.simplilearn.com&#x2F;tutorials&#x2F;c-tutorial&#x2F;enum-in-c#:~:text=Enumeration%20or%20Enum%20in%20C,same%20or%20even%20different%20programmer. --&gt;
&lt;!-- http:&#x2F;&#x2F;osr600doc.sco.com&#x2F;en&#x2F;SDK_c++&#x2F;_Array_manipulation.html --&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Decorators</title>
		<published>2023-02-06T00:00:00+00:00</published>
		<updated>2023-02-06T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/decor/" type="text/html"/>
		<id>https://nskm.xyz/posts/decor/</id>
		<content type="html">&lt;p&gt;I was watching a &lt;em&gt;really&lt;&#x2F;em&gt; interesting &lt;a href=&quot;https:&#x2F;&#x2F;y.com.sb&#x2F;watch?v=RL7BECNn-RI&quot;&gt;video&lt;&#x2F;a&gt; about buildings architecture in New York, when one of my &lt;a href=&quot;https:&#x2F;&#x2F;dit.sn&quot;&gt;DIT&lt;&#x2F;a&gt; student asked me to explain to him what was happening in this &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;flask-user-authentication-example&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;main&#x2F;utils.py#L7&quot;&gt;piece of code&lt;&#x2F;a&gt;. A function I have written few months ago to check for valid authentication tokens. In this post, I will try to show how decorators in &lt;a href=&quot;https:&#x2F;&#x2F;python.org&quot;&gt;Python&lt;&#x2F;a&gt;, a powerful concept, allows us to apply new functionality without modifying the existing structure of an object. &lt;a href=&quot;https:&#x2F;&#x2F;y.com.sb&#x2F;watch?v=cDk9L72ZkuE&quot;&gt;Music please&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;assets&#x2F;decorated.png&quot; alt=&quot;&quot; title=&quot;Somewhere in Africa&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#f&quot;&gt;1 A function doing one thing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#g&quot;&gt;2 A decorator, modifying the behaviour of the function&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#h&quot;&gt;3 A decorator should keep important informations&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#i&quot;&gt;4 A decorator should receive a flexible number of argument&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#j&quot;&gt;5 A decorator can also have parameters&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#k&quot;&gt;6 We are still able to access the decorated function&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#l&quot;&gt;7 An interesting example&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#m&quot;&gt;8 Even more interesting, how decorators are used elsewhere&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;f&quot;&gt;1. A function:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose we want to join 2 paths:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pathlib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Path
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]: a = Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]: a
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;]: b = Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]: a.joinpath(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s suppose we usually combine 2 paths together. So much that we created a function for that purpose:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;]: path_t = str | Path
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;22&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Join 2 paths together&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b, a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;bar&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a, b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;25&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;25&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;corge&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;26&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;qux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;26&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;corge&#x2F;qux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;g&quot;&gt;2. A decorator modifying the behaviour of the function:&lt;&#x2F;h1&gt;
&lt;p&gt;While it may seem confusing at first, a decorator is really just &lt;em&gt;a function that takes a function and returns a function&lt;&#x2F;em&gt;. Let me explain. &lt;&#x2F;p&gt;
&lt;p&gt;Suppose we usually combine our home path with another path. Let&#x27;s suppose the first parameter is often our home path. Let&#x27;s suppose we can&#x27;t modify the original function. Python functions are &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;First-class_citizen&quot;&gt;first-class citizens&lt;&#x2F;a&gt;. That means: &lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We can pass a function as an argument of another function.&lt;&#x2F;li&gt;
&lt;li&gt;We can assign a function to a variable.&lt;&#x2F;li&gt;
&lt;li&gt;We can return a function as a value from another function. &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;38&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func: Callable[[path_t, path_t], path_t]) -&amp;gt; Callable[[path_t], path_t]:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A wrapper that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;39&lt;&#x2F;span&gt;&lt;span&gt;]: f = homeprefix(jp)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span&gt;]: f(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;]: f(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;]: f(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;43&lt;&#x2F;span&gt;&lt;span&gt;]: f(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&#x2F;qux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;43&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&#x2F;qux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;44&lt;&#x2F;span&gt;&lt;span&gt;]: f(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;spam&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;44&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;spam&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As strange as it may seems, we could have done the following: &lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;]: jp = homeprefix(jp) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# there is an alternative syntax
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;46&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;46&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;48&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foobar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;48&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foobar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;49&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;49&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead of &lt;code&gt;jp = homeprefix(jp)&lt;&#x2F;code&gt; we could use the following syntax which better vehicle our intent: &lt;strong&gt;modifying the behaviour of an existing function&lt;&#x2F;strong&gt;. Simply put: &lt;strong&gt;decorating&lt;&#x2F;strong&gt; our original function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;51&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# here we are, decorating jp function 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Join 2 paths together&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;52&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;52&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;53&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&#x2F;qux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;53&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&#x2F;qux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;54&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;54&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;55&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;55&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;56&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;h&quot;&gt;3. A decorator should keep important informations:&lt;&#x2F;h1&gt;
&lt;p&gt;Now we have another problem. Because we are literally replacing one function with another, we&#x27;re also losing important informations like the docstring and the name: &lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;61&lt;&#x2F;span&gt;&lt;span&gt;]: ?jp
&lt;&#x2F;span&gt;&lt;span&gt;Signature: jp(m)
&lt;&#x2F;span&gt;&lt;span&gt;Docstring: A function that takes one parameter.
&lt;&#x2F;span&gt;&lt;span&gt;File:      ~&#x2F;GIT&#x2F;nskm2&#x2F;&amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;59&lt;&#x2F;span&gt;&lt;span&gt;-b4f67b1e800d&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;Type:      function
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;62&lt;&#x2F;span&gt;&lt;span&gt;]: jp.__name__
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;62&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;wrapper&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;63&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s the reason we have &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html#functools.wraps&quot;&gt;functools.wraps&lt;&#x2F;a&gt;. &lt;code&gt;Wraps&lt;&#x2F;code&gt; takes the decorated function and adds the functionality of copying over the function name, docstring, arguments list, etc to &lt;strong&gt;the returned function&lt;&#x2F;strong&gt;. And since wraps is itself a decorator:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;63&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;functools &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;wraps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;64&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join 2 paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;66&lt;&#x2F;span&gt;&lt;span&gt;]: ?jp
&lt;&#x2F;span&gt;&lt;span&gt;Signature: jp(path1: str | pathlib.Path, path2: str | pathlib.Path) -&amp;gt; str | pathlib.Path
&lt;&#x2F;span&gt;&lt;span&gt;Docstring: A function that join &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;paths together.
&lt;&#x2F;span&gt;&lt;span&gt;File:      ~&#x2F;GIT&#x2F;nskm2&#x2F;&amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65&lt;&#x2F;span&gt;&lt;span&gt;-1703cd8a40dc&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;Type:      function
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;67&lt;&#x2F;span&gt;&lt;span&gt;]: jp.__name__
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;67&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;jp&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;68&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;i&quot;&gt;4. A decorator should receive a flexible number of argument:&lt;&#x2F;h1&gt;
&lt;p&gt;Now, let&#x27;s suppose our original function can take many arguments:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;101&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(*args: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join many paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;args:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(*args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span&gt;ValueError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;args should be longer&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;102&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bac&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;abc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;102&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;bac&#x2F;abc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;103&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bac&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;103&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;bac&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;104&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;abc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;104&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;abc&#x2F;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The previous decorator is not flexible enough because the returned function can&#x27;t take more than 1 parameter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;106&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m):
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;107&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(*args: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join many paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;args:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(*args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span&gt;ValueError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;args should be longer&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;108&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;108&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;a&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;109&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;---------------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;TypeError                                 Traceback (most recent call last)
&lt;&#x2F;span&gt;&lt;span&gt;Cell In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;109&lt;&#x2F;span&gt;&lt;span&gt;], line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;----&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TypeError: jp() takes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;positional argument but &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;were given
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;110&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s rewrite our decorator so that the returned function can take an infinte number or arguments:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;113&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(*args):  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# here is our update: using *args 
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;114&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(*args: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join many paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;args:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(*args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span&gt;ValueError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;args should be longer&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;115&lt;&#x2F;span&gt;&lt;span&gt;]: jp()
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;115&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;116&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;c&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;d&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;116&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;b&#x2F;c&#x2F;d&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;117&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;c&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;d&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;117&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;b&#x2F;c&#x2F;d&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;118&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;118&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;119&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the help of the special parameters *args and **kwargs, decorators become more generic. That way if we need the same kind of decorator in different functions with different arguments, we can write just one decorator. In general, a decorator is written like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;decorator(func):
&lt;&#x2F;span&gt;&lt;span&gt;    @wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;        func(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;j&quot;&gt;5. A decorator can also have parameters:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose people using the decorator want to be able to set what should the prefix used as the first parameter of our jp function. Let&#x27;s suppose we want the decorator to receive one parameter, which is the prefix:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;70&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(prefix): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# this function builds and returns a decorator 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(func): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# this function is the decorator 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the function wrapping the original function 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(prefix, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;71&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join 2 paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;72&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;72&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;73&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;73&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;74&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;74&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We understand better what&#x27;s going on when we do this instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;]: decorator = homeprefix(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;patrick&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# setup a prefix 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;76&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;decorator  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# decorate 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join 2 paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;77&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;77&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;patrick&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;78&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;quux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;78&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;patrick&#x2F;quux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;79&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;k&quot;&gt;6. We are still able to access the decorated function:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose for some reason we want to test the function as if it was not decorated. Let&#x27;s suppose we still want to use the underlying function. To achieve that, we&#x27;ll use the &lt;code&gt;__wrapped__&lt;&#x2F;code&gt; attribute (assuming we used the &lt;code&gt;functools.wrap&lt;&#x2F;code&gt; function). &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html?highlight=__wrapped__&quot;&gt;Somewhere&lt;&#x2F;a&gt; in the documentation, we can read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The original underlying function is accessible through the &lt;strong&gt;wrapped&lt;&#x2F;strong&gt; attribute. This is useful for introspection, for bypassing the cache, or for rewrapping the function with a different cache.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;127&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;127&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;]: jp.__wrapped__(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# original function 
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;129&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;l&quot;&gt;7. An interesting example:&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;csv
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sqlite3
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pathlib
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;functools &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;wraps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;here = pathlib.Path(__file__)
&lt;&#x2F;span&gt;&lt;span&gt;db = here.parent.parent.parent &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sqlite_stuff&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook.db&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;connect(db):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A decorator to connect to an SQLite database and execute a query.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    conn = sqlite3.connect(db)
&lt;&#x2F;span&gt;&lt;span&gt;    conn.isolation_level = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(f):
&lt;&#x2F;span&gt;&lt;span&gt;        @wraps(f)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;            query = f(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;            rset = conn.execute(query).fetchall()
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;rset
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;columns(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;columns, limit=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A decorator to specify what columns should be retrieved.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cols = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.join(columns)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(f):
&lt;&#x2F;span&gt;&lt;span&gt;        @wraps(f)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;            query = f(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs).split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;            start, end = query[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].strip(), query[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].strip()
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{start} {cols} {end}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; limit &lt;&#x2F;span&gt;&lt;span&gt;{limit}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;as_csv(where=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;result.csv&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A decorator to save the result as a csv file.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(f):
&lt;&#x2F;span&gt;&lt;span&gt;        @wraps(f)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;            rset = f(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;open(where, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;w&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, newline=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;dest:
&lt;&#x2F;span&gt;&lt;span&gt;                csv_writer = csv.writer(
&lt;&#x2F;span&gt;&lt;span&gt;                    dest, delimiter=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;,&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, quoting=csv.QUOTE_ALL, lineterminator=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\r\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                )
&lt;&#x2F;span&gt;&lt;span&gt;                csv_writer.writerows(rset)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;len(rset)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;###
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@as_csv()
&lt;&#x2F;span&gt;&lt;span&gt;@connect(db)
&lt;&#x2F;span&gt;&lt;span&gt;@columns(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;artistId&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;run(table=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;albums&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    query = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;select * from &lt;&#x2F;span&gt;&lt;span&gt;{table}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;query
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    print(run())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;8-even-more-interesting&quot;&gt;8. Even more interesting:&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sqlite3
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pathlib
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;functools &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;wraps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;here = pathlib.Path(__file__)
&lt;&#x2F;span&gt;&lt;span&gt;db = here.parent.parent.parent &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sqlite_stuff&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook.db&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;connect(cls):
&lt;&#x2F;span&gt;&lt;span&gt;    conn = sqlite3.connect(db)
&lt;&#x2F;span&gt;&lt;span&gt;    conn.isolation_level = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# sqlite3.IMMEDIATE
&lt;&#x2F;span&gt;&lt;span&gt;    setattr(cls, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;conn&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, conn)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;cls
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;select(cls):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;select(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;cls.conn.execute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;select * from &lt;&#x2F;span&gt;&lt;span&gt;{cls.__name__}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).fetchall()
&lt;&#x2F;span&gt;&lt;span&gt;    setattr(cls, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;select&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, select)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;cls
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@select
&lt;&#x2F;span&gt;&lt;span&gt;@connect
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Albums:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    a = Albums()
&lt;&#x2F;span&gt;&lt;span&gt;    print(a.select())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;m&quot;&gt;8. Even more interesting, how decorators are used elsewhere:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cubicweb.org&#x2F;&quot;&gt;Cubicweb&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;cubes&#x2F;api&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;cubicweb_api&#x2F;routes.py#L137&quot;&gt;decorator&lt;&#x2F;a&gt; used to raise an AuthenticationError if no user is detected.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;flask.palletsprojects.com&#x2F;en&#x2F;2.2.x&#x2F;&quot;&gt;Flask&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pallets&#x2F;flask&#x2F;blob&#x2F;afc13b9390ae2e40f4731e815b49edc9ef52ed4b&#x2F;examples&#x2F;tutorial&#x2F;flaskr&#x2F;auth.py#L19&quot;&gt;decorator&lt;&#x2F;a&gt;  that redirects anonymous users to the login page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;flask.palletsprojects.com&#x2F;en&#x2F;2.2.x&#x2F;patterns&#x2F;viewdecorators&#x2F;#templating-decorator&quot;&gt;Templating decorator&lt;&#x2F;a&gt; invented by the &lt;a href=&quot;https:&#x2F;&#x2F;turbogears.org&#x2F;&quot;&gt;TurboGears&lt;&#x2F;a&gt; guys a while back to automatically render a template.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;main&#x2F;django&#x2F;views&#x2F;decorators&#x2F;http.py&quot;&gt;decorators&lt;&#x2F;a&gt; to manipulate &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Headers&quot;&gt;http headers&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;9-more-on-this-topic&quot;&gt;9. More on this topic:&lt;&#x2F;h1&gt;
&lt;p&gt;I hope that you found this post helpful. To learn about this topic, please, browse the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0318&#x2F;&quot;&gt;PEP 318 – Decorators for Functions and Methods&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;wiki.python.org&#x2F;moin&#x2F;PythonDecoratorLibrary&quot;&gt;PythonDecoratorLibrary&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html&quot;&gt;functools&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;glossary.html#term-decorator&quot;&gt;decorator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;sqlite3.html#&quot;&gt;DB-API 2.0 interface for SQLite databases&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;15357776&#x2F;what-is-the-difference-between-functools-wraps-and-update-wrapper&quot;&gt;The difference between wraps and update_wrapper&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.artima.com&#x2F;weblogs&#x2F;viewpost.jsp?thread=241209&quot;&gt;Python Decorators III: A Decorator-Based Build System&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;2692&#x2F;&quot;&gt;Interior decorating&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!-- https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=zA53Lf-fqcQ --&gt;
&lt;!-- https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;6685232&#x2F;how-are-methods-classmethod-and-staticmethod-implemented-in-python --&gt;
&lt;!-- https:&#x2F;&#x2F;wiki.python.org&#x2F;moin&#x2F;PythonDecoratorLibrary --&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Test driven interview</title>
		<published>2022-10-16T00:00:00+00:00</published>
		<updated>2022-10-16T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/tdi/" type="text/html"/>
		<id>https://nskm.xyz/posts/tdi/</id>
		<content type="html">&lt;h1 id=&quot;introduction&quot;&gt;Introduction:&lt;&#x2F;h1&gt;
&lt;p&gt;Test Driven Development &lt;em&gt;TDD&lt;&#x2F;em&gt; is a method of implementing software that rely on software requirements being converted to test cases before software is fully developed.&lt;&#x2F;p&gt;
&lt;p&gt;Red, Green and Refactor is the 3 phases of TDD. When followed, this order of steps helps ensure that you have tests for the code you are writing and you are writing only the code that you have to test for.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;context&quot;&gt;Context:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose we should implement some requirements. Let&#x27;s suppose all the requirements and specifications are written using unit tests. See this &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&quot;&gt;repository&lt;&#x2F;a&gt;. Our mission is to write enough code to make all the tests pass. Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;y.com.sb&#x2F;watch?v=gptoH8rzG14&quot;&gt;dive in&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#setup&quot;&gt;Setup&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#tests&quot;&gt;Tests&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Requirements&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#firstreq&quot;&gt;First requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#secondreq&quot;&gt;Second requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#thirdreq&quot;&gt;Third requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#fourthreq&quot;&gt;Fourth requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#fifthreq&quot;&gt;Fifth requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#lastreq&quot;&gt;Last requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; git create-branch feat-1  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# create a new branch for feature work
&lt;&#x2F;span&gt;&lt;span&gt;Basculement sur la nouvelle branche &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;feat-1&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(.env) ~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; python3.10 -m venv .env  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# create a virtual environment
&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; source .env&#x2F;bin&#x2F;activate  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# activate virtual environment
&lt;&#x2F;span&gt;&lt;span&gt;(.env) ~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; pip install -r requirements.txt  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# install requirements
&lt;&#x2F;span&gt;&lt;span&gt;Collecting django&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;.2,&amp;gt;=3.1
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached Django-3.1.14-py3-none-any.whl (7.8 MB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting djangorestframework&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;.13,&amp;gt;=3.12
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached djangorestframework-3.12.4-py3-none-any.whl (957 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting sqlparse&amp;gt;=0.2.2
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached sqlparse-0.4.3-py3-none-any.whl (42 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting asgiref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;,&amp;gt;=3.2.10
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached asgiref-3.5.2-py3-none-any.whl (22 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting pytz
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached pytz-2022.4-py2.py3-none-any.whl (500 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Installing collected packages: pytz, sqlparse, asgiref, django, djangorestframework
&lt;&#x2F;span&gt;&lt;span&gt;Successfully installed asgiref-3.5.2 django-3.1.14 djangorestframework-3.12.4 pytz-2022.4 sqlparse-0.4.3
&lt;&#x2F;span&gt;&lt;span&gt;WARNING: You are using pip version 22.0.4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span&gt;however, version 22.3 is available.
&lt;&#x2F;span&gt;&lt;span&gt;You should consider upgrading via the &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;.env&#x2F;bin&#x2F;python3.10 -m pip install --upgrade pip&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; command.
&lt;&#x2F;span&gt;&lt;span&gt;(.env) ~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;tests&quot;&gt;How to launch tests ?&lt;&#x2F;h2&gt;
&lt;p&gt;According to the &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;4.1&#x2F;topics&#x2F;testing&#x2F;overview&#x2F;#running-tests&quot;&gt;documentation&lt;&#x2F;a&gt;, we can run tests using the test command of your project&#x27;s manage.py utility. Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;eradman.com&#x2F;entrproject&#x2F;&quot;&gt;run that command&lt;&#x2F;a&gt; when any of the Python files changes. We also tell Django to stop running the test suite after first failed test. In a different terminal, let&#x27;s type one of the following commands:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# you can ask git ls-files command to watch for all the python files
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; git ls-files&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt; -- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*.py&amp;#39; &amp;#39;:!:*__.py&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;entr sh -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python src&#x2F;manage.py test --failfast --force-color -v 2 src&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# you can ask find command to watch for all the python files
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; find src -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -not -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__*&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;entr sh -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python src&#x2F;manage.py test --failfast --force-color -v 2 src&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the ack command seems more readable
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; ack -f --python &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;entr sh -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python src&#x2F;manage.py test --failfast --force-color -v 2 src&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Here is our first error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;django.db.utils.OperationalError: no such table: inventory_product
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;firstreq&quot;&gt;1. First requirements: we need a Product model.&lt;&#x2F;h2&gt;
&lt;p&gt;We need to create a model named Product inside an application named inventory. &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L12&quot;&gt;Somewhere&lt;&#x2F;a&gt; within the tests file, we can read:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;create_coke(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Product.objects.create(
&lt;&#x2F;span&gt;&lt;span&gt;            description=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Coca-Cola&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            unit_price=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            stock=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;models.py#L4&quot;&gt;open&lt;&#x2F;a&gt; the &lt;code&gt;models.py&lt;&#x2F;code&gt; file and write the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Product(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    description = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    unit_price = models.FloatField()
&lt;&#x2F;span&gt;&lt;span&gt;    stock = models.IntegerField()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;After running the migration scripts:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; python src&#x2F;manage.py makemigrations &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;python src&#x2F;manage.py migrate
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The tests tells us to return an &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Status&#x2F;201&quot;&gt;http status 201&lt;&#x2F;a&gt; after Product creation. Right now, we have a 404. We need to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;create a REST API.&lt;&#x2F;li&gt;
&lt;li&gt;we should be able to create a Product via the API.&lt;&#x2F;li&gt;
&lt;li&gt;and the returned http status should be 201 _created.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;=====================================================================&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAIL: test_create_product (modules.inventory.tests.ProductTestCase)
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, line 45, in test_create_product
&lt;&#x2F;span&gt;&lt;span&gt;    self.assertEqual(response.status_code, 201)
&lt;&#x2F;span&gt;&lt;span&gt;AssertionError: 404 != 201
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 1 test in 0.010s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAILED (failures=1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;secondreq&quot;&gt;We need a REST API for managing a Product.&lt;&#x2F;h2&gt;
&lt;p&gt;Another &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L44&quot;&gt;part&lt;&#x2F;a&gt; of the tests is telling us we need an url named &lt;code&gt;api&#x2F;products&#x2F;&lt;&#x2F;code&gt;. Let&#x27;s create a &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;serializers&#x2F;#modelserializer&quot;&gt;serializer&lt;&#x2F;a&gt;, a &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;viewsets&#x2F;#modelviewset&quot;&gt;viewset&lt;&#x2F;a&gt; and a &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;routers&#x2F;&quot;&gt;router&lt;&#x2F;a&gt;. Here is the code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# &#x2F;src&#x2F;modules&#x2F;inventory&#x2F;views.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;serializers  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;viewsets
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Product
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ProductSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = Product
&lt;&#x2F;span&gt;&lt;span&gt;        fields = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__all__&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ProductsViewSet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.ModelViewSet&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Product.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = ProductSerializer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# &#x2F;src&#x2F;pos&#x2F;urls.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.urls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;path, include
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;routers
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;modules.inventory.views &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;ProductsViewSet
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;router = routers.DefaultRouter()
&lt;&#x2F;span&gt;&lt;span&gt;router.register(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;products&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, ProductsViewSet)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;urlpatterns = [
&lt;&#x2F;span&gt;&lt;span&gt;    path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;api&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, include(router.urls)),
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;After the changes, we notice some progress. The test tells us that if we attempt to delete a Product, we should receive an &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Status&#x2F;405&quot;&gt;http status 405&lt;&#x2F;a&gt; instead of 204. Litteraly, we have been able to delete a Product while it shouldn&#x27;t be allowed:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;=====================================================================&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAIL: test_delete_product (modules.inventory.tests.ProductTestCase)
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, line 142, in test_delete_product
&lt;&#x2F;span&gt;&lt;span&gt;    self.assertEqual(response.status_code, 405)
&lt;&#x2F;span&gt;&lt;span&gt;AssertionError: 204 != 405
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 2 tests in 0.011s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAILED (failures=1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;thirdreq&quot;&gt;A Product cannot be deleted.&lt;&#x2F;h2&gt;
&lt;p&gt;I should have take the time to carefully read all the tests. &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L139&quot;&gt;Indeed&lt;&#x2F;a&gt;, one of them clearly states that we can&#x27;t delete a Product. Obviously, the ModelViewSet is not a good choice. We should update our viewset in a way that forbids product deletion. The operations: &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L36&quot;&gt;creating&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L18&quot;&gt;listing&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L95&quot;&gt;updating&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L57&quot;&gt;getting one product&lt;&#x2F;a&gt; should still be permitted. To achieve that, we&#x27;ll use some &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;generic-views&#x2F;#mixins&quot;&gt;mixins&lt;&#x2F;a&gt; offered by the framework. The product viewset becomes:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;viewsets, mixins
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ProductsViewSet(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.CreateModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.ListModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.UpdateModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.RetrieveModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.GenericViewSet&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Product.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = ProductSerializer
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;let-s-commit-what-have-been-done-so-far&quot;&gt;Let&#x27;s commit what have been done so far.&lt;&#x2F;h3&gt;
&lt;p&gt;All the tests related to Product are passing. We can commit and push what we&#x27;ve done so far.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; git commit -m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Add Product API&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;[feat-1 a11ffeb] Add Product API
&lt;&#x2F;span&gt;&lt;span&gt; 5 files changed, 76 insertions(+), 6 deletions(-)
&lt;&#x2F;span&gt;&lt;span&gt; create mode 100644 src&#x2F;modules&#x2F;inventory&#x2F;migrations&#x2F;0001_initial.py
&lt;&#x2F;span&gt;&lt;span&gt; rewrite src&#x2F;modules&#x2F;inventory&#x2F;views.py (98%)
&lt;&#x2F;span&gt;&lt;span&gt; create mode 100644 src&#x2F;modules&#x2F;orders&#x2F;migrations&#x2F;0001_initial.py
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; git push origin feat-1 
&lt;&#x2F;span&gt;&lt;span&gt;Énumération des objets: 25, fait.
&lt;&#x2F;span&gt;&lt;span&gt;Décompte des objets: 100% (24&#x2F;24), fait.
&lt;&#x2F;span&gt;&lt;span&gt;Compression par delta en utilisant jusqu&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;à 4 fils d&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;exécution
&lt;&#x2F;span&gt;&lt;span&gt;Compression des objets: 100% (14&#x2F;14), fait.
&lt;&#x2F;span&gt;&lt;span&gt;Écriture des objets: 100% (14&#x2F;14), 1.80 Kio &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;1.80 Mio&#x2F;s, fait.
&lt;&#x2F;span&gt;&lt;span&gt;Total 14 (delta 6), réutilisés 0 (delta 0), réutilisés du pack 0
&lt;&#x2F;span&gt;&lt;span&gt;remote: 
&lt;&#x2F;span&gt;&lt;span&gt;remote: Create a new pull request for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;feat-1&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;remote:   https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;compare&#x2F;master...feat-1
&lt;&#x2F;span&gt;&lt;span&gt;remote: 
&lt;&#x2F;span&gt;&lt;span&gt;remote: . Processing 1 references
&lt;&#x2F;span&gt;&lt;span&gt;remote: Processed 1 references in total
&lt;&#x2F;span&gt;&lt;span&gt;To https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview.git
&lt;&#x2F;span&gt;&lt;span&gt; * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;new branch&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;      feat-1 -&amp;gt; feat-1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width:100; height:100&quot; src=&quot;&#x2F;images&#x2F;ofcourse.gif&quot; alt=&quot;Of course&quot; title=&quot;Of course&quot;&#x2F;&gt;
&lt;h2 id=&quot;fourthreq&quot;&gt;We need another model named Order.&lt;&#x2F;h2&gt;
&lt;p&gt;All the tests located in the &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py&quot;&gt;inventory&lt;&#x2F;a&gt; application are passing. This is why we decided to commit and push. There is one test currently failing, it it located inside the &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py&quot;&gt;orders&lt;&#x2F;a&gt; application. The test tells us we need to create a model named Order:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;=====================================================================&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAIL: test_create_order (modules.orders.tests.OrdersTestCase)
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, line 87, in test_create_order
&lt;&#x2F;span&gt;&lt;span&gt;    self.assertEqual(response.status_code, 201)
&lt;&#x2F;span&gt;&lt;span&gt;AssertionError: 404 != 201
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 7 tests in 0.054s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAILED (failures=1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s continue reading the tests. &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py#L90&quot;&gt;Line 90&lt;&#x2F;a&gt;, we read that an item should have 4 attributes: &lt;code&gt;description, quantity, unit_price, total&lt;&#x2F;code&gt;. We also read that an Order has 2 attributes: &lt;code&gt;items&lt;&#x2F;code&gt; and &lt;code&gt;total&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;order = Order.objects.get()
&lt;&#x2F;span&gt;&lt;span&gt;expected = {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;id&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: order.id,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;items&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;        {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;description&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Coca-Cola&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;quantity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;unit_price&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;total&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        },
&lt;&#x2F;span&gt;&lt;span&gt;        {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;description&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Potato Chips&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;quantity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;unit_price&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;total&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2000&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    ],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;total&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, our models may look like the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Order(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    @property
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;total(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# this field is just a sum, depending on all the items in the current Order
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum([x.total &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self.items.all()])
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;OrderItem(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    order = models.ForeignKey(Order, related_name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;items&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, on_delete=models.CASCADE)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# For being able to retrieve the description and the unit_price fields ?
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Should I add Product as a foreign key ? 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Should I duplicate the fields ?
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    @property
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;total(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the total is obviouly a property that will be calculated 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# based on the number of items in the Order &amp;amp; the unit price for each item 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;float(self.unit_price * self.quantity)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;fifthreq&quot;&gt;We should be able to update the stock depending on the number of items ordered:&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py#L114&quot;&gt;Line 114&lt;&#x2F;a&gt; of the tests tells us, a Product should have a method to refresh its stock:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;pyhon&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-pyhon &quot;&gt;&lt;code class=&quot;language-pyhon&quot; data-lang=&quot;pyhon&quot;&gt;&lt;span&gt;self.chips.refresh_from_db()
&lt;&#x2F;span&gt;&lt;span&gt;self.assertEqual(self.chips.stock, 8)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s update our Product model and add the new method. This method will substract the number of Product ordered from the current stock:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Product(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    description = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    unit_price = models.FloatField()
&lt;&#x2F;span&gt;&lt;span&gt;    stock = models.IntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;refresh_from_db(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;modules.orders.models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;OrderItem
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        self.stock = self.stock - sum(
&lt;&#x2F;span&gt;&lt;span&gt;            oi.quantity &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;oi &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;OrderItem.objects.filter(id=self.id)
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;        self.save()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;lastreq&quot;&gt;We should be able to update a Product without modifiying already made Orders:&lt;&#x2F;h2&gt;
&lt;p&gt;After reading the &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py#L141&quot;&gt;Line 141&lt;&#x2F;a&gt;, we know that the fields &lt;code&gt;description and unit_price&lt;&#x2F;code&gt; will be duplicated inside the OrderItem model. During the OrderItem creation, we should copy those fields from the Product model. This task will be achieved using our serializers:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ItemSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    quantity = serializers.IntegerField(required=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    unit_price = serializers.FloatField(required=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    description = serializers.CharField(required=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = OrderItem
&lt;&#x2F;span&gt;&lt;span&gt;        fields = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;description&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;quantity&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;unit_price&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;total&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;OrderSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    items = ItemSerializer(many=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;create(self, validated_data):
&lt;&#x2F;span&gt;&lt;span&gt;        order = Order.objects.create()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# I want to be able to access the id, the id represent the Product id
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# So, I&amp;#39;m using initial_data instead of validated_data
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# I&amp;#39;ll need to find a proper way
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;item_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self.initial_data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;items&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]:
&lt;&#x2F;span&gt;&lt;span&gt;            product = Product.objects.get(id=item_data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;            OrderItem.objects.create(
&lt;&#x2F;span&gt;&lt;span&gt;                id=product.id,
&lt;&#x2F;span&gt;&lt;span&gt;                order=order,
&lt;&#x2F;span&gt;&lt;span&gt;                description=product.description,
&lt;&#x2F;span&gt;&lt;span&gt;                unit_price=product.unit_price,
&lt;&#x2F;span&gt;&lt;span&gt;                quantity=item_data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;quantity&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;            )
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;order
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = Order
&lt;&#x2F;span&gt;&lt;span&gt;        fields = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;items&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;total&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;OrdersViewSet(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.CreateModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.ListModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.RetrieveModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.GenericViewSet&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Order.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = OrderSerializer
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion:&lt;&#x2F;h1&gt;
&lt;p&gt;It&#x27;s been a long time since I&#x27;ve written Django and DRF code. I really enjoyed the exercise. The final result can be found &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; python src&#x2F;manage.py test src --failfast
&lt;&#x2F;span&gt;&lt;span&gt;Creating test database for alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;default&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;System check identified no issues (0 silenced).
&lt;&#x2F;span&gt;&lt;span&gt;............
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 12 tests in 0.093s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;OK
&lt;&#x2F;span&gt;&lt;span&gt;Destroying test database for alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;default&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;while-i-still-have-your-attention&quot;&gt;While I still have your attention:&lt;&#x2F;h1&gt;
&lt;p&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;djangochat.com&#x2F;episodes&#x2F;django-unicorn-adam-hill&quot;&gt;conversation&lt;&#x2F;a&gt; with Adam Hill about writing software, the perfect settings file set up, and more. Adam is a software engineer at The Motley Fool and the author of multiple open source packages including &lt;a href=&quot;https:&#x2F;&#x2F;www.django-unicorn.com&#x2F;&quot;&gt;Django Unicorn&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The videos for the &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=0kOLsFQGxyk&amp;amp;list=PLY_che_OEsX3eIKKLUKvQXfVJhCHYWATM&quot;&gt;DjangoCon Europe 2022&lt;&#x2F;a&gt; are available. Can someone tell me please when the &lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;weblog&#x2F;2019&#x2F;nov&#x2F;18&#x2F;introducing-djangocon-africa&#x2F;&quot;&gt;DjangoCon Africa&lt;&#x2F;a&gt; event will be held ? So I can prepare myself ?&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;more-on-the-topic&quot;&gt;More on the topic:&lt;&#x2F;h1&gt;
&lt;p&gt;I really hope you have learned something. To dive even more deeper in the topic, let me please recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;125&#x2F;&quot;&gt;Marketing interview&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Test-driven_development&quot;&gt;Test Driven Development&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;unittest.html&quot;&gt;Unit testing framework&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Learn&#x2F;Server-side&#x2F;Django&#x2F;Testing&quot;&gt;Testing a Django web application&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;test-driven-django-development.readthedocs.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;Test Driven Web Development with Django&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;4.1&#x2F;topics&#x2F;testing&#x2F;overview&#x2F;&quot;&gt;Writing and running tests&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;google.aip.dev&#x2F;&quot;&gt;API Improvement Proposal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;dsfpa&#x2F;&quot;&gt;Django single file project&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=rR4n-0KYeKQ&quot;&gt;How we write&#x2F;review code in big tech companies&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Linear regression</title>
		<published>2022-07-24T00:00:00+00:00</published>
		<updated>2022-07-24T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/linreg/" type="text/html"/>
		<id>https://nskm.xyz/posts/linreg/</id>
		<content type="html">&lt;p&gt;For the &lt;a href=&quot;https:&#x2F;&#x2F;dit.sn&quot;&gt;Dakar Institute of Technology&lt;&#x2F;a&gt;, I give Python introductory classes. During one of my sessions I was asked about simple linear regression with Python. Let the music &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=adBfKzfemtI&quot;&gt;play&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;49aedcae11b5c8fa00.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#introduction&quot;&gt;Introduction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#first-solution&quot;&gt;First solution&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#reading-the-data-set&quot;&gt;Reading the data set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#plotting-the-data-set&quot;&gt;Plotting the data set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#splitting-the-data-set&quot;&gt;Splitting the data set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#ordinary-least-squares&quot;&gt;Least squares estimates&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#mean&quot;&gt;Mean&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#variance&quot;&gt;Variance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#covariance&quot;&gt;Covariance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#estimates&quot;&gt;Estimates&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#prediction&quot;&gt;Prediction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#error&quot;&gt;How good is the model&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#final-plot&quot;&gt;Regression line&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#class&quot;&gt;The complete program&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#statistics&quot;&gt;Another solution using the statistics module&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#code&quot;&gt;Just give me the code please&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;introduction&quot;&gt;Introduction:&lt;&#x2F;h1&gt;
&lt;p&gt;Simple linear regression is a commonly used type of predictive analysis. The idea of regression is to examine if a set of predictor variables do a good job in predicting an outcome variable.&lt;&#x2F;p&gt;
&lt;p&gt;Linear regression models are used in many industries such as healthcare (predicting disease from biological factors), economics (predicting growth), businesses (predicting product sales), etc ...&lt;&#x2F;p&gt;
&lt;p&gt;For simple linear regression, the relationship between the independent variable &lt;strong&gt;x&lt;&#x2F;strong&gt; and the dependent variable &lt;strong&gt;y&lt;&#x2F;strong&gt; is expressed as: &lt;code&gt;y = slope * x + intercept + noise&lt;&#x2F;code&gt;, where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;slope&lt;&#x2F;em&gt; and &lt;em&gt;intercept&lt;&#x2F;em&gt; are the regression parameters that are estimated&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;noise&lt;&#x2F;em&gt; is the variability of the data (difference between predicted and actual values of &lt;strong&gt;y&lt;&#x2F;strong&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;first-solution&quot;&gt;First solution:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s write a Python program to achieve this task. We&#x27;ll use the following &lt;a href=&quot;&#x2F;assets&#x2F;dataset.txt&quot;&gt;data set&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reading-the-data-set&quot;&gt;1. Reading the data set:&lt;&#x2F;h2&gt;
&lt;p&gt;To read the data, we&#x27;ll write a function in charge of opening and reading the file containing our data. We assume each line will consist of an int value, followed by a tabulation and a float value. This function will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;open the file&lt;&#x2F;li&gt;
&lt;li&gt;get all the lines except the first one (the header)&lt;&#x2F;li&gt;
&lt;li&gt;convert first column to int, convert second column to float&lt;&#x2F;li&gt;
&lt;li&gt;return a tuple containing 2 things: &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;read_text(
&lt;&#x2F;span&gt;&lt;span&gt;    filename: t.Union[pathlib.Path, t.AnyStr],
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; t.Tuple[t.Collection[float], t.Collection[float]]:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;open(filename, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;r&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;f:
&lt;&#x2F;span&gt;&lt;span&gt;        slines = [line.strip().split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;[li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;f.readlines()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:]]]
&lt;&#x2F;span&gt;&lt;span&gt;        nlines = [(int(x), float(y)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;slines]
&lt;&#x2F;span&gt;&lt;span&gt;        X, Y = zip(*nlines)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;X, Y
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Bonjour&lt;&#x2F;p&gt;
&lt;h2 id=&quot;plotting-the-data-set&quot;&gt;2. Plotting the data set:&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ll have to do some plotting. The following program is just one we use to setup our &lt;a href=&quot;https:&#x2F;&#x2F;matplotlib.org&#x2F;stable&#x2F;api&#x2F;_as_gen&#x2F;matplotlib.pyplot.subplots.html#matplotlib-pyplot-subplots&quot;&gt;plots&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;_, ax = plt.subplots()
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_xlabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;X-coordinates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_ylabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Y-coordinates &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_title(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Graphical representation of our points&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.grid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The first step in finding a linear regression equation is to determine if there is a relationship between the two variables. To determine if there is a relationship between x and y we can scatter plot the data set.&lt;&#x2F;p&gt;
&lt;p&gt;Scatter plots are used to observe relationships between variables. We&#x27;ll need one function to do a scatter plot: put dots on our graph and see each individual data point.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;scatter_plot(
&lt;&#x2F;span&gt;&lt;span&gt;    x: t.Collection[float], y: t.Collection[float], ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    ax.scatter(x, y, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;red&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using this function with our &lt;a href=&quot;&#x2F;assets&#x2F;dataset.txt&quot;&gt;data set&lt;&#x2F;a&gt;, we can see the following chart:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;b61840e0f55e0c6000.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;We&#x27;ll need a function to draw a line. If we correctly find estimates for our regression parameters (slope and the intercept), we should be able to draw a line that will go through the cloud of data points:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;line_plot(a: int, b: int, ax: mpl.axes.Axes) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    x = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;130&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    y = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;x]
&lt;&#x2F;span&gt;&lt;span&gt;    ax.plot(x, y)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;splitting-the-data-set&quot;&gt;3. Splitting the data set:&lt;&#x2F;h2&gt;
&lt;p&gt;We don’t want our model to over learn from the data and perform poorly when presented data never seen before. We also need to have a mechanism to assess how well our model is generalizing. Hence, we&#x27;ll need to separate our input data into &lt;em&gt;at least&lt;&#x2F;em&gt; 2 sets: training and testing:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-training-data-set&quot;&gt;1. Training data set:&lt;&#x2F;h4&gt;
&lt;p&gt;This is the set of data that will be used only for learning. We will use only one part of the data set to find the best parameters for our model. &lt;&#x2F;p&gt;
&lt;h4 id=&quot;2-testing-data-set&quot;&gt;2. Testing data set:&lt;&#x2F;h4&gt;
&lt;p&gt;It would be best if we evaluate the model with new data that hasn’t been seen by the model before. So we need a set of data used to provide an evaluation without bias of the model that was fitted on the training data set.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s write a function that will split our data. We&#x27;ll keep 80% for the training and 20% for testing. This function will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;randomly pick 20% of all the indexes in our collection&lt;&#x2F;li&gt;
&lt;li&gt;with those 20% indexes, create a list containing 20% of the collections&lt;&#x2F;li&gt;
&lt;li&gt;from those 20% indexes, create a list containing 80% of the collections&lt;&#x2F;li&gt;
&lt;li&gt;return all the sets&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;split_seq = t.Tuple[
&lt;&#x2F;span&gt;&lt;span&gt;    t.Collection[float], t.Collection[float], t.Collection[float], t.Collection[float]
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;split_train_test(
&lt;&#x2F;span&gt;&lt;span&gt;    X: t.Collection[float], Y: t.Collection[float], frac: float = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.2
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; split_seq:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    indexes = list(range(len(X)))
&lt;&#x2F;span&gt;&lt;span&gt;    indexes_test = set(random.sample(indexes, int(frac * len(X))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 20% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;    X_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;    Y_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 80% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;    X_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;    Y_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;X_train, X_test, Y_train, Y_test
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s visualize how the 2 sets are rendered in a scatter plot:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;3b4d8a3cf8c1442b00.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;ordinary-least-squares&quot;&gt;4. Least squares for the slope and the intercept:&lt;&#x2F;h1&gt;
&lt;p&gt;How do we estimate our parameters α and β ? That’s the learning procedure. There are different optimization techniques to implement this part. To determine the optimum values of these two parameters, we should find the line that best fit the data set.&lt;&#x2F;p&gt;
&lt;p&gt;To determine the optimum values of these two parameters, we need to find the &lt;strong&gt;slope&lt;&#x2F;strong&gt; and the &lt;strong&gt;intercept&lt;&#x2F;strong&gt; so that when we sum all the errors between the predicted y values and the observed y values, this sum should be the least possible.&lt;&#x2F;p&gt;
&lt;p&gt;The following chart will show us all the distances (or all the differences, or all the errors) between each point on the dataset and the regression line:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;98e11ca1344d399400.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s see how the chart looks like when the parameters are not correctly estimated &lt;em&gt;(the regression line does not &amp;quot;fit&amp;quot; the data set)&lt;&#x2F;em&gt; :&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;7f33d5fc2a8c12d700.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;And here is the function used to plot the errors. This function will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Take the estimated coefficients α and β&lt;&#x2F;li&gt;
&lt;li&gt;Take the list of X and the list of Y&lt;&#x2F;li&gt;
&lt;li&gt;For all points in our data set:
&lt;ul&gt;
&lt;li&gt;predict &lt;code&gt;y&lt;&#x2F;code&gt; based on α and β&lt;&#x2F;li&gt;
&lt;li&gt;draw a dashed line between 2 points: &lt;code&gt;(x, y)&lt;&#x2F;code&gt; and &lt;code&gt;(x, y_pred)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;plot_errors(
&lt;&#x2F;span&gt;&lt;span&gt;    a: float,
&lt;&#x2F;span&gt;&lt;span&gt;    b: float,
&lt;&#x2F;span&gt;&lt;span&gt;    X: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;    Y: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;    ax: mpl.axes.Axes,
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;zip(X, Y):
&lt;&#x2F;span&gt;&lt;span&gt;        y_pred = a * x + b
&lt;&#x2F;span&gt;&lt;span&gt;        ax.plot([x, x], [y, y_pred], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, label=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Errors&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, linestyle=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dashed&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;the-total-error-of-this-model-is-the-sum-of-all-the-errors-for-each-point&quot;&gt;The total error of this model is the sum of all the errors for each point:&lt;&#x2F;h1&gt;
&lt;p&gt;We should sum all the errors and look for the least error. Here is the formula: &lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The SSE (Sum of Squared Errors) is equal to the sum of the square of Y observed - Y calculated, for all point in the data set.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;81d1697567dc974900.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;If we do all the correct &lt;a href=&quot;&#x2F;assets&#x2F;Simple_Linear_Regression_Leastsquares.pdf&quot;&gt;algebraic manipulation&lt;&#x2F;a&gt;, we should find that:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;d4c4f5b9f90b639600.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;p&gt;Seeing those formulas, those familiar with statistics already know we&#x27;ll need to define a function to calculate a mean, another function to calculate a variance and a function to calculate a covariance. βeta hat can be defined as Covariance(X, Y) &#x2F; Variance(X).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mean&quot;&gt;5.1 Mean:&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;em&gt;arithmetic&lt;&#x2F;em&gt; mean, is a measure of central tendency of a finite set of numbers: specifically, the sum of the values divided by the number of values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;mean(lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum(lst) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;variance&quot;&gt;5.2 Variance:&lt;&#x2F;h2&gt;
&lt;p&gt;The variance  is the measure of the &lt;strong&gt;spread&lt;&#x2F;strong&gt; in a data set. The variance is a measure of how far each number in the data set is from the mean, and thus from every other number in the data set. The higher the variance, the more spread out the variables are.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;variance(lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    m = mean(lst)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum([(x - m) ** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;lst]) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;variance: 582.8381391772394
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is 2 ways to plot the variance. We can do it manually, or we can use a &lt;a href=&quot;https:&#x2F;&#x2F;matplotlib.org&#x2F;stable&#x2F;api&#x2F;_as_gen&#x2F;matplotlib.pyplot.boxplot.html#matplotlib-pyplot-boxplot&quot;&gt;box plot&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;c202d06d65cf747100.png&quot; &#x2F;&gt;

&lt;&#x2F;center&gt;
&lt;img style=&quot;display: block; margin: 0 auto&quot; src=&quot;&#x2F;assets&#x2F;jcvd_split.gif&quot; alt=&quot;Jean-Claude Van Damme split looks like a box plot&quot; title=&quot;Jean-Claude Van Damme split looks like a box plot&quot;&#x2F;&gt;
&lt;br&gt;
&lt;p&gt;Here is the function used to plot the variance:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;plot_variance(
&lt;&#x2F;span&gt;&lt;span&gt;    X: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;    Y: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    fig: mpl.figure.Figure
&lt;&#x2F;span&gt;&lt;span&gt;    ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    _, ax = plt.subplots(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].set_xlabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;X-coordinates &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].set_ylabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Y-coordinates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].set_title(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Graphical representation of variance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].grid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# box plot
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].boxplot([X], vert=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;, showmeans=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# mean line
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].axvline(x=mean(X), ymin=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, ymax=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;130&lt;&#x2F;span&gt;&lt;span&gt;, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;orange&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# distance from point to mean line
&lt;&#x2F;span&gt;&lt;span&gt;    x_mean = mean(X)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;zip(X, Y):
&lt;&#x2F;span&gt;&lt;span&gt;        ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].plot(
&lt;&#x2F;span&gt;&lt;span&gt;            [x, x_mean],
&lt;&#x2F;span&gt;&lt;span&gt;            [y, y],
&lt;&#x2F;span&gt;&lt;span&gt;            marker=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;o&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;green&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            label=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Mean&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            linestyle=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dotted&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;    plt.show()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;covariance&quot;&gt;5.3 Covariance:&lt;&#x2F;h2&gt;
&lt;p&gt;The covariance is a measure of the relationship between two variables. Covariance is the extent to which the variance in one variable depends on another variable. The higher the covariance, the stronger the relationship.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;covariance(X: t.Sequence[float], Y: t.Sequence[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    mean_x, mean_y, length_x = mean(X), mean(Y), len(X)
&lt;&#x2F;span&gt;&lt;span&gt;    covar = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(X)):
&lt;&#x2F;span&gt;&lt;span&gt;        covar += (X[i] - mean_x) * (Y[i] - mean_y)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;covar &#x2F; length_x
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;covariance: 2059.003344867359
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;estimates&quot;&gt;5.4 Estimates:&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have a function for calculating the variance and another one for calculating the covariance, we can write a function that will calculate our slope and our intercept using this 2 formulas seen earlier:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;estimate_coefficients(X: t.Collection[float], Y: t.Collection[float]) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;    b1 = covariance(X, Y) &#x2F; variance(X)
&lt;&#x2F;span&gt;&lt;span&gt;    b0 = mean(Y) - b1 * mean(X)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;b0, b1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;prediction&quot;&gt;5.5. Prediction:&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have extracted our coefficients, let&#x27;s see if we can make a prediction, we&#x27;ll use the testing data set:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;b, a = estimate_coefficients(X_train, Y_train)
&lt;&#x2F;span&gt;&lt;span&gt;Y_predicted = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;X_test]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, j &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;zip(Y_test, Y_predicted):
&lt;&#x2F;span&gt;&lt;span&gt;    print(i, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, j)   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# print Y observed in testing set next to Y predicted using our coefficients
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt; python3 script.py
&lt;&#x2F;span&gt;&lt;span&gt;392.5 	 389.8167994835544
&lt;&#x2F;span&gt;&lt;span&gt;15.7 	 65.88576964183908
&lt;&#x2F;span&gt;&lt;span&gt;48.8 	 45.426967757099156
&lt;&#x2F;span&gt;&lt;span&gt;113.0 	 99.98377278307227
&lt;&#x2F;span&gt;&lt;span&gt;48.7 	 52.246568385345796
&lt;&#x2F;span&gt;&lt;span&gt;40.3 	 38.607367128852516
&lt;&#x2F;span&gt;&lt;span&gt;59.6 	 76.11517058420904
&lt;&#x2F;span&gt;&lt;span&gt;152.8 	 147.72097718079874
&lt;&#x2F;span&gt;&lt;span&gt;73.4 	 161.360178437292
&lt;&#x2F;span&gt;&lt;span&gt;21.3 	 59.066169013592436
&lt;&#x2F;span&gt;&lt;span&gt;55.6 	 48.83676807122248
&lt;&#x2F;span&gt;&lt;span&gt;194.5 	 123.85237498193551
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;error&quot;&gt;5.6. How good is our model:&lt;&#x2F;h2&gt;
&lt;p&gt;We need to able to measure how good our model is. Among the methods available to achieve this task, let&#x27;s use the most common and the most used: the &lt;a href=&quot;#&quot;&gt;Root mean squared error&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rmse&quot;&gt;RMSE:&lt;&#x2F;h3&gt;
&lt;p&gt;One way (the most common way?) to assess how well our model fits our data set is to calculate the Root Mean Squared Error. The RMSE is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the square root &lt;&#x2F;li&gt;
&lt;li&gt;of the mean &lt;&#x2F;li&gt;
&lt;li&gt;of the square of all of the errors&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s write a function to calculate the RMSE:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;rmse(actual: t.Sequence[float], predicted: t.Sequence[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    sum_error = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(actual)):
&lt;&#x2F;span&gt;&lt;span&gt;        prediction_error = predicted[i] - actual[i]
&lt;&#x2F;span&gt;&lt;span&gt;        sum_error += prediction_error**&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span&gt;    mean_error = sum_error &#x2F; float(len(actual))
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;math.sqrt(mean_error)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we develop mutliple models, and we want to verify which one performs better:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Calculate the RMSE value for each model&lt;&#x2F;li&gt;
&lt;li&gt;The lower the RMSE value, the better the model. &lt;&#x2F;li&gt;
&lt;li&gt;A RMSE value of 0 indicate a perfect fit. &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The data set we&#x27;re working with has a range: [Y_min, Y_max]. This range is important in determining whether a given RMSE value is &amp;quot;low&amp;quot; or &amp;quot;high&amp;quot;. There is no &amp;quot;good&amp;quot; or no &amp;quot;bad&amp;quot; RMSE value. It always depends on the range of the data set we&#x27;re working with.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;normalized-rmse&quot;&gt;Normalized RMSE:&lt;&#x2F;h3&gt;
&lt;p&gt;The NRMSE is the RMSE divided by Y_max - Y_min. The result will be between 0 and 1, where values closer to 0 represent better fitting models. The normalization facilitates the comparison between data sets with different scales:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;rmse(
&lt;&#x2F;span&gt;&lt;span&gt;    actual: t.Sequence[float], predicted: t.Sequence[float]
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;    mean_error = sum([(predicted[i] - actual[i])**&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(actual))]) &#x2F; float(len(actual))
&lt;&#x2F;span&gt;&lt;span&gt;    rmse = math.sqrt(mean_error)
&lt;&#x2F;span&gt;&lt;span&gt;    nrmse = rmse &#x2F; (max(predicted) - min(predicted))
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;rmse, nrmse
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; python3 script.py 
&lt;&#x2F;span&gt;&lt;span&gt;The RMSE is 23.27666203730159
&lt;&#x2F;span&gt;&lt;span&gt;Normalized RMSE is 0.06371542339113609
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;final-plot&quot;&gt;5.7. Regression line:&lt;&#x2F;h2&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;0b1b498c76badfb400.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;class&quot;&gt;The complete program:&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;math
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;random
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;requests  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;matplotlib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;mpl  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;matplotlib.pyplot &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;plt  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pathlib
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;dataclasses &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;dataclass, field
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# setup plots
&lt;&#x2F;span&gt;&lt;span&gt;fig: mpl.figure.Figure
&lt;&#x2F;span&gt;&lt;span&gt;ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;fig, ax = plt.subplots()
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_xlabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;X-coordinates &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_ylabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Y-coordinates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_title(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Graphical representation of our points&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.grid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;splits = t.Tuple[
&lt;&#x2F;span&gt;&lt;span&gt;    t.Collection[float], t.Collection[float], t.Collection[float], t.Collection[float]
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@dataclass
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;SimpleLinearRegression:
&lt;&#x2F;span&gt;&lt;span&gt;    filename: t.Union[pathlib.Path, str] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;dataset.txt&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    __X: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    __Y: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    X_train: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    Y_train: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    X_test: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    Y_test: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__post_init__(self) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;open(self.filename, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;r&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;f:
&lt;&#x2F;span&gt;&lt;span&gt;            slines = [
&lt;&#x2F;span&gt;&lt;span&gt;                line.strip().split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;[li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;f.readlines()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:]]
&lt;&#x2F;span&gt;&lt;span&gt;            ]
&lt;&#x2F;span&gt;&lt;span&gt;            nlines = [(float(x), float(y)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;slines]
&lt;&#x2F;span&gt;&lt;span&gt;            self.__X, self.__Y = zip(*nlines)
&lt;&#x2F;span&gt;&lt;span&gt;            self.__split_train_test()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;scatter_plot(self, ax: mpl.axes.Axes, color: str = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;red&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, label=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        ax.scatter(self.__X, self.__Y, color=color, label=label)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;line_plot(self, ax: mpl.axes.Axes) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        b, a = self.estimate_coefficients()
&lt;&#x2F;span&gt;&lt;span&gt;        x = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;130&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        y = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;x]
&lt;&#x2F;span&gt;&lt;span&gt;        ax.plot(x, y, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;green&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__mean(self, lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum(lst) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__var(self, lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;        m = self.__mean(lst)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum([(x - m) ** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;lst]) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__cov(self, X: t.Sequence[float], Y: t.Sequence[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;        mean_x = self.__mean(X)
&lt;&#x2F;span&gt;&lt;span&gt;        mean_y = self.__mean(Y)
&lt;&#x2F;span&gt;&lt;span&gt;        covar = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(X)):
&lt;&#x2F;span&gt;&lt;span&gt;            covar += (X[i] - mean_x) * (Y[i] - mean_y)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;covar &#x2F; len(X)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__split_train_test(self, frac: float = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.2&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        indexes = list(range(len(self.__X)))
&lt;&#x2F;span&gt;&lt;span&gt;        indexes_test = set(random.sample(indexes, int(frac * len(self.__X))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 20% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;        self.X_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;        self.Y_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 80% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;        self.X_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;        self.Y_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;estimate_coefficients(
&lt;&#x2F;span&gt;&lt;span&gt;        self,
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;        mean_x, mean_y = self.__mean(self.X_train), self.__mean(self.Y_train)
&lt;&#x2F;span&gt;&lt;span&gt;        b1 = self.__cov(self.X_train, self.Y_train) &#x2F; self.__var(  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span&gt;            self.X_train
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;        b0 = mean_y - b1 * mean_x
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;b0, b1
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;rmse(self) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;        b, a = self.estimate_coefficients()
&lt;&#x2F;span&gt;&lt;span&gt;        predicted = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self.X_test]
&lt;&#x2F;span&gt;&lt;span&gt;        actual = self.Y_test
&lt;&#x2F;span&gt;&lt;span&gt;        mean_error = sum(
&lt;&#x2F;span&gt;&lt;span&gt;            [(predicted[i] - actual[i]) ** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(actual))]  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span&gt;        ) &#x2F; float(
&lt;&#x2F;span&gt;&lt;span&gt;            len(actual)
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;        rmse = math.sqrt(mean_error)
&lt;&#x2F;span&gt;&lt;span&gt;        nrmse = math.sqrt(mean_error) &#x2F; (max(predicted) - min(predicted))
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;rmse, nrmse
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# program entry point
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;main() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        model = SimpleLinearRegression()
&lt;&#x2F;span&gt;&lt;span&gt;        model.scatter_plot(ax)
&lt;&#x2F;span&gt;&lt;span&gt;        model.line_plot(ax)
&lt;&#x2F;span&gt;&lt;span&gt;        b, a = model.estimate_coefficients()
&lt;&#x2F;span&gt;&lt;span&gt;        rmse, nrmse = model.rmse()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The slope is &lt;&#x2F;span&gt;&lt;span&gt;{a}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, the intercept is &lt;&#x2F;span&gt;&lt;span&gt;{b}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The RMSE and NRMSE are: &lt;&#x2F;span&gt;&lt;span&gt;{rmse}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; and &lt;&#x2F;span&gt;&lt;span&gt;{nrmse}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        plt.show()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    main()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;The slope is 3.426108589853597, the intercept is 20.478117458572427
&lt;&#x2F;span&gt;&lt;span&gt;The RMSE and NRMSE are: 27.82841276749733 and 0.07520791645397
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;statistics&quot;&gt;Another solution, using the statistics module:&lt;&#x2F;h1&gt;
&lt;p&gt;Before jumping to big and powerful libraries such as &lt;a href=&quot;https:&#x2F;&#x2F;numpy.org&#x2F;doc&#x2F;stable&#x2F;reference&#x2F;routines.statistics.html&quot;&gt;NumPy&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.scipy.org&#x2F;doc&#x2F;scipy&#x2F;reference&#x2F;stats.html&quot;&gt;SciPy&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pandas-dev&#x2F;pandas&quot;&gt;Pandas&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;raphaelvallat&#x2F;pingouin&quot;&gt;Pingouin&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;statsmodels&#x2F;statsmodels&quot;&gt;Statsmodel&lt;&#x2F;a&gt;, and all the others. We have to notice, Python provides us with a module named &lt;a href=&quot;https:&#x2F;&#x2F;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html&quot;&gt;statistics&lt;&#x2F;a&gt;. Even though the statistics module is not intended to be a competitor to the ones listed above, it&#x27;s interesting to see that inside, there is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.mean&quot;&gt;mean&lt;&#x2F;a&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.variance&quot;&gt;variance&lt;&#x2F;a&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.covariance&quot;&gt;covariance&lt;&#x2F;a&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;even a &lt;a href=&quot;https:&#x2F;&#x2F;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.linear_regression&quot;&gt;linear regression&lt;&#x2F;a&gt; function.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Our program will suddenly become shorter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;statistics &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;lestat
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# load dataset
&lt;&#x2F;span&gt;&lt;span&gt;X, Y = read_text(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dataset.txt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# extract coefficients
&lt;&#x2F;span&gt;&lt;span&gt;a, b = lestat.linear_regression(X, Y)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;code&quot;&gt;Source code:&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;a5n5GalczLsAAAAM&#x2F;relief-phew.gif&quot;&gt;&lt;em&gt;Phew&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;. All the cool devs today will share the source code via a Jupyter notebook stored on Github or on Colab. According to the &lt;a href=&quot;https:&#x2F;&#x2F;sfconservancy.org&#x2F;&quot;&gt;Software Freedom Conservancy&lt;&#x2F;a&gt;, we should all &lt;a href=&quot;https:&#x2F;&#x2F;sfconservancy.org&#x2F;GiveUpGitHub&#x2F;&quot;&gt;Give Up GitHub&lt;&#x2F;a&gt;. And as a free software advocate, I agree with them. The source code can be found &lt;a href=&quot;&#x2F;assets&#x2F;script.py&quot;&gt;here&lt;&#x2F;a&gt; and the data set &lt;a href=&quot;&#x2F;assets&#x2F;dataset.txt&quot;&gt;here&lt;&#x2F;a&gt;. You&#x27;re welcome.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;more-on-this-topic&quot;&gt;More on this topic:&lt;&#x2F;h1&gt;
&lt;p&gt;I really hope you&#x27;ve learned something, really. Talking about the whole subject won&#x27;t be possible in this tiny article. To dive deeper and learn even more, let me please recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;datasette&#x2F;&quot;&gt;Datasette&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;matplotlib.org&#x2F;&quot;&gt;Matplotlib&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;378&#x2F;&quot;&gt;Real programmers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.sciencedirect.com&#x2F;topics&#x2F;engineering&#x2F;root-mean-squared-error&quot;&gt;Root-Mean-Squared Error&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;posit.co&#x2F;&quot;&gt;RStudio is becoming Posit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;scikit-learn.org&#x2F;stable&#x2F;modules&#x2F;generated&#x2F;sklearn.linear_model.LinearRegression.html&quot;&gt;Ordinary least squares Linear Regression with scikit learn&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Scafold</title>
		<published>2022-07-24T00:00:00+00:00</published>
		<updated>2022-07-24T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/snips/scfldc/" type="text/html"/>
		<id>https://nskm.xyz/snips/scfldc/</id>
		<content type="html">&lt;p&gt;It&#x27;s been a very long time since I&#x27;ve written my first &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mk&#x2F;&quot;&gt;post&lt;&#x2F;a&gt; about the way I use make. Now that I&#x27;m reading it again, I realize I don&#x27;t even use Makefiles anymore. Since few years now, I use &lt;a href=&quot;https:&#x2F;&#x2F;tox.wiki&#x2F;en&#x2F;latest&#x2F;#basic-example&quot;&gt;Tox&lt;&#x2F;a&gt;, &lt;em&gt;too much Python development I guess&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I started &lt;em&gt;(again)&lt;&#x2F;em&gt; learning C programming, I had to write a simple Makefile for being able to easily and quickly build, install, remove my executables. The following is a Bash script I&#x27;ve created to bootstrap small C projects:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;GIT=`which git`
&lt;&#x2F;span&gt;&lt;span&gt;MSG=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;initial commit from $&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;USER&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt; on $(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;date&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;CURRENT_DIRECTORY=`pwd`
&lt;&#x2F;span&gt;&lt;span&gt;PROJECT_NAME=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;EXECUTABLE_NAME=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;2:-&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;kli}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;[[ -z &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;PROJECT_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; then
&lt;&#x2F;span&gt;&lt;span&gt;  echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Please add the name of the project&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  exit
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;[[ -d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CURRENT_DIRECTORY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&#x2F;${&lt;&#x2F;span&gt;&lt;span&gt;PROJECT_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; then
&lt;&#x2F;span&gt;&lt;span&gt;  echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The folder exists. Choose another name&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  exit
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# project tree
&lt;&#x2F;span&gt;&lt;span&gt;mkdir -p &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CURRENT_DIRECTORY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&#x2F;${&lt;&#x2F;span&gt;&lt;span&gt;PROJECT_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;{build,src,docs,include,lib,tests,data}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# clang format config ???
&lt;&#x2F;span&gt;&lt;span&gt;clang-format --style=llvm -dump-config &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CURRENT_DIRECTORY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&#x2F;${&lt;&#x2F;span&gt;&lt;span&gt;PROJECT_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.clang-format
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Makefile header
&lt;&#x2F;span&gt;&lt;span&gt;cat &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CURRENT_DIRECTORY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&#x2F;${&lt;&#x2F;span&gt;&lt;span&gt;PROJECT_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Makefile&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;SHELL := &#x2F;bin&#x2F;sh
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;EXECUTABLE := $&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;EXECUTABLE_NAME
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Makefile body
&lt;&#x2F;span&gt;&lt;span&gt;cat &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CURRENT_DIRECTORY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&#x2F;${&lt;&#x2F;span&gt;&lt;span&gt;PROJECT_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Makefile&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# https:&#x2F;&#x2F;matt.sh&#x2F;howto-c
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# where all bin will be moved for easy trying
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;BIN_DIR := $(shell echo $${HOME})&#x2F;bin
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# set build and source directories
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;BUILD_DIR := build
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;SRC_DIRS := src
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;LIBS := -lm -lpthread
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# all source files are .c files under source directory
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;SRCS := $(shell find $(SRC_DIRS) -name *.c)
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# all objects files are obtained from all the .c files in src directory
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# and placed under build directory with the o extension
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;OBJS := $(SRCS:%.c=$(BUILD_DIR)&#x2F;%.o)
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# deps are .d files, obtained from all the .o files in the build directory
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;DEPS := $(OBJS:.o=.d)
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# directories to include are all the directories under src directory
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;INC_DIRS := $(shell find $(SRC_DIRS) -type d)
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# add -I in front of each subdirectory under src directory
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;INC_FLAGS := $(addprefix -I,$(INC_DIRS))
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;#
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;CFLAGS ?= $(INC_FLAGS) -g -Wall -Wfatal-errors -Wpedantic -Wextra -Werror -Wshadow -std=c11 -MMD -MP -march=native
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;install: $(BUILD_DIR)&#x2F;$(EXECUTABLE) ## install prog
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	@echo &amp;quot;installing...&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	$(CP) $(BUILD_DIR)&#x2F;$(EXECUTABLE) $(BIN_DIR)
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$(BUILD_DIR)&#x2F;$(EXECUTABLE): $(OBJS) ## build executable
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	@echo &amp;quot;building executable file...&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	$(CC) $(OBJS) -o $@ $(LDFLAGS) $(LIBS)  # CC and LDFLAGS are predefined see make -p -f &#x2F;dev&#x2F;null
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$(BUILD_DIR)&#x2F;%.o: %.c clean ## build object files
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	@echo &amp;quot;building object files...&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	@$(MKDIR_P) $(dir $@)
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;    # $&amp;lt; evaluates to the first &amp;quot;prerequisite&amp;quot;, $@ evaluates to the &amp;quot;target&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	$(CC) $(CFLAGS) -c $&amp;lt; -o $@
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;format:
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	@echo &amp;quot;reformatting...&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	find . -iname *.h -o -iname *.c | xargs clang-format -style=file -i -fallback-style=none
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clean: ## delete build files
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	@echo &amp;quot;deleting old build...&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	@$(RM) -r $(BUILD_DIR)
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;	@$(RM) -r $(BIN_DIR)&#x2F;$(EXECUTABLE)
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# acts like include except that there is no error (not even a warning) if DEPS does not exists, sinclude is another name
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;-include $(DEPS)
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;# Meh :\
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;MKDIR_P ?= mkdir -p
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;CP ?= cp -r
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.PHONY: clean install help format
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# main source file
&lt;&#x2F;span&gt;&lt;span&gt;cat &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CURRENT_DIRECTORY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&#x2F;${&lt;&#x2F;span&gt;&lt;span&gt;PROJECT_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;src&#x2F;main.c&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;#include &amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;#include &amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;#include &amp;lt;getopt.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;#include &amp;lt;stdbool.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;#include &amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;#include &amp;lt;stdint.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;int main (int argc, char **argv) {
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;    printf(&amp;quot;Hello World.\n&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;    exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# git it
&lt;&#x2F;span&gt;&lt;span&gt;cd ${PROJECT_NAME}
&lt;&#x2F;span&gt;&lt;span&gt;${GIT} init -q .
&lt;&#x2F;span&gt;&lt;span&gt;${GIT} add --all .
&lt;&#x2F;span&gt;&lt;span&gt;${GIT} commit -m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span&gt;MSG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;991384ed29750d7900.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Yasnippet</title>
		<published>2022-07-24T00:00:00+00:00</published>
		<updated>2022-07-24T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/snips/ysnp/" type="text/html"/>
		<id>https://nskm.xyz/snips/ysnp/</id>
		<content type="html">&lt;p&gt;The following is a Yasnippet I&#x27;ve created to quickly insert &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&quot;&gt;getzola&lt;&#x2F;a&gt; front matters.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;# -*- mode: snippet -*-
&lt;&#x2F;span&gt;&lt;span&gt;# name: Zola header
&lt;&#x2F;span&gt;&lt;span&gt;# key: zheader
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# --
&lt;&#x2F;span&gt;&lt;span&gt;+++
&lt;&#x2F;span&gt;&lt;span&gt;title = &amp;quot;$1&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;date = ${2:`(format-time-string &amp;quot;%Y-%m-%d&amp;quot;)`}
&lt;&#x2F;span&gt;&lt;span&gt;updated = ${3:`(format-time-string &amp;quot;%Y-%m-%d&amp;quot;)`}
&lt;&#x2F;span&gt;&lt;span&gt;slug= $4
&lt;&#x2F;span&gt;&lt;span&gt;draft = true
&lt;&#x2F;span&gt;&lt;span&gt;[taxonomies]
&lt;&#x2F;span&gt;&lt;span&gt;  categories=  [${5:&amp;quot;Python&amp;quot;}]
&lt;&#x2F;span&gt;&lt;span&gt;  tags=  [&amp;quot;$6&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;+++
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;$0
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# More on this topic:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;I really hope you&amp;#39;ve learned something reading this article. Talking about the current subject won&amp;#39;t be possible in one tiny article. If you want to dive deeper and to learn even more, let me recommend the following links:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;- [Foo](#)
&lt;&#x2F;span&gt;&lt;span&gt;- [Bar](#)
&lt;&#x2F;span&gt;&lt;span&gt;- [Baz](#)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Wall of Fame</title>
		<published>2022-07-04T00:00:00+00:00</published>
		<updated>2022-07-04T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/wall/" type="text/html"/>
		<id>https://nskm.xyz/wall/</id>
		<content type="html">&lt;p&gt;Here it is, the Wall of Fame.&lt;&#x2F;p&gt;
&lt;div&gt;

    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Yasnippets_to_send_a_resume.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;42253e10466dfe8b00.png&quot; alt=&quot;foo&quot; title=&quot;Yasnippets to send a resume&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_a_core_dev_followed_me.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;c5f96244c3fcfa1600.jpg&quot; alt=&quot;foo&quot; title=&quot;a core dev followed me&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Playing_with_Quarto.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;d3adaadc2d0896de00.png&quot; alt=&quot;foo&quot; title=&quot;Playing with Quarto&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_PSF_member_yes.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;0711e2fe1980243a00.png&quot; alt=&quot;foo&quot; title=&quot;PSF member yes&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Django_donator.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;68e94e946a6d693000.png&quot; alt=&quot;foo&quot; title=&quot;Django donator&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Emacs_massive_find_replace.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;5ca345d748fa99e900.png&quot; alt=&quot;foo&quot; title=&quot;Emacs massive find replace&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_When_I_was_dealing_with_Paypox_wtf.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;4b4876c789fe48fe00.png&quot; alt=&quot;foo&quot; title=&quot;When I was dealing with Paypox wtf&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_PR_accepted_to_typeshed_repo.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;617599e33e3dc6a900.png&quot; alt=&quot;foo&quot; title=&quot;PR accepted to typeshed repo&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Taking_stance.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;eaa3b1da309d00cf00.png&quot; alt=&quot;foo&quot; title=&quot;Taking stance&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_ashwinvis_enjoyed_my_mypy_article.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;7deae9243539f9fb00.png&quot; alt=&quot;foo&quot; title=&quot;ashwinvis enjoyed my mypy article&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Dont_introduce_yourself.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;0b7ac3d107da77a000.png&quot; alt=&quot;foo&quot; title=&quot;Dont introduce yourself&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_You_are_your_own_timezone.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;7c195bee30d1eb0c00.jpg&quot; alt=&quot;foo&quot; title=&quot;You are your own timezone&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Why_I_dont_use_social.media.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;5c7704e5dbfeb79900.png&quot; alt=&quot;foo&quot; title=&quot;Why I dont use social.media&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Efficacite_de_la_creation.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;e0809a87251d10b200.png&quot; alt=&quot;foo&quot; title=&quot;Efficacite de la creation&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Konami_code.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;80fb05accfd2bc0900.png&quot; alt=&quot;foo&quot; title=&quot;Konami code&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Really_?.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;0fc506aa377f408100.png&quot; alt=&quot;foo&quot; title=&quot;Really ?&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Julien_Palard_reacted_to_my_toot.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;e94e3e24317ac35a00.png&quot; alt=&quot;foo&quot; title=&quot;Julien Palard reacted to my toot&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_kingbuzzman_reused_my_work.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;3e505438ef207cf400.png&quot; alt=&quot;foo&quot; title=&quot;kingbuzzman reused my work&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Gandi_API.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;98e3c7cbb27882b100.png&quot; alt=&quot;foo&quot; title=&quot;Gandi API&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_pycon_africa_speaker.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;085a9e855617ae7100.jpg&quot; alt=&quot;foo&quot; title=&quot;pycon africa speaker&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Never_knew_I_was_one_of_the_creators_of_Python_Idle.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;f336f3056f0b5f8b00.png&quot; alt=&quot;foo&quot; title=&quot;Never knew I was one of the creators of Python Idle&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_customized_Hugo_hermit_theme.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;858f48060de8a11000.png&quot; alt=&quot;foo&quot; title=&quot;customized Hugo hermit theme&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Rules_for_a_good_life.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;a9f8d58d51f90bf000.jpg&quot; alt=&quot;foo&quot; title=&quot;Rules for a good life&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_First_day_on_Mastodon.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;dcbcc18b334ede3200.png&quot; alt=&quot;foo&quot; title=&quot;First day on Mastodon&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_I_am_a_libertarian_leftist.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;bd25d17917a160f900.png&quot; alt=&quot;foo&quot; title=&quot;I am a libertarian leftist&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Current_status.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;869ed1677de17bbb00.jpg&quot; alt=&quot;foo&quot; title=&quot;Current status&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Python_release_meassages_are_the_bests.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;4f1369880b8baf1300.png&quot; alt=&quot;foo&quot; title=&quot;Python release meassages are the bests&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Playing_with_Git_hooks.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;e58df38eff0cff7c00.png&quot; alt=&quot;foo&quot; title=&quot;Playing with Git hooks&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Python_subprocess_example.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;6d4546d8cf0c676f00.png&quot; alt=&quot;foo&quot; title=&quot;Python subprocess example&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Hercules.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;1566971334eac9b300.png&quot; alt=&quot;foo&quot; title=&quot;Hercules&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Bash_aliases_and_functions.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;d6c8b580046b17e300.png&quot; alt=&quot;foo&quot; title=&quot;Bash aliases and functions&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_donkirby_reusing_my_work.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;a1bfe8012cc1ee1900.png&quot; alt=&quot;foo&quot; title=&quot;donkirby reusing my work&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Reading.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;01979b64d1383af300.jpg&quot; alt=&quot;foo&quot; title=&quot;Reading&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Djibril_being_grateful_to_me.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;e3618c1b0897b2d000.png&quot; alt=&quot;foo&quot; title=&quot;Djibril being grateful to me&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Proud_Emacs_Stackexchange_User.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;54a087731338c29100.png&quot; alt=&quot;foo&quot; title=&quot;Proud Emacs Stackexchange User&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Gnus_once_upon_a_time.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;57b9d8687395c08000.png&quot; alt=&quot;foo&quot; title=&quot;Gnus once upon a time&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Proud_Emacs_user.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;0c0a3fcf6419201100.jpg&quot; alt=&quot;foo&quot; title=&quot;Proud Emacs user&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_sqlite_select_as_CSV.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;5d75c827066e42f400.png&quot; alt=&quot;foo&quot; title=&quot;sqlite select as CSV&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Exploring_PyPolars.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;f00710112dabe0a600.png&quot; alt=&quot;foo&quot; title=&quot;Exploring PyPolars&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Mercurial_aliases.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;07d3fac5afd348dc00.png&quot; alt=&quot;foo&quot; title=&quot;Mercurial aliases&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Figthing_against_Mypy.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;d9f9ad2f8ef9d5dc00.png&quot; alt=&quot;foo&quot; title=&quot;Figthing against Mypy&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Time_to_upgrade_distribution.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;0407daaa04648a3900.png&quot; alt=&quot;foo&quot; title=&quot;Time to upgrade distribution&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Logilab_thanks_me_for_my_work.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;db9110178cea994a00.png&quot; alt=&quot;foo&quot; title=&quot;Logilab thanks me for my work&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_me.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;19ea85236f66096900.jpg&quot; alt=&quot;foo&quot; title=&quot;me&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;Body_laser_wtf?.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;04a7743eae61ffc700.png&quot; alt=&quot;foo&quot; title=&quot;&amp;#x2F;wof&amp;#x2F;pictures&amp;#x2F;Body laser wtf?&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Gandi_API_again.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;82c748dcb0d7389f00.png&quot; alt=&quot;foo&quot; title=&quot;Gandi API again&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Playing_with_Delta_Chat.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;07cb36200ebbabb400.png&quot; alt=&quot;foo&quot; title=&quot;Playing with Delta Chat&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_When_I_was_working_on_Vialegal.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;a1bddc8619ae78af00.png&quot; alt=&quot;foo&quot; title=&quot;When I was working on Vialegal&quot;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Writing</title>
		<published>2022-05-20T00:00:00+00:00</published>
		<updated>2022-05-20T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/blg/" type="text/html"/>
		<id>https://nskm.xyz/posts/blg/</id>
		<content type="html">&lt;p&gt;I often receive resumes from people looking for a job and asking me for help. To all of them I always ask: &amp;quot;Do you have a website ?&amp;quot;, &amp;quot;Do you write ?&amp;quot;. And most of the time, the answer is negative. &lt;&#x2F;p&gt;
&lt;p&gt;Writing skills are important because they allow the reader to get their first impression of who is the writer. For example: writing skills displayed in resume, cover letter email communications, website. In my humble opinion, if you&#x27;re looking for a job as a software engineer, you should have a tiny space on the internet. A space in which you write about what you experiment, what you code, what you build.&lt;&#x2F;p&gt;
&lt;p&gt;This article is an attempt to answer, why I think everybody (every software engineer)  should have a website. Or at least, why everybody should write. This article is also &lt;em&gt;kind of&lt;&#x2F;em&gt; a recap of a talk I gave for the &lt;a href=&quot;https:&#x2F;&#x2F;dit.sn&quot;&gt;Dakar Institute of Tecnology&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;fde5c4e65d5a81e700.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;some-reasons-for-you-to-start-writing&quot;&gt;&lt;u&gt;Some reasons for you to start writing: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;1-improve-your-knowledge-on-a-topic&quot;&gt;&lt;em&gt;1. Improve your knowledge on a topic&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You&#x27;ll often have to write about subjects that you are not familiar with, so finding quality sources quickly is a skill you&#x27;ll develop. Before you write a single word, you need to do your research about the topic you&#x27;re writing on. The more you do research, the more you find quality sources, the more you improve your knowledge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-organize-your-thoughts&quot;&gt;&lt;em&gt;2. Organize your thoughts&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can write down more than you can easily remember, so that your capacity to consider a number of ideas at the same time is broadened. Once those ideas are written down, you can move them around, change them. You can also reject those that are finally not good enough. You will stay with good, original clearly defined ideas. And you will be able to organize and communicate them easily. &lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-share-your-expertise-meet-fellow-specialist-and-grow-your-knowledge&quot;&gt;&lt;em&gt;3. Share your expertise, meet fellow specialist and grow your knowledge&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Knowledge is the only thing that grows when shared. Sharing your knowledge helps you grow your knowledge by doing research, synthesizing multiple and different viewpoints. Sharing your expertise means inviting people to read you, inviting people to a new conversation. A conversation is always an occasion to meet new people and to grow as a human.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-make-money&quot;&gt;&lt;em&gt;4. Make money&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Even professions that don&#x27;t focus on writing require written communication skills. The tech industry for example, is more and more looking for people who are able to write. Those writings include things like instruction manuals, user manuals, journal articles, product descriptions, memos, wikis, documentations, etc...&lt;&#x2F;p&gt;
&lt;p&gt;You can have a look :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.indeed.com&#x2F;q-Technical-Writer-jobs.html?vjk=1e9cd66778e25548&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.upwork.com&#x2F;freelance-jobs&#x2F;technical-writing&#x2F;&quot;&gt;then here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.glassdoor.com&#x2F;Job&#x2F;technical-writer-jobs-SRCH_KO0,16.htm&quot;&gt;here again&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;careers.google.com&#x2F;jobs&#x2F;results&#x2F;93728821645058758-technical-writer-google-cloud&#x2F;?distance=50&amp;amp;q=technical%20writer&quot;&gt;also  here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;By the way:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;realpython.com&#x2F;write-for-us&#x2F;&quot;&gt;Real Python is hiring&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;895695&#x2F;&quot;&gt;LWN is hiring too&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;disclaimer: I&#x27;m not paid by anybody to share those job offers&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;what-are-the-topic-to-write-about&quot;&gt;&lt;u&gt;What are the topic to write about: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Coming up with writing inspiration is tough. My advice would be, &lt;strong&gt;in all the cases, always write about something you really like, or something you really enjoy.&lt;&#x2F;strong&gt; As a technical writer, you can write different kinds of articles:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-story&quot;&gt;&lt;em&gt;1. Story&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Human beings are interested in stories about people. If your reader knows you a little through your blog, the reader will remember who you are and the reader will be more interested by your technical articles. &lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;ask&quot;&gt;Here&lt;&#x2F;a&gt; you&#x27;ll find different kinds of stories.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-opinion&quot;&gt;&lt;em&gt;2. Opinion&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Giving an opinion is a common way of interacting with other people. Of course you don&#x27;t simply share an opinion, you&#x27;ll also share the compelling and interesting argument that support this opinion. Also, please don&#x27;t spend your time attacking others people or spreading controversial ideas. Here is an &lt;a href=&quot;https:&#x2F;&#x2F;drewdevault.com&#x2F;2019&#x2F;12&#x2F;09&#x2F;Developers-shouldnt-distribute.html&quot;&gt;axample&lt;&#x2F;a&gt; of a shared opinion.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-how-tos&quot;&gt;&lt;em&gt;3. HOW-TOs&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;An how-to is a document providing detailed and practical step-by-step guide on how to do something. In a precise, step-by-step approach, you should walk your reader through the process. You should make sure your reader can reproduce the same results by following the provided steps.  &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;howto&#x2F;pyporting.html&quot;&gt;Example&lt;&#x2F;a&gt; of an HOWTO. &lt;&#x2F;p&gt;
&lt;!-- https:&#x2F;&#x2F;tldp.org&#x2F;HOWTO&#x2F;HOWTO-INDEX&#x2F;howtos.html --&gt;
&lt;!-- https:&#x2F;&#x2F;tldp.org&#x2F;HOWTO&#x2F;HOWTO-INDEX&#x2F;categories.html --&gt;
&lt;h2 id=&quot;4-how-something-work&quot;&gt;&lt;em&gt;4. How something work&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There are people &lt;em&gt;like me&lt;&#x2F;em&gt; who want to know how almost everything works. This kind of article is suitable when you want to deep dive into a very specific topic. For example, somebody already using Django sessions, may be suddenly wondering how does Django sessions work under the hood ? Here is an &lt;a href=&quot;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2011&#x2F;06&#x2F;24&#x2F;how-django-sessions-work-introduction&quot;&gt;article&lt;&#x2F;a&gt; showing how Django sessions work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-reviews&quot;&gt;&lt;em&gt;5. Reviews&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You have read, used, tested, played with something. In a review, your attempt will be to write about what was your experience. You&#x27;ll describe the thing, you&#x27;ll share what were your feelings about the thing, you&#x27;ll show the strengths and the weaknesses of the thing. Example of &lt;a href=&quot;https:&#x2F;&#x2F;emptysqua.re&#x2F;blog&#x2F;review-of-autotools-a-practitioners-guide&#x2F;&quot;&gt;review&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;identifying-the-target-audience&quot;&gt;&lt;u&gt;Identifying the target audience: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Identifying your intended audience will help you write effective content that achieves your goals. What are you writing ? Who are you writing for ? Knowing your audience will help you adapt your content accordingly. And if you don&#x27;t know who to write for, then the following is a serie of questions you can ask yourself:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Who am I writing for ?&lt;&#x2F;li&gt;
&lt;li&gt;What subject am I writing about ?&lt;&#x2F;li&gt;
&lt;li&gt;What does my audience already know about the subject?&lt;&#x2F;li&gt;
&lt;li&gt;What does my audience want to know about the subject?&lt;&#x2F;li&gt;
&lt;li&gt;What are the questions will my audience have?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;finding-the-audience&quot;&gt;&lt;u&gt;Finding the audience: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;For example, &lt;strong&gt;as a Python specialist&lt;&#x2F;strong&gt;, the audience can be found in different places. Pycoder weekly news want to hear from you about projects you are working on, conferences you are running, and articles you want to &lt;a href=&quot;https:&#x2F;&#x2F;pycoders.com&#x2F;submissions&quot;&gt;share&lt;&#x2F;a&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;Awesome Python is another newsletter who want you to &lt;a href=&quot;https:&#x2F;&#x2F;python.libhunt.com&#x2F;contribute&quot;&gt;contribute&lt;&#x2F;a&gt; links to blog posts, tutorials, libraries, events, videos, books. &lt;&#x2F;p&gt;
&lt;p&gt;You can als share your posts on &lt;a href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;&quot;&gt;Lobsters&lt;&#x2F;a&gt;, on &lt;a href=&quot;https:&#x2F;&#x2F;tilde.news&#x2F;&quot;&gt;Tilde News&lt;&#x2F;a&gt;, on &lt;a href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;&quot;&gt;dev.to&lt;&#x2F;a&gt;, on &lt;a href=&quot;https:&#x2F;&#x2F;towardsdatascience.com&#x2F;about&quot;&gt;towardsdatascience&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;improving-your-writing&quot;&gt;&lt;u&gt;Improving your writing: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The following is what I recommend. In all the cases, you should find what is best for you.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-practice&quot;&gt;&lt;em&gt;1. Practice&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The most effective writers write every day, &lt;em&gt;at least a bit&lt;&#x2F;em&gt;.  The more you write, the more your brain form connections between neurons. Those connections get stronger the more often you write. After some time and regular practice, you no longer have to think about it. This is when writing becomes a habit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-make-time&quot;&gt;&lt;em&gt;2. Make time&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Prepare to spend between 90 minutes and 3 hours writing. But hey, 15 minutes can be useful if you do it every day. Don&#x27;t fool yourself, thinking you&#x27;ll wait for a big chunk of free time to start. That will never happen. &lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-when&quot;&gt;&lt;em&gt;3. When&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You are much smarter and more resilient after you have slept properly and ate. Again, find what suits you best. According to some studies, creativity peaks in the morning. My experience tells me that&#x27;s true.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-frequency&quot;&gt;&lt;em&gt;4. Frequency&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Write only when you feel it.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;tools-for-writing-ssg&quot;&gt;&lt;u&gt;Tools for writing... SSG:&lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You should provide yourself with the right technology. Here again, I can tell you what I do, but there are plenty of differents tools, you &lt;a href=&quot;https:&#x2F;&#x2F;app.hackernoon.com&#x2F;signup&quot;&gt;should&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;pages.github.com&#x2F;&quot;&gt;always&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;jekyllrb.com&#x2F;&quot;&gt;find&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;substack.com&#x2F;for-bloggers&quot;&gt;what&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;write.as&#x2F;start&quot;&gt;suits&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.blogger.com&#x2F;about&#x2F;?bpli=1&quot;&gt;you&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;creators&quot;&gt;best&lt;&#x2F;a&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve choosen to build my website using a Static Site Generator (SSG). An ssg is a tool that generates a full static HTML website based on raw data (text files) and a set of templates (html, css, js files). :&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;9ce2d1b7dc4dc5e900.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;p style=&quot;text-align:center&quot;&gt; &lt;a href=&quot;https:&#x2F;&#x2F;devopedia.org&#x2F;static-site-generators&quot;&gt;Image source&lt;&#x2F;a&gt; &lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;why-ssg&quot;&gt;&lt;u&gt;Why SSG:&lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;No need for internet for writing, no need to login somewhere before writing.&lt;&#x2F;li&gt;
&lt;li&gt;no need for a particular environment, just a text editor, and a browser.&lt;&#x2F;li&gt;
&lt;li&gt;No vendor lock in, no dependency on any product for writing or migrating your content.&lt;&#x2F;li&gt;
&lt;li&gt;No need for a program to dynamically generate webpages. Web pages load faster.&lt;&#x2F;li&gt;
&lt;li&gt;No dependencies running on the server, just a web server. Increased security&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;i-m-convinced-can-you-show-me-an-example-please&quot;&gt;&lt;u&gt;I&#x27;m convinced, can you show me an example please:&lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;blg&#x2F;&quot;&gt;article&lt;&#x2F;a&gt; you&#x27;re reading right now, was generated from a &lt;a href=&quot;https:&#x2F;&#x2F;bin.nskm.xyz&#x2F;pastes&#x2F;markdown.md&quot;&gt;markdown file&lt;&#x2F;a&gt; using an SSG named &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; and a theme named &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;barlog-m&#x2F;oceanic-zen&quot;&gt;Oceanic Zen&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;To finish this article, I would like to quote &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Leslie_Lamport&quot;&gt;Leslie Lamport&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;If you’re thinking without writing, you only think you’re thinking.&amp;quot;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;— Leslie Lamport&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;h1 id=&quot;links&quot;&gt;Links:&lt;&#x2F;h1&gt;
&lt;p&gt;To learn more on this topic, I strongly recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yieldcode.blog&#x2F;post&#x2F;why-engineers-should-write&#x2F;&quot;&gt;Why engineers should focus on writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=RnY5iJea5ww&amp;amp;t=77s&quot;&gt;Think and write, with Leslie Lamport&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=HOXwDWCoqQg&quot;&gt;Jordan Peterson on the importance of reading and writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=vyVpRiqOvt4&quot;&gt;How writing online made me a millionaire&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=tod1sraj8we&quot;&gt;How to improve your clarity of thought (&amp;quot;writing is thinking&amp;quot;)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=fxLFjOa-9UY&quot;&gt;Programmers that don&#x27;t blog should start right now&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=p8dve3MqQW4&quot;&gt;Benefits of writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=mmU25Xd0BGs&quot;&gt;Technical blogging for Python programmers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=aTgPJQ9Dy7Q&quot;&gt;Look deeper -- write -- the wonders of writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=t4vKPhjcMZg&quot;&gt;What nobody tells you about documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Verba_volant,_scripta_manent&quot;&gt;Spoken words fly away, written words remain&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Circadian_rhythm&quot;&gt;Circadian rythm&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;links-again&quot;&gt;Links again:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;jamstack.org&#x2F;generators&#x2F;&quot;&gt;Static Site Generators&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;blog&#x2F;2022&#x2F;04&#x2F;18&#x2F;comparing-static-site-generators&#x2F;&quot;&gt;How to choose the right static site generator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola, your one-stop static site engine&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;getpublii.com&#x2F;&quot;&gt;Publii, Static Site Generator with GUI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;&quot;&gt;Hugo, the world’s fastest framework for building websites&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;orbifx&#x2F;logarion&quot;&gt;Logarion, a suite of tools, for discovering, collecting &amp;amp; exchanging texts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;even-more-links&quot;&gt;Even more links:&lt;&#x2F;h1&gt;
&lt;p&gt;Things that were discussed during the talk:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Literate_programming&quot;&gt;Literate programming&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=Mr3WTR0a5SM&quot;&gt;Knuth on Literate Programming&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;orgmode.org&#x2F;worg&#x2F;org-contrib&#x2F;babel&#x2F;&quot;&gt;Babel: active code in Org-mode&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;&quot;&gt;Pandoc, a universal document converter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;quarto.org&#x2F;&quot;&gt;Quarto, open-source scientific and technical publishing system built on Pandoc&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!-- https:&#x2F;&#x2F;www.maestralsolutions.com&#x2F;m&#x2F;u&#x2F;2020&#x2F;10&#x2F;SSG-1.png --&gt;
&lt;!-- https:&#x2F;&#x2F;uploads.toptal.io&#x2F;blog&#x2F;image&#x2F;126943&#x2F;toptal-blog-image-1534876856505-558f1c71902d47812f218825d358fe4b.png --&gt;
&lt;!-- https:&#x2F;&#x2F;devopedia.org&#x2F;images&#x2F;article&#x2F;78&#x2F;1631.1525880749.png --&gt;
&lt;!-- https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20170603045917&#x2F;http:&#x2F;&#x2F;vasc.ri.cmu.edu:80&#x2F;old_help&#x2F;Programming&#x2F;Literate&#x2F;literate.html --&gt;
&lt;br&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;731fe52f2aaf4be400.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;!-- Love the article, nicely written. I do think it&#x27;s such a shame that writing well isn&#x27;t taught alongside software engineering. --&gt;
&lt;!-- I&#x27;d even go so far to say that having a good writer can make or break a team - someone who is able to structure everyone&#x27;s collective knowledge, and make it easy to access and understand. Someone who ties the team together through past and future. --&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Function pointers</title>
		<published>2022-04-29T16:15:50+00:00</published>
		<updated>2022-04-29T16:15:50+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/fp/" type="text/html"/>
		<id>https://nskm.xyz/posts/fp/</id>
		<content type="html">&lt;p&gt;In Python, we say, functions are &lt;em&gt;first class citizen&lt;&#x2F;em&gt;. This means, functions can be used like any other objects. They can be stored inside variables, they can be passed as argument to a function, they can be returned from a function. The following is a very basic example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;square = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;lambda &lt;&#x2F;span&gt;&lt;span&gt;x: x * x
&lt;&#x2F;span&gt;&lt;span&gt;cube = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;lambda &lt;&#x2F;span&gt;&lt;span&gt;x: x * x * x
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;operations = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: square, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;: cube}
&lt;&#x2F;span&gt;&lt;span&gt;choice = int(input(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Square (1) or Cube (2) ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;value = int(input(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;print(operations[choice](value))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s start with a very simple function to print out a simple &amp;quot;hello world&amp;quot; using a function pointer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; defining a function ptr
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a function taking no argument and returning nothing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello world!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; make our function pointer points to greet function
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; call greet function via the function pointer
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;slowly-please&quot;&gt;&lt;strong&gt;Slowly please?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The first interesting line is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We&#x27;re defining a &lt;em&gt;pointer to a function&lt;&#x2F;em&gt;, named &lt;strong&gt;greet_ptr&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;re using the &lt;strong&gt;*&lt;&#x2F;strong&gt; notation to signify that it is a pointer.&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should receive no argument: &lt;strong&gt;()&lt;&#x2F;strong&gt; &lt;&#x2F;li&gt;
&lt;li&gt;The function should return nothing: &lt;strong&gt;void&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We need parenthesis, otherwise it becomes &lt;strong&gt;void *greet_ptr()&lt;&#x2F;strong&gt;, a function returning a &lt;strong&gt;void pointer.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;p&gt;The next interesting lines are:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;greet_ptr&lt;&#x2F;code&gt; is a pointer, so it should receive &lt;em&gt;the address&lt;&#x2F;em&gt; of a function.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;greet&lt;&#x2F;code&gt; is a function, taking no argument, and returning void.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;greet_ptr()&lt;&#x2F;code&gt;: let&#x27;s execute the code living at the address stored by greet_ptr.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;what-if-the-function-pointed-to-takes-arguments&quot;&gt;&lt;strong&gt;What if the function pointed to, takes arguments?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Simple example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; defining a function ptr
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; make our function pointer points to greet function
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; call greet function via the function pointer
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The first interesting line is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We&#x27;re defining a pointer to a function, named &lt;strong&gt;greet_ptr&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;re using the &lt;strong&gt;*&lt;&#x2F;strong&gt; notation to signify that it is a pointer.&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should take one argument of type char pointer &lt;strong&gt;(char *)&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should return nothing: &lt;strong&gt;void&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We need parenthesis, otherwise it becomes &lt;strong&gt;void *greet_ptr(char *)&lt;&#x2F;strong&gt;, a function taking a string and returning a &lt;strong&gt;void pointer.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;p&gt;The next interesting lines are:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;greet_ptr still points to greet function.&lt;&#x2F;li&gt;
&lt;li&gt;let&#x27;s execute the code living at the address stored by greet_ptr.&lt;&#x2F;li&gt;
&lt;li&gt;This executable, &lt;code&gt;greet&lt;&#x2F;code&gt; is waiting for a parameter of type &lt;code&gt;char *&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;So the parameter &lt;code&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;code&gt; will be passed to the function &lt;code&gt;greet&lt;&#x2F;code&gt; before execution.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;what-is-the-address-of-a-function&quot;&gt;&lt;strong&gt;What is the address of a function?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Before going further, we have to keep one thing in mind. &lt;strong&gt;a function name (label) is the address of the function.&lt;&#x2F;strong&gt; Yes. A &lt;code&gt;function name (label)&lt;&#x2F;code&gt; is converted to a &lt;code&gt;pointer to itself&lt;&#x2F;code&gt;. This means that function names can be assigned to a function pointer without using &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; to pass an address. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;hello_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;  hello_ptr = greet; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; notice, there is no &amp;amp;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(greet_ptr == hello_ptr)
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Pointers containing the same address.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  hello_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;function-pointers-as-arguments&quot;&gt;&lt;strong&gt;Function pointers as arguments?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Remember, a function name (label) is converted to a pointer to itself, so it can be passed whenever we need a function pointer. So, we can write function taking function pointers as arguments. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;sayHello(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;sayHi(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hey &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a function that takes a function and a string as parameters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fctPtr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name) {
&lt;&#x2F;span&gt;&lt;span&gt;  fctPtr(name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greetBar(){
&lt;&#x2F;span&gt;&lt;span&gt;  greet(sayHello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main () {
&lt;&#x2F;span&gt;&lt;span&gt;  greet(sayHello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  greet(sayHi, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;baz&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  greetBar();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The first interesting lines are:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fctPtr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name) {
&lt;&#x2F;span&gt;&lt;span&gt;  fctPtr(name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We&#x27;re defining a function, named &lt;code&gt;greet&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;greet&lt;&#x2F;code&gt;  function takes 2 arguments:
&lt;ol&gt;
&lt;li&gt;a function pointer: &lt;code&gt;void (*fctPtr)(char *)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;a char pointer: &lt;code&gt;char *name&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should be called with an argument of type &lt;code&gt;char *&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to is then called: &lt;code&gt;fctPtr(name)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;p&gt;The next interesting line is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;greet(sayHello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;sayHello&lt;&#x2F;code&gt; is a function name (label)
&lt;ol&gt;
&lt;li&gt;that will be converted to a pointer to itself.&lt;&#x2F;li&gt;
&lt;li&gt;then, that pointer will be passed to &lt;code&gt;greet&lt;&#x2F;code&gt; function.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;The function &lt;code&gt;sayHello&lt;&#x2F;code&gt; will be called with &lt;code&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;code&gt; as parameter.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;we-can-also-use-function-pointers-as-return-values&quot;&gt;&lt;strong&gt;We can also use function pointers as return values.&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We &lt;em&gt;already&lt;&#x2F;em&gt; know a pointer can be returned from a function. A function pointer, &lt;em&gt;is&lt;&#x2F;em&gt; a &lt;em&gt;pointer&lt;&#x2F;em&gt;, so there is no big deal here. &lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;the-original-python-example-in-c&quot;&gt;&lt;strong&gt;The original Python example in C?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;square (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;x) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; x;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;cube (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;x) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; x;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main () {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; choice, value;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; an array of pointers to functions
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; those functions should take an int and return an int
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fp[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) = {square, cube};
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Square (1) or Cube (2) ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  scanf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;choice);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  scanf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;value);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fp[choice-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;])(value));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;any-real-life-examples&quot;&gt;&lt;strong&gt;Any real life examples?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Function pointers gives C programmers, &lt;strong&gt;first-class citizen&lt;&#x2F;strong&gt;  &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;First-class_function&quot;&gt;functionality&lt;&#x2F;a&gt;: being able to pass functions as argument to other functions, and being able to return functions as value from other functions. &lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;more-on-the-topic&quot;&gt;&lt;strong&gt;More on the topic:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;10758811&#x2F;c-syntax-for-functions-returning-function-pointers&#x2F;10759352#10759352&quot;&gt;C syntax for functions returning function pointers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>My journey to type checking 7521 lines of Python</title>
		<published>2021-11-08T03:40:17+00:00</published>
		<updated>2021-11-08T03:40:17+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/stcmp2/" type="text/html"/>
		<id>https://nskm.xyz/posts/stcmp2/</id>
		<content type="html">&lt;p&gt;I&#x27;ve spent the last couple of months adding &lt;a href=&quot;http:&#x2F;&#x2F;mypy-lang.org&#x2F;&quot;&gt;type hints&lt;&#x2F;a&gt; to the &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;merge_requests?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=all&amp;amp;author_username=nsukami&quot;&gt;RQL package&lt;&#x2F;a&gt;. In the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;stcmp&#x2F;&quot;&gt;first&lt;&#x2F;a&gt; part, I talked you &lt;strong&gt;the reasons&lt;&#x2F;strong&gt; I think Mypy may be useful. In this part, I&#x27;ll talk about the &lt;strong&gt;process I&#x27;ve followed&lt;&#x2F;strong&gt; for adding type annotations to RQL.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recap-of-the-first-part&quot;&gt;Recap of the first part:&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Type hints are mainly useful for the &lt;a href=&quot;https:&#x2F;&#x2F;hynek.me&#x2F;talks&#x2F;python-foss&#x2F;&quot;&gt;maintainers&lt;&#x2F;a&gt;, &lt;strong&gt;&lt;em&gt;the human readers&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; of &lt;strong&gt;&lt;em&gt;large code bases&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. The  people who &lt;strong&gt;read&lt;&#x2F;strong&gt; and &lt;strong&gt;debug&lt;&#x2F;strong&gt; and &lt;strong&gt;maintain&lt;&#x2F;strong&gt; large software systems &lt;strong&gt;they did not write&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The major benefit for you won&#x27;t be fewer bugs or unit tests, but the ability to more easily read and reason about code written by someone else.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;h2 id=&quot;outline&quot;&gt;Outline:&lt;&#x2F;h2&gt;
&lt;p&gt;First, I&#x27;ll talk about what &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#mypy&quot;&gt;Mypy&lt;&#x2F;a&gt; is and what should be it&#x27;s initial &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#initial-setup&quot;&gt;setup&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Secondly, I&#x27;ll briefly show you how I deconstructed the project (&lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#import-structure&quot;&gt;import structure&lt;&#x2F;a&gt; &amp;amp; &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#classes-hierarchy&quot;&gt;classes hierarchy&lt;&#x2F;a&gt;) to have another perspective of how the project is built.&lt;&#x2F;p&gt;
&lt;p&gt;I will also show 3 different ways to &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#type-hints-generation&quot;&gt;generate&lt;&#x2F;a&gt; type annotations and &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#type-information-inline-or-via-stubs&quot;&gt;where&lt;&#x2F;a&gt; I think those type annotations should reside.&lt;&#x2F;p&gt;
&lt;p&gt;Finaly, I&#x27;ll talk about things that still need to be &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#improvements&quot;&gt;improved&lt;&#x2F;a&gt;. Mainly, the use of &lt;code&gt;Any&lt;&#x2F;code&gt; and &lt;code&gt;type:ignore&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to jump straight to the part that&#x27;s most interesting.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;mypy&quot;&gt;Mypy:&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;existing_code.html#using-mypy-with-an-existing-codebase&quot;&gt;Mypy&lt;&#x2F;a&gt; is a library that provides optional static type checking. Unlike other programming languages, where the static type-checking takes place at compilation time, Mypy CLI does the type-check on-demand. At Logilab, the type-check was done, locally when developing, but also in the Continuous Integration pipeline, using Gitlab and Tox.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;initial-setup&quot;&gt;Initial setup:&lt;&#x2F;h2&gt;
&lt;p&gt;We need to ensure that Mypy is really being run everywhere it should be and everytime someone pushes code. We don&#x27;t want to spend time applying type annotations that won&#x27;t be checked. If you don&#x27;t check type annotations on a regular basis, they may become wrong after a certain period of time. That means:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-configuring-mypy&quot;&gt;1. Configuring Mypy&lt;&#x2F;h3&gt;
&lt;p&gt;Configuration is done using a &lt;code&gt;mypy.ini&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;532de9f4788887a4c5ff315ad9a515033979c822&#x2F;mypy.ini&quot;&gt;file&lt;&#x2F;a&gt;. At the begining, we do not want strict typing checks. Then, we&#x27;ll try to work towards more strigency, for example: &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;command_line.html#disallow-dynamic-typing&quot;&gt;dissallowing dynamic typing&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;command_line.html#untyped-definitions-and-calls&quot;&gt;disallowing untyped definitions&lt;&#x2F;a&gt;. We&#x27;re working with a legacy code base with no type definitions, let&#x27;s start with more relaxed options.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-ignoring-external-libraries&quot;&gt;2. Ignoring external libraries:&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve done it many weeks later, but I could have done it right from the beginning: tell Mypy to &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;commit&#x2F;66c3196a4d2925183b6f6c943f6368943c3e4522&quot;&gt;ignore&lt;&#x2F;a&gt; missing type hints from &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;running_mypy.html#missing-type-hints-for-third-party-library&quot;&gt;external libraries&lt;&#x2F;a&gt;. Maybe in another phase, we&#x27;ll annotate them, but for now, they should be ignored.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-set-a-tox-environment-and-ci-job&quot;&gt;3. Set a Tox environment and CI job:&lt;&#x2F;h3&gt;
&lt;p&gt;Add Tox environment to automate the boring stuff and reduce the &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;tox.ini#L44&quot;&gt;boilerplate&lt;&#x2F;a&gt;. And add a Gitlab CI &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;.gitlab-ci.yml#L39&quot;&gt;job&lt;&#x2F;a&gt;. that will be in charge of running Mypy every time a new changeset is sent to the Gitlab server.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;import-structure&quot;&gt;Import structure&lt;&#x2F;h2&gt;
&lt;p&gt;I thought a diagram showing the import structure would help me understand the project. I also thought making a graph of the RQL&#x27;s import structure would help me add types a bit faster. My idea was to add annotations from bottom to top. I was wrong. More than once, after adding type annotations to a module, I was obliged to go back to where it was already done. For example, method &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;common_issues.html#incompatible-overrides&quot;&gt;overrides&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;thebjorn&#x2F;pydeps&quot;&gt;PyDeps&lt;&#x2F;a&gt; is the module dependency visualization I used, the result being:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;import_structure2.svg&quot; alt=&quot;&quot; title=&quot;Right click &amp;amp; Open in new tab for better view&quot; &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you open the diagram in another tab, you&#x27;ll notice that we can see external libraries too, for example: &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;open-source&#x2F;logilab-database&quot;&gt;logilab-database&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;smurfix&#x2F;yapps&quot;&gt;yapps&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pygments&#x2F;pygments&quot;&gt;pygments&lt;&#x2F;a&gt;. Those are the ones that need to be ignored during type checking.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;classes-hierachy&quot;&gt;Classes hierachy:&lt;&#x2F;h2&gt;
&lt;p&gt;Within &lt;a href=&quot;https:&#x2F;&#x2F;pylint.org&#x2F;&quot;&gt;Pylint&lt;&#x2F;a&gt;, there is a tool named &lt;a href=&quot;https:&#x2F;&#x2F;www.logilab.org&#x2F;blogentry&#x2F;6883&quot;&gt;Pyreverse&lt;&#x2F;a&gt; that analyses Python code and extracts UML class diagrams and package dependencies. Using Pyreverse, we can have a clear view of all the classes and the relation between them:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;classes_RQL2.svg&quot; alt=&quot;&quot; title=&quot;Right click &amp;amp; Open in new tab for better view&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;type-hints-addition&quot;&gt;Type hints addition:&lt;&#x2F;h2&gt;
&lt;p&gt;There are different options for adding type annotations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-manual&quot;&gt;1. Manual&lt;&#x2F;h3&gt;
&lt;p&gt;We can do it manually: finding what are the types flowing through our program, &lt;em&gt;I&#x27;ve been there, it&#x27;s painful&lt;&#x2F;em&gt;. Literally:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Adding breakpoints here and there&lt;&#x2F;li&gt;
&lt;li&gt;Running the function or running the tests&lt;&#x2F;li&gt;
&lt;li&gt;Once inside PDB, asking the &lt;code&gt;type&lt;&#x2F;code&gt; function to tell me who is who&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;  
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;73&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;g(x):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     breakpoint()
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     x[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# a long list of non understandable code
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;y
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;76&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# let&amp;#39;s assume we launched the tests and somewhere, g is called
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;77&lt;&#x2F;span&gt;&lt;span&gt;]: g([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;72&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;38&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;34&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;-ef8444a3ab59&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)g()
&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; x[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) type(x)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# please, what is the type of the parameter x?
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;list&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) n
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;-ef8444a3ab59&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)g()
&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) n
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;-ef8444a3ab59&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)g()
&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;y
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) type(y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# please, what is the type of the returned value?
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;int&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;After that first run, we may be temped to write our function like one that takes a list and returns an integer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# g takes a list and return an integer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;81&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;g(x: list) -&amp;gt; int:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     x[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# a long list of non understandable code
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;y
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;I said &lt;em&gt;&amp;quot;temped&amp;quot;&lt;&#x2F;em&gt; because, maybe the function takes a dictionary and returns an integer. Only an extensive set of tests will tell us what&#x27;s the best answer.&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-reveal&quot;&gt;2. Reveal:&lt;&#x2F;h3&gt;
&lt;p&gt;I never really use them, but another option is to use &lt;code&gt;reveal_type&lt;&#x2F;code&gt; or &lt;code&gt;reveal_locals&lt;&#x2F;code&gt;  &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;latest&#x2F;common_issues.html#displaying-the-type-of-an-expression&quot;&gt;functions&lt;&#x2F;a&gt;. You just put a &lt;code&gt;reveal_type(expr)&lt;&#x2F;code&gt; in the code, and run it with Mypy. I never really use those 2 functions because most of the time, the revealed type is &lt;code&gt;Any&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;reveal.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-pyannotate&quot;&gt;3. PyAnnotate:&lt;&#x2F;h3&gt;
&lt;p&gt;The third &lt;em&gt;and really helpful&lt;&#x2F;em&gt; option I want to suggest is, using a tool that will give you an &lt;strong&gt;exhaustive list of suggestions&lt;&#x2F;strong&gt;, for example PyAnnotate. &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dropbox&#x2F;pyannotate&quot;&gt;PyAnnotate&lt;&#x2F;a&gt; will help you list all the &lt;strong&gt;call arguments and all the return types observed at runtime&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Similar projects exists, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Instagram&#x2F;MonkeyType&quot;&gt;MonkeyType&lt;&#x2F;a&gt; created by Instagram. &lt;a href=&quot;https:&#x2F;&#x2F;google.github.io&#x2F;pytype&#x2F;&quot;&gt;Pytype&lt;&#x2F;a&gt; from Google. And &lt;a href=&quot;https:&#x2F;&#x2F;pyre-check.org&#x2F;&quot;&gt;Pyre&lt;&#x2F;a&gt; created at Facebook... &lt;em&gt;Hem, I mean, Meta&lt;&#x2F;em&gt;. I&#x27;ve used PyAnnotate just because it felt like the most easiest to setup and to use. I should probably give a try to the other options.&lt;&#x2F;p&gt;
&lt;p&gt;In the repository, there is a configuration  &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dropbox&#x2F;pyannotate&#x2F;blob&#x2F;master&#x2F;example&#x2F;example_conftest.py&quot;&gt;example&lt;&#x2F;a&gt; you can use with Pytest. And after running your tests, you should find a new file named &lt;code&gt;type_info.json&lt;&#x2F;code&gt;. This file will contain a json that looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql&#x2F;__init__.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;line&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;func_name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;RQLHelper.compute_solutions&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;type_comments&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, None, None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Insert, None, None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, Dict[str, function], None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Delete, None, None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Set, None, None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, Dict[str, function], Dict[str, str], int) -&amp;gt; Set[str]&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, None, None, int) -&amp;gt; pyannotate_runtime.collect_types.NoReturnType&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Insert, None, None, int) -&amp;gt; pyannotate_runtime.collect_types.NoReturnType&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;samples&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql&#x2F;__init__.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;line&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;152&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;func_name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;RQLHelper.simplify&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;type_comments&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union) -&amp;gt; None&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;samples&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;14
&lt;&#x2F;span&gt;&lt;span&gt;    },    
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Those generated type-hints are &lt;strong&gt;suggestions&lt;&#x2F;strong&gt;. You will have to tweak them first, then apply them. Once applied, you should run mypy on the updated files to verify that everything stays green.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;how-much-should-be-typed&quot;&gt;How much should be typed?&lt;&#x2F;h2&gt;
&lt;p&gt;I won&#x27;t deny, I was &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;existing_code.html#using-mypy-with-an-existing-codebase&quot;&gt;gradually&lt;&#x2F;a&gt; adding annotation to everything, everywhere. There was a feeling of endlessness.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;everywhere.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Then I asked myself: &lt;em&gt;&amp;quot;How do I know the RQL package has enough annotations? How do I know that I&#x27;ve done enough?&amp;quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I decided to &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;commit&#x2F;68f034d32bb10d8ce8c7244c361afe219cc0cca8&quot;&gt;follow&lt;&#x2F;a&gt; a path: adding Mypy &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;command_line.html#cmdoption-mypy-txt-report&quot;&gt;coverage reports&lt;&#x2F;a&gt; to the project. The lower the percentage, the happier you should be:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;Mypy Type Check Coverage Summary
&lt;&#x2F;span&gt;&lt;span&gt;================================
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Script: index
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;span&gt;| Module              | Imprecision       | Lines    |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;span&gt;| rql                 |  29.63% imprecise |  324 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql._exceptions     |   0.00% imprecise |   48 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.analyze         |  62.35% imprecise |  603 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.base            |  13.19% imprecise |  288 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.interfaces      |  11.54% imprecise |   78 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.nodes           |  24.20% imprecise | 1438 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.parser          |  77.19% imprecise | 1245 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.parser.__main__ |  19.30% imprecise |   57 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.pygments_ext    |  23.21% imprecise |   56 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.rqlgen          |   1.62% imprecise |  247 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.rqltypes        |  12.92% imprecise |  178 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.stcheck         |  49.25% imprecise |  867 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.stmts           |  30.98% imprecise | 1372 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.undo            |  27.39% imprecise |  387 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.utils           |  20.72% imprecise |  333 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;span&gt;| Total               |  38.64% imprecise | 7521 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Mypy does &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;type_inference_and_annotations.html#type-inference&quot;&gt;type inference&lt;&#x2F;a&gt;, it can guess the types of values based on the context. We see in the picture below that even though there is no type annotations, the program is not flagged as 100% imprecise:
&lt;img src=&quot;&#x2F;images&#x2F;mypy_reports_one.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I finally &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;commit&#x2F;00efe84a7e18f71cf4741dbd71736b6549dfbd0b&quot;&gt;gave up&lt;&#x2F;a&gt;, to focus on what other &lt;em&gt;Logilabians&lt;&#x2F;em&gt;, suggested: &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;cubicweb&#x2F;-&#x2F;snippets&#x2F;61#LC41&quot;&gt;find&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;cubicweb&#x2F;-&#x2F;issues&#x2F;218&quot;&gt;list&lt;&#x2F;a&gt; what are the &lt;strong&gt;RQL&#x27;s most imported&#x2F;used classes and functions&lt;&#x2F;strong&gt;. If those classes and functions are typed, we&#x27;ll consider we&#x27;ve reach a milestone.&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;type-information-inline-or-via-stubs&quot;&gt;Type information inline or via stubs?&lt;&#x2F;h2&gt;
&lt;p&gt;Mypy gives you the ability to add type annotations to your project without ever modifying the original source code. You do it using what&#x27;s called &amp;quot;stub files&amp;quot;. &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;stubs.html&quot;&gt;Stub&lt;&#x2F;a&gt; files are python-like files, that only contain type-checked variable, function, and class definitions. Nothing else.&lt;&#x2F;p&gt;
&lt;p&gt;I went the other way, I&#x27;ve added type annotations directly within the original source code. In the beginning, it really felt like the easiest thing to do, having everything in the same file. But now that there is more and more types, I think I&#x27;m better improve readability.&lt;&#x2F;p&gt;
&lt;p&gt;I can for example write &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;kinds_of_types.html#type-aliases&quot;&gt;type aliases&lt;&#x2F;a&gt; whenever &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;rql&#x2F;stcheck.py#L158&quot;&gt;necessary&lt;&#x2F;a&gt;. Interesting inspiration can be found &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dropbox&#x2F;incubator-superset-internal&#x2F;blob&#x2F;4cf3f99ee881a10995212828494f0b126dd5415e&#x2F;superset&#x2F;typing.py&quot;&gt;here&lt;&#x2F;a&gt;. I can also write a snippet that will strip all those annotations and put them inside &lt;code&gt;.pyi&lt;&#x2F;code&gt; files.&lt;&#x2F;p&gt;
&lt;p&gt;From now on, I think I&#x27;ll always use stub files.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;type-checking&quot;&gt;Type Checking:&lt;&#x2F;h2&gt;
&lt;p&gt;The typing module defines a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html#typing.TYPE_CHECKING&quot;&gt;TYPE_CHECKING&lt;&#x2F;a&gt; constant that is &lt;code&gt;False&lt;&#x2F;code&gt; at runtime but treated as &lt;code&gt;True&lt;&#x2F;code&gt; while type checking. This technique is used to tell mypy something without the code being evaluated at runtime, for example resolving import cycles. Example &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;rql&#x2F;nodes.py#L51&quot;&gt;here&lt;&#x2F;a&gt;, another one &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;rql&#x2F;stmts.py#L243&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;improvements&quot;&gt;Improvements:&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-less-any&quot;&gt;&lt;em&gt;1. Less Any:&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve been into situations where I&#x27;m not sure what should be the correct type annotation. Instead of leaving an empty type annotation, I put &lt;code&gt;Any&lt;&#x2F;code&gt;, to show other developers that the lack of a restrictive type hint is a conscious choice: either I don&#x27;t know, either I&#x27;m not sure.&lt;&#x2F;p&gt;
&lt;p&gt;Normally, I should use &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html#the-any-type&quot;&gt;Any&lt;&#x2F;a&gt; only if it&#x27;s impossible for me to know what the type is going to be.&lt;&#x2F;p&gt;
&lt;p&gt;From the documentation we can &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html#the-any-type&quot;&gt;read&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Notice that no type checking is performed when assigning a value of type Any to a more precise type. For example, the static type checker did not report an error when assigning a to s even though s was declared to be of type str and receives an int value at runtime!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So, to take advantage of Mypy, I should really avoid using &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;search?group_id=23&amp;amp;nav_source=navbar&amp;amp;page=1&amp;amp;project_id=300&amp;amp;repository_ref=branch%2Fdefault&amp;amp;scope=&amp;amp;search=%3A+Any&amp;amp;search_code=true&amp;amp;snippets=false&quot;&gt;Any&lt;&#x2F;a&gt; and see if I can replace it with a proper annotation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-less-type-ignore-comments&quot;&gt;&lt;em&gt;2. Less type: ignore comments:&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It was also impossible to progress without using &lt;code&gt;# type: ignore&lt;&#x2F;code&gt; comments, to work around the trickier cases. There are still too many &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;search?group_id=23&amp;amp;nav_source=navbar&amp;amp;page=1&amp;amp;project_id=300&amp;amp;search=%3A+ignore&quot;&gt;type: ignore&lt;&#x2F;a&gt; comments. I should have another look and see if I can improve the type annotations and remove some of those type: ignore comments.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;thanks&quot;&gt;Thanks:&lt;&#x2F;h2&gt;
&lt;p&gt;Special thanks to &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;romaricst&quot;&gt;Romaric&lt;&#x2F;a&gt; who took the time to read this article and provide insightful critiques.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic:&lt;&#x2F;h2&gt;
&lt;p&gt;Really hope you&#x27;ve learned something reading this article. As always, the topic is wide and cannot be completely covered here. To discover more about this subject, I strongly recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;typeddjango&#x2F;awesome-python-typing&quot;&gt;Awesome typing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=8wjntHrTGPs&quot;&gt;Liskov Substitution Principle with Johan Vergeer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dropbox.tech&#x2F;application&#x2F;our-journey-to-type-checking-4-million-lines-of-python&quot;&gt;Our journey to type checking 4 million lines of Python&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;instagram-engineering.com&#x2F;static-analysis-at-scale-an-instagram-story-8f498ab71a0c&quot;&gt;Static analysis at scale: an Instagram story&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>To type or not to type? That is the question</title>
		<published>2021-08-22T03:40:17+00:00</published>
		<updated>2021-08-22T03:40:17+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/stcmp/" type="text/html"/>
		<id>https://nskm.xyz/posts/stcmp/</id>
		<content type="html">&lt;p&gt;I&#x27;ve spent the last couple of months adding &lt;a href=&quot;http:&#x2F;&#x2F;mypy-lang.org&#x2F;&quot;&gt;type hints&lt;&#x2F;a&gt; to the &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;merge_requests?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=all&amp;amp;author_username=nsukami&quot;&gt;RQL package&lt;&#x2F;a&gt;. In this first part, I&#x27;ll try to tell you &lt;strong&gt;when&lt;&#x2F;strong&gt; I think Mypy may be useful. In a &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;stcmp2&#x2F;&quot;&gt;second part&lt;&#x2F;a&gt;, I&#x27;ll talk about the &lt;strong&gt;how&lt;&#x2F;strong&gt;, the process I&#x27;ve followed for adding type annotations to RQL. In a last part, I&#x27;ll talk about what I&#x27;ve &lt;strong&gt;learned&lt;&#x2F;strong&gt; during the process.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;what&quot;&gt;What?&lt;&#x2F;h2&gt;
&lt;p&gt;Yes, in case you were living under a rock, here are the news: you can now write Python &lt;strong&gt;as if&lt;&#x2F;strong&gt; it was a static programming language. The official &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0484&#x2F;&quot;&gt;PEP&lt;&#x2F;a&gt;, the official &lt;a href=&quot;http:&#x2F;&#x2F;www.mypy-lang.org&#x2F;&quot;&gt;website&lt;&#x2F;a&gt;. The official &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt;. And the official &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;python&#x2F;mypy&quot;&gt;repository&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The &lt;a href=&quot;http:&#x2F;&#x2F;www.alorelang.org&#x2F;&quot;&gt;Alore&lt;&#x2F;a&gt; programming language, the project Mypy borrows heavily from.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;&#x2F;h2&gt;
&lt;p&gt;I remember when I was asked to work on this task. The (my) skepticism was real. Around me, reactions were mixed (confused, disgusted, interesed). I won&#x27;t deny, sometimes, I&#x27;m really wondering if I&#x27;m not better go and learn to write &lt;a href=&quot;https:&#x2F;&#x2F;ocaml.org&#x2F;learn&#x2F;&quot;&gt;OCaml&lt;&#x2F;a&gt;. Python devs are so used to quickly prototype their programs, without worrying about the types of their variables, without worrying about their return types, etc. You cannot just come and tell them that type hints are nice! They need to be convinced.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;what.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;More than once, the discussion ended with the &amp;quot;explicit vs implicit&amp;quot;, &amp;quot;static vs dynamic&amp;quot; holy wars, etc... I&#x27;m not trying to fuel those debates. There are pros and cons on each sides. You have to know what are the tools, what suits you best, depending on what you&#x27;re trying to achieve, depending on what is your position (user, author, maintainer).&lt;&#x2F;p&gt;
&lt;p&gt;Assuming you&#x27;re a person who already write Python programs, and you want to discover more about Mypy. If you only look at some introductory examples, they will help you understand &lt;strong&gt;what&#x27;s going on.&lt;&#x2F;strong&gt; They won&#x27;t &lt;strong&gt;convince&lt;&#x2F;strong&gt; you to jump on the type-hints band wagon. The problem with most of the examples is, they&#x27;re too short, or too basic.&lt;&#x2F;p&gt;
&lt;p&gt;No disrepect to the authors, I guess, the intent was to make things easier to understand. Short and simple to get to the point. But short and simple would barely convince you to try.&lt;&#x2F;p&gt;
&lt;p&gt;So, what are the situations in which adding types to your program will be useful, necessary, not a waste of time, priceless, meaningful? To this question, I would say this: &lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Type hints are mainly useful for the &lt;a href=&quot;https:&#x2F;&#x2F;hynek.me&#x2F;talks&#x2F;python-foss&#x2F;&quot;&gt;maintainers&lt;&#x2F;a&gt;, &lt;strong&gt;&lt;em&gt;the human readers&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; of &lt;strong&gt;&lt;em&gt;large code bases&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. The  people who &lt;strong&gt;read&lt;&#x2F;strong&gt; and &lt;strong&gt;debug&lt;&#x2F;strong&gt; and &lt;strong&gt;maintain&lt;&#x2F;strong&gt; large software systems &lt;strong&gt;they did not write&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The major benefit for you won&#x27;t be fewer bugs or unit tests, but the ability to more easily read and reason about code written by someone else.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;h2 id=&quot;i-need-to-know-the-types&quot;&gt;I need to know the types:&lt;&#x2F;h2&gt;
&lt;p&gt;When you read&#x2F;debug&#x2F;maintain a large software system you&#x27;ve not written, you&#x27;ll often be in the position in which you ask yourself: &amp;quot;Those function arguments, those variables, what are their types?&amp;quot;, or &amp;quot;Is this function returning something?&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Remember, you were reading the source code, now you need to: modifiy the source code, add a couple of: &lt;code&gt;print(foo)&lt;&#x2F;code&gt;, &lt;code&gt;type(bar)&lt;&#x2F;code&gt;, &lt;code&gt;isinstance(baz)&lt;&#x2F;code&gt;, &lt;code&gt;qux.__class__&lt;&#x2F;code&gt;, &lt;code&gt;corge.__dict__&lt;&#x2F;code&gt;. You will probably add &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functions.html#breakpoint&quot;&gt;breakpoints&lt;&#x2F;a&gt; here and there, to dive inside &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;pdb.html&quot;&gt;pdb&lt;&#x2F;a&gt;. Then start a REPL, then launch the program, then do some instrospection, then see what&#x27;s going on. And finally, discover that the type is not what you were expecting.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;vZrArZhxAUoAAAAd&#x2F;hugh-laurie-facepalm.gif&quot; alt=&quot;phew&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;what-about-just-reading-the-type&quot;&gt;What about just reading the type?&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s be honest, as a &lt;em&gt;reader&lt;&#x2F;em&gt;, as the one who review millions of lines of code, you just want to be able to &lt;em&gt;read&lt;&#x2F;em&gt; what are the types. And I&#x27;m not talking about &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0257&#x2F;&quot;&gt;docstrings&lt;&#x2F;a&gt;. Everybody should document their programs and write docstrings. But let&#x27;s face it, docstrings may be missing, misleading, out of date, not clear enough, etc.... Let&#x27;s compare the 2 following &lt;em&gt;shorts&lt;&#x2F;em&gt; snippets:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# What is tr ???
&lt;&#x2F;span&gt;&lt;span&gt;        foo = self.get_foo()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;foo != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tr(foo) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ah, tr is a function. What&amp;#39;s returned by tr?
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# The method seems to return a string
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Imagine having to find answers to those questions many times in a day?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr: rt.TranslationFunction) -&amp;gt; Optional[str]:
&lt;&#x2F;span&gt;&lt;span&gt;        foo = self.get_foo()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;foo != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tr(foo)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You see that in the second snippet, all the important informations are on the function header. You don&#x27;t even read the function body and you already know that: &lt;strong&gt;&amp;quot;get_description is a method that takes a function as its only parameter and return a string or nothing&amp;quot;&lt;&#x2F;strong&gt;. That&#x27;s a game changer when you&#x27;re a maintainer.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not a surprise, &lt;a href=&quot;https:&#x2F;&#x2F;google.github.io&#x2F;pytype&#x2F;&quot;&gt;all&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;pyre-check.org&#x2F;&quot;&gt;the&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Microsoft&#x2F;pyright&quot;&gt;big&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;monkeytype.readthedocs.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;companies&lt;&#x2F;a&gt;, the ones with large software systems, are already using type annotations.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;too-verbose-and-confusing-to-read&quot;&gt;Too verbose and confusing to read?&lt;&#x2F;h2&gt;
&lt;p&gt;Adding type annotation can quickly lead to a source code that is too verbose and disgusting to read. The following is something I&#x27;ve written for RQL. I think I can do better (define type aliases, use stub files, use dataclasses, refactor, ...)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ScopeNode(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;BaseNode&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__init__(self):
&lt;&#x2F;span&gt;&lt;span&gt;        self.defined_vars: Dict[str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.nodes.Variable&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = {}
&lt;&#x2F;span&gt;&lt;span&gt;        self.with_: List[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.nodes.SubQuery&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = []
&lt;&#x2F;span&gt;&lt;span&gt;        self.solutions: rt.SolutionsList = []
&lt;&#x2F;span&gt;&lt;span&gt;        self._varmaker = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        self.where: Optional[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.base.Node&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        self.having: Iterable[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.base.Node&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = ()
&lt;&#x2F;span&gt;&lt;span&gt;        self.schema: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        self.aliases: Dict[str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.nodes.ColumnAlias&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;stub-files&quot;&gt;Stub files?&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to keep your source code free of type annotations, but still want to use type annotations, you can write &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0484&#x2F;#stub-files&quot;&gt;stub files&lt;&#x2F;a&gt;. A stub file is just a file that will contain all your variables, function signatures, &lt;em&gt;annotated&lt;&#x2F;em&gt;. &lt;strong&gt;Function bodies in stub files are just a single ellipsis.&lt;&#x2F;strong&gt; Another really short example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# foo.py
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr):
&lt;&#x2F;span&gt;&lt;span&gt;        foo = self.get_foo()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;foo != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tr(foo)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# foo.pyi &amp;lt;--- notice the extension used for stub files
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr: rt.TranslationFunction) -&amp;gt; Optional[str]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;i-want-type-annotations-what-s-next&quot;&gt;I want type annotations, what&#x27;s next?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;introduction.html#introduction&quot;&gt;Mypy&lt;&#x2F;a&gt; is a static type checker for Python. Let&#x27;s see what Mypy can to for us.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;1-generating-type-annotations&quot;&gt;1. Generating type annotations:&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s suppose you want to add type annotations to your code base. How do you proceed?&lt;&#x2F;p&gt;
&lt;p&gt;Mypy includes the &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;stubgen.html&quot;&gt;stubgen&lt;&#x2F;a&gt; tool that can automatically generate stub files. For example, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;LeMeteore&#x2F;typeshed&#x2F;blob&#x2F;b2e1083560e223ec415fcb4dd155366e2984b2a5&#x2F;stubs&#x2F;dateparser&#x2F;dateparser&#x2F;__init__.pyi&quot;&gt;here&lt;&#x2F;a&gt; is an example of a &lt;code&gt;.pyi&lt;&#x2F;code&gt; file generated by the stubgen tool for the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scrapinghub&#x2F;dateparser&quot;&gt;dateparser&lt;&#x2F;a&gt; package.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Any, Optional
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;parse(
&lt;&#x2F;span&gt;&lt;span&gt;    date_string: Any, 
&lt;&#x2F;span&gt;&lt;span&gt;    date_formats: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    languages: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    locales: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    region: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    settings: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Keep in mind, most types annotations will default to &lt;code&gt;Any&lt;&#x2F;code&gt;. You&#x27;ll need to update &lt;code&gt;pyi&lt;&#x2F;code&gt; files and write more precise types (We agree that &lt;code&gt;Any&lt;&#x2F;code&gt; everywhere is not really useful). &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hoefling&#x2F;typeshed&#x2F;blob&#x2F;855acb4da416375b0d4791be51bf0934b0ee9e29&#x2F;stubs&#x2F;dateparser&#x2F;dateparser&#x2F;__init__.pyi&quot;&gt;Here&lt;&#x2F;a&gt; is an example of the same stub file with more precise type annotations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;datetime
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sys
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Set, Tuple
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;dateparser.date &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;DateDataParser
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;sys.version_info &amp;gt;= (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Literal, TypedDict
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing_extensions &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Literal, TypedDict
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;__version__: str
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;_default_parser: DateDataParser
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;_Part = Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;day&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;month&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;year&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;_ParserKind = Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;timestamp&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;relative-time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;custom-formats&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;absolute-time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;no-spaces-time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;_Settings(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;TypedDict&lt;&#x2F;span&gt;&lt;span&gt;, total=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    DATE_ORDER: str
&lt;&#x2F;span&gt;&lt;span&gt;    PREFER_LOCALE_DATE_ORDER: bool
&lt;&#x2F;span&gt;&lt;span&gt;    TIMEZONE: str
&lt;&#x2F;span&gt;&lt;span&gt;    TO_TIMEZONE: str
&lt;&#x2F;span&gt;&lt;span&gt;    RETURN_AS_TIMEZONE_AWARE: bool
&lt;&#x2F;span&gt;&lt;span&gt;    PREFER_DAY_OF_MONTH: Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;current&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;first&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;last&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    PREFER_DATES_FROM: Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;current_period&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;future&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;past&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    RELATIVE_BASE: datetime.datetime
&lt;&#x2F;span&gt;&lt;span&gt;    STRICT_PARSING: bool
&lt;&#x2F;span&gt;&lt;span&gt;    REQUIRE_PARTS: list[_Part]
&lt;&#x2F;span&gt;&lt;span&gt;    SKIP_TOKENS: list[str]
&lt;&#x2F;span&gt;&lt;span&gt;    NORMALIZE: bool
&lt;&#x2F;span&gt;&lt;span&gt;    RETURN_TIME_AS_PERIOD: bool
&lt;&#x2F;span&gt;&lt;span&gt;    PARSERS: list[_ParserKind]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;parse(
&lt;&#x2F;span&gt;&lt;span&gt;    date_string: str,
&lt;&#x2F;span&gt;&lt;span&gt;    date_formats: list[str] | Tuple[str] | Set[str] | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    languages: list[str] | Tuple[str] | Set[str] | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    locales: list[str] | Tuple[str] | Set[str] | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    region: str | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    settings: _Settings | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; datetime.datetime | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Do we agree that the :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;parse function parameters are more precise. &lt;&#x2F;li&gt;
&lt;li&gt;settings parameter is annotated with a more detailed type.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;returned value is more precise. &lt;&#x2F;li&gt;
&lt;li&gt;refactoring of this function will be easier.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h3 id=&quot;2-type-checking&quot;&gt;2. Type checking:&lt;&#x2F;h3&gt;
&lt;p&gt;Before running your tests, before running your program, Mypy can detect &lt;em&gt;some types&lt;&#x2F;em&gt; of bugs:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;what2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I pretend &lt;code&gt;foo&lt;&#x2F;code&gt; should return a &lt;code&gt;string&lt;&#x2F;code&gt;, yet, there are cases where foo does return &lt;code&gt;None&lt;&#x2F;code&gt;. That should be fixed. Notice how, the program is running fine. Mypy will type check the program and tell you what&#x27;s wrong. Mypy won&#x27;t stop you from running the program.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion:&lt;&#x2F;h2&gt;
&lt;p&gt;Most people, including myself, don&#x27;t work on projects of this size (&lt;a href=&quot;https:&#x2F;&#x2F;dropbox.tech&#x2F;application&#x2F;our-journey-to-type-checking-4-million-lines-of-python&quot;&gt;4 million lines of Python code&lt;&#x2F;a&gt;), and hence have not to deal with the constraints of such a big code base.&lt;&#x2F;p&gt;
&lt;p&gt;Most people can perfectly write their Python programs without using type annotations. Mypy is just another tool inside your toolbox. I just want you to try, that will certainly make you a better software developer.&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;stcmp2&#x2F;&quot;&gt;next article&lt;&#x2F;a&gt;, I will talk a little bit more about the actual process I&#x27;ve followed for adding type annotations to the RQL package.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;to-learn-more-about-this-topic&quot;&gt;To learn more about this topic:&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html&quot;&gt;Python typing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tube.incognet.io&#x2F;watch?v=pJOmlFf5Je4&quot;&gt;What Python can learn from Haskell&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=hTrjTAPnA_k&quot;&gt;Type hinting (and mypy)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Which, by the way, is where you&#x27;ll find more interesting answers than what&#x27;s inside the documentation, imho.
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;: Yes. I won&#x27;t deny, there is suddenly more lines to &lt;strong&gt;read&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Elephant in the room (part 1)</title>
		<published>2021-05-25T03:40:17+00:00</published>
		<updated>2021-05-25T03:40:17+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/eitr/" type="text/html"/>
		<id>https://nskm.xyz/posts/eitr/</id>
		<content type="html">&lt;p&gt;I&#x27;m living in a Continent where (&lt;em&gt;it sounds like&lt;&#x2F;em&gt;) nobody really cares about software freedom, data privacy, surveillance. I guess, people here are simply too busy trying to stay &lt;a href=&quot;https:&#x2F;&#x2F;www.africanews.com&#x2F;2021&#x2F;05&#x2F;29&#x2F;second-volcano-erupts-in-eastern-democratic-republic-of-congo&#x2F;&quot;&gt;alive&lt;&#x2F;a&gt;, not enough time to think about FOSS. Or maybe they&#x27;re simply confused, maybe they simply don&#x27;t know. &lt;&#x2F;p&gt;
&lt;p&gt;The topic is wide, it&#x27;s easy to digress, and I&#x27;m not sure about the best way to tackle it (&lt;em&gt;consider this to be a first draft, updates will come&lt;&#x2F;em&gt;). Let&#x27;s say it&#x27;s just an attempt, an effort, to &lt;em&gt;at least&lt;&#x2F;em&gt; address the issue.&lt;&#x2F;p&gt;
&lt;br&gt;
Okay. Let me put you in the context...
&lt;br&gt;
&lt;h1 id=&quot;will-you-be-okay-with-anybody-trying-to&quot;&gt;&lt;em&gt;Will you be okay with anybody trying to:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Fix any of your furnitures.&lt;&#x2F;li&gt;
&lt;li&gt;Take you anywhere you want.&lt;&#x2F;li&gt;
&lt;li&gt;Offer you any food you want.&lt;&#x2F;li&gt;
&lt;li&gt;Pay for all your phone, sms, mail bills.&lt;&#x2F;li&gt;
&lt;li&gt;Let you watch any movie, any film, any show.&lt;&#x2F;li&gt;
&lt;li&gt;Alert you about something every 5mn.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;and-in-exchange-the-same-person&quot;&gt;&lt;em&gt;And in exchange the same person:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Won&#x27;t ask you for any money, nothing, he&#x27;ll just keep a tiny tiny list of all:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the furnitures in your house?&lt;&#x2F;li&gt;
&lt;li&gt;the places you visit?&lt;&#x2F;li&gt;
&lt;li&gt;the foods you eat?&lt;&#x2F;li&gt;
&lt;li&gt;the conversations you had?&lt;&#x2F;li&gt;
&lt;li&gt;the movies you watched?&lt;&#x2F;li&gt;
&lt;li&gt;the time he notified you? The reason he notified you?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;do-we-agree-that-you-won-t-be-okay&quot;&gt;&lt;em&gt;Do we agree that you won&#x27;t be okay?&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;em&gt;In standard conditions for temperature and pressure&lt;&#x2F;em&gt;, you won&#x27;t be okay with anybody offering you the deal above because (&lt;em&gt;among many other reasons&lt;&#x2F;em&gt;):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;you don&#x27;t want anybody to access your &lt;strong&gt;private space&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;you want to keep a certain level of &lt;strong&gt;autonomy&lt;&#x2F;strong&gt;, &lt;strong&gt;independance&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;you want to preserve your physical &lt;strong&gt;integrity&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;interestingly&quot;&gt;&lt;em&gt;Interestingly:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;It sounds like, nobody want me to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;put a webcam and a microphone in their house. &lt;&#x2F;li&gt;
&lt;li&gt;have the key to their house. &lt;&#x2F;li&gt;
&lt;li&gt;follow them. &lt;&#x2F;li&gt;
&lt;li&gt;take picture of them or recording them. &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Yet, most of the same people are using all kinds of &lt;em&gt;&amp;quot;privacy invading&amp;quot;&lt;&#x2F;em&gt; technologies on a daily basis:  &lt;a href=&quot;https:&#x2F;&#x2F;www.forbes.com&#x2F;sites&#x2F;kateoflahertyuk&#x2F;2019&#x2F;07&#x2F;28&#x2F;apple-siri-eavesdropping-puts-millions-of-users-at-risk&quot;&gt;Siri&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.cnet.com&#x2F;home&#x2F;smart-home&#x2F;alexa-and-google-voice-assistants-app-exploits-left-it-vulnerable-to-eavesdropping&#x2F;&quot;&gt;Alexa&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.vrt.be&#x2F;vrtnws&#x2F;en&#x2F;2019&#x2F;07&#x2F;10&#x2F;google-employees-are-eavesdropping-even-in-flemish-living-rooms&#x2F;&quot;&gt;Google&lt;&#x2F;a&gt;. I won&#x27;t even talk about &lt;a href=&quot;https:&#x2F;&#x2F;www.dw.com&#x2F;en&#x2F;samsung-admits-smart-tv-may-be-eavesdropping&#x2F;a-18246372&quot;&gt;smart TVs&lt;&#x2F;a&gt;, nor &lt;a href=&quot;https:&#x2F;&#x2F;www.reuters.com&#x2F;article&#x2F;us-eu-facebook-dataprotection-idUSKCN1UO1B4&quot;&gt;Facebook&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;any-reasons-that-let-us-give-our-datas-to-the-tech-giants&quot;&gt;&lt;em&gt;Any reasons that let us give our datas to the Tech Giants?&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;People use privacy invading software for maaaaany reasons that can be understood. 
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There is the &amp;quot;I need to figure out what to eat today&amp;quot; reason. Present all over the world, especially for the poorer people. Even more true in the Black continent. &lt;&#x2F;p&gt;
&lt;p&gt;There is the fact that &lt;strong&gt;implications&lt;&#x2F;strong&gt; (of using privacy invading software) &lt;strong&gt;are invisible&lt;&#x2F;strong&gt;, not obvious. While the benefits are immediate, concrete, observable. &lt;&#x2F;p&gt;
&lt;p&gt;Terms of Service are, &lt;em&gt;most of the time&lt;&#x2F;em&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tosdr.org&#x2F;en&#x2F;service&#x2F;182&quot;&gt;confusing&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tosdr.org&#x2F;fr&#x2F;service&#x2F;217&quot;&gt;difficult&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tosdr.org&#x2F;fr&#x2F;service&#x2F;198&quot;&gt;blurry&lt;&#x2F;a&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;There is also the &amp;quot;I use it because people around me are using it&amp;quot; reason. People are moved by &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Network_effect&quot;&gt;those around&lt;&#x2F;a&gt; them and wish to fit in as quickly as possible, as simply as possible.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Henrik_Ibsen&quot;&gt;Henrik Ibsen&lt;&#x2F;a&gt; said &lt;em&gt;&amp;quot;A thousand words leave not the same deep impression as does a single deed&amp;quot;&lt;&#x2F;em&gt;. And I definitely agree with him:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;de606972e250f89d00.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;theconversation.com&#x2F;heres-how-tech-giants-profit-from-invading-our-privacy-and-how-we-can-start-taking-it-back-120078&quot;&gt;Source&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;do-you-know-that&quot;&gt;&lt;em&gt;Do you know that:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;Your right to physical integrity was &lt;em&gt;already&lt;&#x2F;em&gt; affirmed in 1222, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Kouroukan_Fouga#Contents&quot;&gt;inside the Manden Charter&lt;&#x2F;a&gt;, article 5:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Everybody has a right to life and to the &lt;strong&gt;preservation of physical integrity&lt;&#x2F;strong&gt;. [...]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Your right to privacy was affirmed in 1948 by the &lt;a href=&quot;https:&#x2F;&#x2F;www.un.org&#x2F;en&#x2F;about-us&#x2F;universal-declaration-of-human-rights&quot;&gt;Universal Declaration of Human Rights&lt;&#x2F;a&gt;, article 12:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;No one shall be subjected to &lt;strong&gt;arbitrary interference&lt;&#x2F;strong&gt; with his privacy, family, home or correspondence, nor to attacks upon his honour and reputation. Everyone has the right to the protection of the law against such interference or attacks. &lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Within the &lt;a href=&quot;https:&#x2F;&#x2F;www.echr.coe.int&#x2F;documents&#x2F;convention_eng.pdf&quot;&gt;European Convention on Human Rights&lt;&#x2F;a&gt;, in the article 8, we can read:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Right to respect for private and family life. &lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Everyone has the right to respect for his private and family life, his home and his correspondence.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;There shall be &lt;strong&gt;no interference by a public authority&lt;&#x2F;strong&gt; with the exercise of this right except such as is in accordance with the law and is necessary in a democratic society in the interests of national security, public safety or the economic well-being of the country, for the prevention of disorder or crime, for the protection of health or morals, or for the protection of the rights and freedoms of others.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;www.law.cornell.edu&#x2F;constitution&quot;&gt;U.S. constitution&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;constitution.congress.gov&#x2F;constitution&#x2F;amendment-4&#x2F;&quot;&gt;Fourth Amendment&lt;&#x2F;a&gt; states that:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;The right of the people to be secure in their persons, houses, papers, and effects, &lt;strong&gt;against unreasonable searches and seizures&lt;&#x2F;strong&gt;, shall not be violated, and no Warrants shall issue, but upon probable cause, supported by Oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;p&gt;The point seems to be: &lt;strong&gt;Every human being has a right to privacy, and this right should not be violated.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-is-privacy&quot;&gt;&lt;em&gt;What is privacy?&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I was not able to find a fixed, simple, perfect, static definition of &lt;a href=&quot;https:&#x2F;&#x2F;www.nolo.com&#x2F;dictionary&#x2F;right-to-privacy-term.html&quot;&gt;privacy&lt;&#x2F;a&gt;. The definition may vary from one country to another, from one constitution to another, from one period of time to another. &lt;&#x2F;p&gt;
&lt;p&gt;But I guess we can agree that privacy is any information that intrudes into the intimacy of the individual. &lt;em&gt;Right&lt;&#x2F;em&gt;? Privacy is that thing which is essential to the protection of our dignity as Human Being. &lt;em&gt;Right&lt;&#x2F;em&gt;?  Anything that is directly related to :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;your personal space, your house, your image, &lt;&#x2F;li&gt;
&lt;li&gt;your financial status, your medical status,&lt;&#x2F;li&gt;
&lt;li&gt;your religious, political, &lt;em&gt;or even sexual&lt;&#x2F;em&gt; orientations,&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Privacy is the fundamental way to protect yourself&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;some-of-the-solutions-we-can-explore&quot;&gt;&lt;em&gt;Some of the solutions we can explore:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;How do we defend ourselves and our friends from privacy invading technologies? What can we do to safeguard our personal privacy. What are the ways we can use to better protect ourselves when going online? What are the alternatives to the privacy invading software? I&#x27;ll talk about the solutions in the next &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;wmdop&#x2F;&quot;&gt;article&lt;&#x2F;a&gt; (&lt;em&gt;coming soon&lt;&#x2F;em&gt;).&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;no-i-m-not&quot;&gt;&lt;em&gt;No, I&#x27;m not:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Saying that I&#x27;ve all the answers.&lt;&#x2F;li&gt;
&lt;li&gt;Saying that you should do as I say.&lt;&#x2F;li&gt;
&lt;li&gt;Asking you to close all your accounts. &lt;&#x2F;li&gt;
&lt;li&gt;Asking you to go back to the stone age.&lt;&#x2F;li&gt;
&lt;li&gt;Trying to make you affraid of technology.&lt;&#x2F;li&gt;
&lt;li&gt;Saying that I&#x27;ve found all the alternatives.&lt;&#x2F;li&gt;
&lt;li&gt;Saying that migrating from privacy invading software will be an easy task.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;what-i-m-asking-you&quot;&gt;&lt;em&gt;What I&#x27;m asking you:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Completely shuting down all the Tech Giants won&#x27;t be an easy task. It cannot be done within the snap of a finger &lt;em&gt;(I wish it &lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=TWB31WFomz4&quot;&gt;could&lt;&#x2F;a&gt;)&lt;&#x2F;em&gt;. Let&#x27;s stay optimistic, there is still some actionable steps we can take to help:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ask yourself :
&lt;ul&gt;
&lt;li&gt;Why are you using those platforms?&lt;&#x2F;li&gt;
&lt;li&gt;What are the services you really need?&lt;&#x2F;li&gt;
&lt;li&gt;Is there any alternatives? (Respecting your privacy).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Be aware:
&lt;ul&gt;
&lt;li&gt;of the risks, of the pros &amp;amp; cons. &lt;&#x2F;li&gt;
&lt;li&gt;that if it&#x27;s free, you&#x27;re probably the &lt;a href=&quot;https:&#x2F;&#x2F;ethannonsequitur.com&#x2F;wp-content&#x2F;uploads&#x2F;2011&#x2F;09&#x2F;facebook-and-you-pigs.jpg&quot;&gt;product&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Ask for more:
&lt;ul&gt;
&lt;li&gt;Transparency to all those platforms.&lt;&#x2F;li&gt;
&lt;li&gt;Regulation &amp;amp; protection to your leaders, your governments.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Spark conversation, everywhere.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;interesting-links&quot;&gt;Interesting links:&lt;&#x2F;h1&gt;
&lt;p&gt;This topic is too wide to be covered entirely in this tiny article. I really hope you&#x27;re learned something. I strongly recommend the following links for a better exploration and understanding of the topic.&lt;&#x2F;p&gt;
&lt;p&gt;The following is a list of resources you should &lt;em&gt;download, browse &amp;amp; share&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Enemy of the State&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.killswitchthefilm.com&#x2F;&quot;&gt;Killswitch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=ZHl0WI32XkY&quot;&gt;We are legion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Terms and conditions may apply&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;citizenfourfilm.com&#x2F;&quot;&gt;Citizenfour&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.thesocialdilemma.com&#x2F;&quot;&gt;Social dilemma&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.thegreathack.com&#x2F;&quot;&gt;The great hack&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;snowdenfilm.com&#x2F;&quot;&gt;Snowden&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yewtu.be&#x2F;watch?v=YXmMtbgdces&quot;&gt;Nos données personnelles valent de l&#x27;or&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;activism.net&#x2F;cypherpunk&#x2F;manifesto.html&quot;&gt;A Cypherpunk&#x27;s Manifesto&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yewtu.be&#x2F;watch?v=IWzmYE60_dc&quot;&gt;Macron trahit la « start-up nation », les gafam raflent la mise&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;thanks&quot;&gt;Thanks:&lt;&#x2F;h1&gt;
&lt;p&gt;Special &lt;a href=&quot;https:&#x2F;&#x2F;www.meme-arsenal.com&#x2F;memes&#x2F;379eb2a9776a3bbaac72286e3d857cbf.jpg&quot;&gt;thanks&lt;&#x2F;a&gt; to Orbifx, &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.scot&#x2F;@orbifx&quot;&gt;the Nature&#x27;s emissary&lt;&#x2F;a&gt;, and  &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@travis_kalanick&quot;&gt;Travis Kalanick&lt;&#x2F;a&gt;. They both gave me interesting ideas to help me finish this article. &lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;do-not-forget&quot;&gt;Do not forget:&lt;&#x2F;h1&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;5254e12aa2bdb88c00.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Django single file project. Again</title>
		<published>2020-07-10T01:09:16+00:00</published>
		<updated>2020-07-10T01:09:16+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/dsfpa/" type="text/html"/>
		<id>https://nskm.xyz/posts/dsfpa/</id>
		<content type="html">&lt;p&gt;This article is a follow up on the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;dsfp&#x2F;&quot;&gt;one&lt;&#x2F;a&gt; I&#x27;ve written few years
ago. Special shoutout and thanks and hugs and kudos to &lt;a href=&quot;http:&#x2F;&#x2F;buzzi.me&#x2F;&quot;&gt;Javier
Buzzi&lt;&#x2F;a&gt; for taking the time to &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;kingbuzzman&#x2F;d7859d9734b590e52fad787d19c34b52&quot;&gt;improve&lt;&#x2F;a&gt; the original script.&lt;&#x2F;p&gt;
&lt;p&gt;TL;DR: &lt;a href=&quot;https:&#x2F;&#x2F;bin.nskm.xyz&#x2F;pastes&#x2F;ee784daff75aae62&quot;&gt;download old version&lt;&#x2F;a&gt; &amp;amp; &lt;a href=&quot;https:&#x2F;&#x2F;bin.nskm.xyz&#x2F;pastes&#x2F;c4434741122bec0f&quot;&gt;download new version&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br &#x2F;&gt;
&lt;h2 id=&quot;very-important-disclaimer&quot;&gt;VERY IMPORTANT DISCLAIMER&lt;&#x2F;h2&gt;
&lt;p&gt;The content associated with mlvin.xyz may be very offensive to some people. I&#x27;ve lost the ownership of mlvin.xyz a very long time ago, sad situation. I&#x27;m not anymore linked to this domain name, nor to the content hosted on this website. &lt;em&gt;By the way F*** OVH&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-those-improvements&quot;&gt;What are those improvements?&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;application-label&quot;&gt;Application label?&lt;&#x2F;h3&gt;
&lt;p&gt;Our models are not defined as in a classical Django application. So,
each model should declare which app it belongs to. You can read more
about app_label Meta option &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;3.0&#x2F;ref&#x2F;models&#x2F;options&#x2F;#django.db.models.Options.app%5Flabel&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The problem with the first script was duplication:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Author(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Book(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    author = models.ForeignKey(Author, related_name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;books&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    title = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;400&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We want to define app_label once and for all our models:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# The current name of the file, which will be the name of our app
&lt;&#x2F;span&gt;&lt;span&gt;APP_LABEL, _ = os.path.splitext(os.path.basename(os.path.abspath(__file__)))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, we need to overwrite the Django function in charge of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;looking for an application configuration&lt;&#x2F;li&gt;
&lt;li&gt;attach the model to the found&#x2F;correct application configuration.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This function is named &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;stable&#x2F;3.0.x&#x2F;django&#x2F;apps&#x2F;registry.py#L243&quot;&gt;get_containing_app_config&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_containing_app_config(module):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;module == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;__main__&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# if inside single file project,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# retrieve the application configuration using APP_LABEL variable
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;apps.get_app_config(APP_LABEL)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# otherwise, do as you always do
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;apps._get_containing_app_config(module)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# save the original function
&lt;&#x2F;span&gt;&lt;span&gt;apps._get_containing_app_config = apps.get_containing_app_config
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ask Django to use our custom function
&lt;&#x2F;span&gt;&lt;span&gt;apps.get_containing_app_config = get_containing_app_config
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;migrations-folder&quot;&gt;Migrations folder?&lt;&#x2F;h3&gt;
&lt;p&gt;There is a Django settings named &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;stable&#x2F;3.0.x&#x2F;django&#x2F;conf&#x2F;global_settings.py#L616&quot;&gt;MIGRATION_MODULE&lt;&#x2F;a&gt;. According to the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;stable&#x2F;3.0.x&#x2F;docs&#x2F;ref&#x2F;settings.txt#L2021&quot;&gt;documentation&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A dictionary specifying the package where migration modules can be found on a per-app basis. The  default value of this setting is an empty dictionary, but the default package name for migration modules is ``migrations``.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;p&gt;In the first version of the script, all the migrations were put in a folder named &lt;code&gt;migrations&lt;&#x2F;code&gt;. With the following configuration, we can:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;name the migration folder how we want.&lt;&#x2F;li&gt;
&lt;li&gt;make sure that we have one migration folder per application.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Where migrations folder need to be created
&lt;&#x2F;span&gt;&lt;span&gt;APP_MIGRATION_MODULE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;_migrations&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;APP_MIGRATION_PATH = os.path.join(BASE_DIR, APP_MIGRATION_MODULE)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create the migration folder
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# and a __init__.py file if necessary:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if not &lt;&#x2F;span&gt;&lt;span&gt;os.path.exists(APP_MIGRATION_PATH):
&lt;&#x2F;span&gt;&lt;span&gt;    os.makedirs(APP_MIGRATION_PATH)
&lt;&#x2F;span&gt;&lt;span&gt;    open(os.path.join(APP_MIGRATION_PATH, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;__init__.py&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;w&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).close()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also took the time to update the Django settings, somewhere inside the call to &lt;code&gt;settings.configure function&lt;&#x2F;code&gt;, you&#x27;ll find:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Django needs to be told where is the migration module
&lt;&#x2F;span&gt;&lt;span&gt;MIGRATION_MODULES={APP_LABEL: APP_MIGRATION_MODULE},
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;fake-modules&quot;&gt;Not so fake modules?&lt;&#x2F;h3&gt;
&lt;p&gt;A correctly configured Django application should normally have a &lt;code&gt;model modules&lt;&#x2F;code&gt;, a &lt;code&gt;urls modules&lt;&#x2F;code&gt; and a &lt;code&gt;tests module&lt;&#x2F;code&gt;. Python provides us with an interesting  &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;types.html#types.ModuleType&quot;&gt;class&lt;&#x2F;a&gt;: &lt;code&gt;types.ModuleType&lt;&#x2F;code&gt;, that will help us create a module, &lt;em&gt;you guessed it&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Used so you can do &amp;#39;from &amp;lt;name of file&amp;gt;.models import *&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;models_module = ModuleType(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.models&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% (APP_LABEL))
&lt;&#x2F;span&gt;&lt;span&gt;tests_module = ModuleType(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.tests&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% (APP_LABEL))
&lt;&#x2F;span&gt;&lt;span&gt;urls_module = ModuleType(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.urls&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% (APP_LABEL))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# we created the urlpatterns list earlier,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# let&amp;#39;s attach this variable to the urls_module:
&lt;&#x2F;span&gt;&lt;span&gt;urls_module.urlpatterns = urlpatterns
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# A model module needs to have classes that inherits from models.Model
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# let&amp;#39;s correctly add all our models we defined earlier
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# as attributes to the models_module:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;variable_name, value &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;list(locals().items()):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# We are only interested in models
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;inspect.isclass(value) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;and &lt;&#x2F;span&gt;&lt;span&gt;issubclass(value, models.Model):
&lt;&#x2F;span&gt;&lt;span&gt;        setattr(models_module, variable_name, value)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Setup the fake modules
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[models_module.__name__] = models_module
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[urls_module.__name__] = urls_module
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[APP_LABEL].models = models_module
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[APP_LABEL].urls = urls_module
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;going-further&quot;&gt;Going further?&lt;&#x2F;h3&gt;
&lt;p&gt;I really hope you&#x27;ve learned something, I did \o&#x2F;. You may want to browse some of the gists kept by &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;search?q=mlvin&quot;&gt;Javier Buzzi&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;br&gt;
You may also be really interested by the work done for  &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zenwalker&#x2F;django-micro&quot;&gt;django-micro&lt;&#x2F;a&gt; a lightweight wrapper around Django that turns it into a microframework.
&lt;br&gt;&lt;br&gt;
If you have any kind of interesting improvements, advices, suggestions, please send me an email, or post a comment on &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@lemeteore&#x2F;104489090816400323&quot;&gt;Mastodon&lt;&#x2F;a&gt;. &lt;em&gt;Still not took the time to install a comment system, shame on me&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;o&#x2F;&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Free and Open Source Software</title>
		<published>2017-04-04T00:00:00+00:00</published>
		<updated>2017-04-04T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/foss/" type="text/html"/>
		<id>https://nskm.xyz/posts/foss/</id>
		<content type="html">&lt;p&gt;I&#x27;m often asked why do I prefer to use free software in places (Dakar, Libreville, Kinshasa, ...), where basically every human being is using closed source and proprietary software? Here are some of the reasons.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;not-being-able-to-pay-for-a-license&quot;&gt;&lt;strong&gt;Not being able to pay for a license&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Learning informatics was equivalent to installing a bunch of software requiring me to pay for a license. And coming from a very modest family, paying for a license was not an option. I&#x27;ve never really been able to explain to my parent that&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I need to pay, via internet, using a credit card&lt;&#x2F;li&gt;
&lt;li&gt;a company located somewhere in the world, I don&#x27;t even know where&lt;&#x2F;li&gt;
&lt;li&gt;to get the permission to use such an abstract thing like a software&lt;&#x2F;li&gt;
&lt;li&gt;for some time, then I&#x27;ll have to pay again, to renew the permission&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h3 id=&quot;tired-of-looking-for-the-crack&quot;&gt;&lt;strong&gt;Tired of looking for the crack&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Not being able to pay for the license, the remaining choice was to look for the crack. that was the most easy way to get the software you want to use. But in the mean time, That was a very difficult task, always browsing the internet, looking for the product keys, the key generator, the patch, the full activator, etc... It was time consuming, and boring as editors are always trying to make it more and more difficult.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;trying-to-be-a-good-citizen&quot;&gt;&lt;strong&gt;Trying to be a good citizen&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Even if they should, most people often do not feel bad about using cracked software. After all, there were no physical harm, no shoplifting, no unlawful entry into a building, no indiscriminate taking of goods. Why feeling bad about it?&lt;&#x2F;p&gt;
&lt;p&gt;Theft, from &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Theft&quot;&gt;Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;In common usage, a theft is the illegal taking of another person&#x27;s property or services without that person&#x27;s permission or consent with the intent to deprive the rightful owner of it.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Property, from &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Property#Types_of_property&quot;&gt;Wikepedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Important widely recognized types of property include real property (the combination of land and any improvements to or on the land), personal property (physical possessions belonging to a person), private property (property owned by legal persons, business entities or individual natural persons), public property (state owned or publicly owned and available possessions) and intellectual property (exclusive rights over artistic creations, inventions, etc.), although the last is not always as widely recognized or enforced.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
Above are the main reasons why I chose free and open source software. You can actually close this page, and go back to your awesome life, **thanks for reading**. But there is more.
&lt;br&gt;
&lt;h3 id=&quot;the-free-and-open-source-software-philosophy-promotes-values-that-go-beyond-software&quot;&gt;&lt;strong&gt;The free and open source software philosophy promotes values that go beyond software&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;own&lt;&#x2F;em&gt; an item, &lt;em&gt;to use it for any purpose&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;study&lt;&#x2F;em&gt; how this item is made&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;customize&lt;&#x2F;em&gt; this item&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;share&lt;&#x2F;em&gt; the item modified or not, with whoever you want&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h3 id=&quot;fine-can-we-have-some-real-life-examples-please&quot;&gt;&lt;strong&gt;Fine, can we have some real life examples please?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;From &lt;a href=&quot;https:&#x2F;&#x2F;www.softwareheritage.org&#x2F;mission&#x2F;heritage&#x2F;&quot;&gt;Software Heritage&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Software controls the electronic equipment embedded in the machines we use to travel, communicate, trade and exchange. Software is just crucial for the proper operation of every large organizations. Software has enabled the emergence of new forms of social and political organizations. Software is essential to understand our society.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Maybe it&#x27;s not perceptible enough, but free and open source software is already &lt;a href=&quot;http:&#x2F;&#x2F;embedded-computing.com&#x2F;articles&#x2F;open-source-software-everywhere&#x2F;&quot;&gt;everywhere&lt;&#x2F;a&gt;. Here you are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Aerospace: Open Source Software projects from &lt;a href=&quot;https:&#x2F;&#x2F;code.nasa.gov&#x2F;&quot;&gt;NASA&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Automotive: &lt;a href=&quot;https:&#x2F;&#x2F;www.automotivelinux.org&quot;&gt;AGL&lt;&#x2F;a&gt; group, including lots of &lt;a href=&quot;https:&#x2F;&#x2F;www.automotivelinux.org&#x2F;about&#x2F;members&quot;&gt;automakers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Robotics: &lt;a href=&quot;https:&#x2F;&#x2F;www.osrfoundation.org&#x2F;osrf-projects&#x2F;&quot;&gt;Open Source Robotics Foundation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Healthcare: &lt;a href=&quot;http:&#x2F;&#x2F;www.open-emr.org&#x2F;&quot;&gt;Open-EMR&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;openmrs.org&#x2F;&quot;&gt;OpenMRS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Education: &lt;a href=&quot;http:&#x2F;&#x2F;open-sankore.org&#x2F;en&quot;&gt;Open Sankoré&lt;&#x2F;a&gt;, an interactive whiteboard software.&lt;&#x2F;li&gt;
&lt;li&gt;Films: &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=eRsGyueVLvQ&quot;&gt;Sintel&lt;&#x2F;a&gt;, and many other open movies by &lt;a href=&quot;https:&#x2F;&#x2F;www.blender.org&#x2F;features&#x2F;projects&#x2F;&quot;&gt;Blender Foundation&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
It is no more about software, it is about **openess and freedom**.
&lt;br&gt;
The topic is actually very huge and deep, I&#x27;ve not even mentioned privacy, nor surveillance. I obviously won&#x27;t be able to cover the whole thing. 
&lt;h3 id=&quot;for-those-who-want-to-go-further-i-strongly-recommands-the-following-links&quot;&gt;&lt;strong&gt;For those who want to go further, I strongly recommands the following links:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=xKsR5jWl1Tk&quot;&gt;Threats of data mining&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8vOF8VsUwbA&quot;&gt;Freedom in the cloud&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;modernfarmer.com&#x2F;2016&#x2F;07&#x2F;right-to-repair&#x2F;&quot;&gt;Right to fix their own dang tractors&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opensource.com&#x2F;article&#x2F;17&#x2F;4&#x2F;become-open-source-sustainer&quot;&gt;Why you should become an open source sustainer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;anybox.fr&#x2F;blog&#x2F;pourquoi-l-open-source&quot;&gt;Pourquoi l&#x27;open source&lt;&#x2F;a&gt; (French) &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Threads</title>
		<published>2017-03-08T04:30:25+00:00</published>
		<updated>2017-03-08T03:40:17+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/an-overwiew-on-threads/" type="text/html"/>
		<id>https://nskm.xyz/posts/an-overwiew-on-threads/</id>
		<content type="html">&lt;p&gt;I&#x27;ve written something about &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;processes-introduction&#x2F;&quot;&gt;processes&lt;&#x2F;a&gt; Let&#x27;s write some notes about threads. This is not really an introduction to threads. It&#x27;s more like a little bit of introspection, so we can have an interesting perspective of what are threads.&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;what-s-really-a-thread&quot;&gt;&lt;strong&gt;What&#x27;s really a thread?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Processes each have their own address space. Threads exist as subsets of a process. Threads are just multiple workers in the same &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;processes-introduction&#x2F;&quot;&gt;virtual address space&lt;&#x2F;a&gt; all threads in a process share the same memory. They can also share open files and other resources. Within that VAS, each thread has its own ID, its own stack, its own program counter, its own independent flow of control, its own registers set. A thread is just a &lt;strong&gt;context of execution&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;threads-example.gif&quot; alt=&quot;Threads&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;em&gt;Image from &lt;a href=&quot;http:&#x2F;&#x2F;mooneegee.blogspot.sn&#x2F;2015&#x2F;01&#x2F;os-thread.html&quot;&gt;mooneegee.blogspot.sn&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Next is a c script spawning two &lt;em&gt;posix&lt;&#x2F;em&gt; threads:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define _GNU_SOURCE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;pthread.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; sleep
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;syscall.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;types.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void * &lt;&#x2F;span&gt;&lt;span&gt;say_hello(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void* &lt;&#x2F;span&gt;&lt;span&gt;data){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;str = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char*&lt;&#x2F;span&gt;&lt;span&gt;)data;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; howmany = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; r = (rand() % &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pid_t thread_id = syscall(__NR_gettid);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt;(howmany &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    sleep(r);
&lt;&#x2F;span&gt;&lt;span&gt;    howmany = howmany - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,str);
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;from thread &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; and process &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;           thread_id, getpid());
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return NULL&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_t t1,t2;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(getpid() &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;unable to get pid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The main process id is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, getpid());
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_create(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;t1,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;,say_hello,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;howdy&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_create(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;t2,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;,say_hello,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_join(t1,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_join(t2,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;If we &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;strace.1.html&quot;&gt;strace&lt;&#x2F;a&gt; the execution of our c script:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ strace -f .&#x2F;bin&#x2F;how_to_thread
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output will display lots of informations. And for what we are doing, the most interesting lines will look like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;clone(child_stack=0x7f30fa9b8ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f30fa9b99d0, tls=0x7f30fa9b9700, child_tidptr=0x7f30fa9b99d0) = 7450
&lt;&#x2F;span&gt;&lt;span&gt;Process 7450 attached
&lt;&#x2F;span&gt;&lt;span&gt;[pid  7449] clone(child_stack=0x7f30fa1b7ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f30fa1b89d0, tls=0x7f30fa1b8700, child_tidptr=0x7f30fa1b89d0) = 7451
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;the-clone-system-call&quot;&gt;&lt;strong&gt;The clone() system call:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;processes-introduction&#x2F;&quot;&gt;Processes&lt;&#x2F;a&gt; are created with the &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;fork.2.html&quot;&gt;fork()&lt;&#x2F;a&gt; system call. However, there is a separate system call, named &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;clone()&lt;&#x2F;a&gt; which is used for creating threads. It works like fork(), but it accepts a number of flags for adjusting its behavior so the child can share some parts of the parent&#x27;s execution context. Our c script made a call to clone() twice. And looking at &lt;em&gt;some&lt;&#x2F;em&gt; of the flags that have been passed, we can see that:&lt;&#x2F;p&gt;
&lt;p&gt;the caller and the child process:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;CLONE_VM: run in the &lt;strong&gt;same memory space&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;CLONE_FS: share the &lt;strong&gt;same filesystem information&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;CLONE_FILES: share the &lt;strong&gt;same file descriptor table&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;CLONE_THREAD: are placed in the &lt;strong&gt;same thread group&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;p&gt;Another interesting arguments passed to clone system call are &lt;code&gt;child_stack&lt;&#x2F;code&gt; and &lt;code&gt;tls&lt;&#x2F;code&gt;. From the man page, we can read &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;somewhere&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The child_stack argument specifies the location of the stack used by the child process.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And in &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;set_thread_area.2.html&quot;&gt;another part&lt;&#x2F;a&gt; of the man page:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;set a thread local storage (TLS) area&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Basically, we&#x27;re allocating a &lt;em&gt;personal stack&lt;&#x2F;em&gt; to each of our threads. But, we also give each thread, an access to a region of memory which is &lt;em&gt;not shared&lt;&#x2F;em&gt; with all other threads. Like one may do with Python using the &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;threading.html#thread-local-data&quot;&gt;threading.local&lt;&#x2F;a&gt; class.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gdb-to-the-rescue&quot;&gt;&lt;strong&gt;GDB to the rescue&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Let&#x27;s have a confirmation using &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gdb&#x2F;&quot;&gt;GDB&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ gdb .&#x2F;bin&#x2F;how_to_thread
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;First, we set two breakpoints, one at the start of the main function, another one at the start of the say_hello function:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;insert-breakpoints.png&quot; alt=&quot;insert breakpoints&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Then we start the debugged program: &lt;code&gt;r&lt;&#x2F;code&gt;, and list the mapped memory regions:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;info-proc-map1.png&quot; alt=&quot;info proc mappings&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So far, we see only one stack segment, the one used by the main process, that is because our threads are not yet created. Let&#x27;s continue a little bit (twice) with &lt;code&gt;c&lt;&#x2F;code&gt;, and you should be able to see something like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;info-proc-map2.png&quot; alt=&quot;info proc mappings&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This time, we can see three stacks in the same virtual address space. The ones used by our threads are &lt;code&gt;[stack:15074]&lt;&#x2F;code&gt; and &lt;code&gt;[stack:15075]&lt;&#x2F;code&gt;. GDB to inspect each thread&#x27;s stack:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;stacks.png&quot; alt=&quot;thread&#x27;s stack&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;LWP is an acronym and stands for Light Weight Process. Next to LWP is the thread ID assigned by the kernel to this thread. We see that each thread has its own stack, and inside each stack, the progress is different, while thread 3 is entering the say_hello function, thread 2 is in &lt;em&gt;nanosleep&lt;&#x2F;em&gt;. By the way nanosleep is also a &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;nanosleep.2.html&quot;&gt;system call&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here we are, a thread is indeed just a &lt;strong&gt;context of execution&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t be able to cover the whole topic as it&#x27;s not an easy and small one. So you may find &lt;em&gt;really&lt;&#x2F;em&gt; interesting the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;pthreads.7.html&quot;&gt;Pthreads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;7577&#x2F;&quot;&gt;Making Linux safe for pthreads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.linfo.org&#x2F;context_switch.html&quot;&gt;Context switch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;0xax.gitbooks.io&#x2F;linux-insides&#x2F;content&#x2F;SyncPrim&#x2F;sync-3.html&quot;&gt;Semaphores&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;turnoff.us&#x2F;geek&#x2F;dont-share-mutable-state&#x2F;&quot;&gt;The real reason not to share a mutable state&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Django single file project</title>
		<published>2017-01-12T17:17:17+00:00</published>
		<updated>2017-01-12T17:17:17+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/dsfp/" type="text/html"/>
		<id>https://nskm.xyz/posts/dsfp/</id>
		<content type="html">&lt;h4 id=&quot;disclaimer&quot;&gt;&lt;strong&gt;Disclaimer?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;The main purpose of this post is learning. Like any tool we should explore and find ways to bend it until it breaks. You should &lt;em&gt;normally&lt;&#x2F;em&gt; not use those techniques in real life projects &lt;em&gt;right&lt;&#x2F;em&gt;? For this post, I&#x27;m assuming you&#x27;re using Django 1.10.4, and Python3.6.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;single-file&quot;&gt;&lt;strong&gt;Single file?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Before reading &lt;a href=&quot;http:&#x2F;&#x2F;shop.oreilly.com&#x2F;product&#x2F;0636920032502.do&quot;&gt;Lightweight Django&lt;&#x2F;a&gt;, I never tought it was possible to build a Django project in a single python file. For that kind of stuff, I usually think, &lt;a href=&quot;http:&#x2F;&#x2F;flask.pocoo.org&#x2F;&quot;&gt;Flask&lt;&#x2F;a&gt;, or &lt;a href=&quot;http:&#x2F;&#x2F;bottlepy.org&#x2F;docs&#x2F;dev&#x2F;&quot;&gt;Bottle&lt;&#x2F;a&gt;. And in fact, there are many &lt;a href=&quot;http:&#x2F;&#x2F;codecondo.com&#x2F;14-minimal-web-frameworks-for-python&#x2F;&quot;&gt;others&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After reading the first chapter, I was a little bit disappointed. There were no Django &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.10&#x2F;topics&#x2F;db&#x2F;models&#x2F;&quot;&gt;models&lt;&#x2F;a&gt; involved in the shown example. So, I try to find out if it was possible: &lt;strong&gt;a single file Django project with at least one application containing one model&lt;&#x2F;strong&gt;. I found some interesting links on the topic. But either it was for a very old version of Django, either I was obliged to install another package besides Django. After few days reading others people code, this is what I&#x27;ve done:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;os
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sys
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.conf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;settings
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;sys.path[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] = os.path.dirname(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the current folder name will also be our app
&lt;&#x2F;span&gt;&lt;span&gt;APP_LABEL = os.path.basename(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;settings.configure(
&lt;&#x2F;span&gt;&lt;span&gt;    DEBUG=os.environ.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DEBUG&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;on&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;on&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    SECRET_KEY=os.environ.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;SECRET_KEY&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, os.urandom(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;)),
&lt;&#x2F;span&gt;&lt;span&gt;    ALLOWED_HOSTS=os.environ.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ALLOWED_HOSTS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;localhost&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;,&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    ROOT_URLCONF=__name__,
&lt;&#x2F;span&gt;&lt;span&gt;    MIDDLEWARE=[
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.security.SecurityMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.sessions.middleware.SessionMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.common.CommonMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.csrf.CsrfViewMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth.middleware.AuthenticationMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages.middleware.MessageMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.clickjacking.XFrameOptionsMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.locale.LocaleMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;    INSTALLED_APPS=[
&lt;&#x2F;span&gt;&lt;span&gt;        APP_LABEL,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.admin&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.contenttypes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.sessions&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.staticfiles&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;    STATIC_URL=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;static&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    STATICFILES_DIRS=[
&lt;&#x2F;span&gt;&lt;span&gt;        os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;static&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    ],
&lt;&#x2F;span&gt;&lt;span&gt;    STATIC_ROOT=os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;static_root&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    MEDIA_ROOT=os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;media&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    MEDIA_URL=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;media&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    TEMPLATES=[
&lt;&#x2F;span&gt;&lt;span&gt;        {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;BACKEND&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.backends.django.DjangoTemplates&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DIRS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;templates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),],
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;APP_DIRS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;OPTIONS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;context_processors&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.debug&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.i18n&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.request&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth.context_processors.auth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.tz&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages.context_processors.messages&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                ],
&lt;&#x2F;span&gt;&lt;span&gt;            },
&lt;&#x2F;span&gt;&lt;span&gt;        },
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;    DATABASES={
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;default&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ENGINE&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.db.backends.sqlite3&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;NAME&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;db.sqlite3&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        },
&lt;&#x2F;span&gt;&lt;span&gt;    REST_FRAMEWORK={
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DEFAULT_PERMISSION_CLASSES&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework.permissions.IsAdminUser&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;PAGE_SIZE&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;django
&lt;&#x2F;span&gt;&lt;span&gt;django.setup()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.contrib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;admin
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create your models here.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Author(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Book(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    author = models.ForeignKey(Author, related_name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;books&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    title = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;400&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;admin.site.register(Book)
&lt;&#x2F;span&gt;&lt;span&gt;admin.site.register(Author)
&lt;&#x2F;span&gt;&lt;span&gt;admin.autodiscover()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;serializers
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;BookSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = Book
&lt;&#x2F;span&gt;&lt;span&gt;        fields = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;__all__&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;viewsets
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;BooksViewSet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.ReadOnlyModelViewSet&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Book.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = BookSerializer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.conf.urls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;url, include
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;routers
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.http &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;HttpResponse
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.contrib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;admin
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;router = routers.DefaultRouter()
&lt;&#x2F;span&gt;&lt;span&gt;router.register(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;books&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, BooksViewSet)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;index(request):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;HttpResponse(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;urlpatterns = [
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;admin&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, admin.site.urls),
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, index, name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;homepage&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;api&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, include(router.urls)),
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;api-auth&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, include(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework.urls&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,\
&lt;&#x2F;span&gt;&lt;span&gt;                                   namespace=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.core.wsgi &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;get_wsgi_application
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.core.management &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;execute_from_command_line
&lt;&#x2F;span&gt;&lt;span&gt;    execute_from_command_line(sys.argv)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    get_wsgi_application()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Everything related to &lt;a href=&quot;http:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;&quot;&gt;Django REST Framework&lt;&#x2F;a&gt; is not mandatory. I was looking for &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;979&#x2F;&quot;&gt;interesting links&lt;&#x2F;a&gt; over the internet, and I found this question on &lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;32866578&#x2F;4055832&quot;&gt;StackOverflow&lt;&#x2F;a&gt;. I saw this as an opportunity to kill two birds with one stone.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The above script was saved in a file named &lt;code&gt;single.py&lt;&#x2F;code&gt; in a folder named &lt;code&gt;lwdj&lt;&#x2F;code&gt;. But you can do as you feel, as soon as you respect the name of the file and the name of the current folder. The rest is known story:&lt;&#x2F;p&gt;
&lt;p&gt;Make the migrations for our application:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py makemigrations lwdj
&lt;&#x2F;span&gt;&lt;span&gt;Migrations for &amp;#39;lwdj&amp;#39;:
&lt;&#x2F;span&gt;&lt;span&gt;  migrations&#x2F;0001_initial.py:
&lt;&#x2F;span&gt;&lt;span&gt;    - Create model Author
&lt;&#x2F;span&gt;&lt;span&gt;    - Create model Book
&lt;&#x2F;span&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%) ⤷
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Run the migrations:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py migrate
&lt;&#x2F;span&gt;&lt;span&gt;Operations to perform:
&lt;&#x2F;span&gt;&lt;span&gt;  Apply all migrations: admin, auth, contenttypes, lwdj, sessions
&lt;&#x2F;span&gt;&lt;span&gt;Running migrations:
&lt;&#x2F;span&gt;&lt;span&gt;  Applying contenttypes.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying admin.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying admin.0002_logentry_remove_auto_add... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying contenttypes.0002_remove_content_type_name... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0002_alter_permission_name_max_length... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0003_alter_user_email_max_length... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0004_alter_user_username_opts... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0005_alter_user_last_login_null... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0006_require_contenttypes_0002... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0007_alter_validators_add_error_messages... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0008_alter_user_username_max_length... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying lwdj.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying sessions.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Create a super user and run the server:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py createsuperuser
&lt;&#x2F;span&gt;&lt;span&gt;Username (leave blank to use &amp;#39;nsukami&amp;#39;):
&lt;&#x2F;span&gt;&lt;span&gt;Email address: nsukami@gmail.com
&lt;&#x2F;span&gt;&lt;span&gt;Password:
&lt;&#x2F;span&gt;&lt;span&gt;Password (again):
&lt;&#x2F;span&gt;&lt;span&gt;Superuser created successfully.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py runserver
&lt;&#x2F;span&gt;&lt;span&gt;Performing system checks...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;System check identified no issues (0 silenced).
&lt;&#x2F;span&gt;&lt;span&gt;January 12, 2017 - 18:52:57
&lt;&#x2F;span&gt;&lt;span&gt;Django version 1.10.4, using settings None
&lt;&#x2F;span&gt;&lt;span&gt;Starting development server at http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;Quit the server with CONTROL-C.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;so-what-have-we-learned-here&quot;&gt;&lt;strong&gt;So, what have we learned here?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Yes, that is not how you are supposed to use Django. But we were able to learn few things.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;projects-and-applications&quot;&gt;&lt;strong&gt;Projects and applications&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Somewhere in the Django documentation related to &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.10&#x2F;ref&#x2F;applications&#x2F;#projects-and-applications&quot;&gt;projects and applications&lt;&#x2F;a&gt;, we can read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;There&#x27;s no restriction that a project package can&#x27;t also be considered an application and have models, etc. (which would require adding it to INSTALLED_APPS).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We can double check using the &lt;code&gt;tree&lt;&#x2F;code&gt; command:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ tree
&lt;&#x2F;span&gt;&lt;span&gt;.
&lt;&#x2F;span&gt;&lt;span&gt;├── activate -&amp;gt; &#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;bin&#x2F;activate
&lt;&#x2F;span&gt;&lt;span&gt;├── db.sqlite3
&lt;&#x2F;span&gt;&lt;span&gt;├── Makefile
&lt;&#x2F;span&gt;&lt;span&gt;├── media
&lt;&#x2F;span&gt;&lt;span&gt;├── migrations
&lt;&#x2F;span&gt;&lt;span&gt;│   ├── 0001_initial.py
&lt;&#x2F;span&gt;&lt;span&gt;│   ├── __init__.py
&lt;&#x2F;span&gt;&lt;span&gt;│   └── __pycache__
&lt;&#x2F;span&gt;&lt;span&gt;│       └── __init__.cpython-36.pyc
&lt;&#x2F;span&gt;&lt;span&gt;├── single.py
&lt;&#x2F;span&gt;&lt;span&gt;├── static
&lt;&#x2F;span&gt;&lt;span&gt;│   └── site.css
&lt;&#x2F;span&gt;&lt;span&gt;├── static_root
&lt;&#x2F;span&gt;&lt;span&gt;└── templates
&lt;&#x2F;span&gt;&lt;span&gt;    └── home.html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;the-django-setup-method&quot;&gt;&lt;strong&gt;The django.setup() method&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Reading The Fabulous &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;dev&#x2F;ref&#x2F;applications&#x2F;#how-applications-are-loaded&quot;&gt;Manual&lt;&#x2F;a&gt;, we learn that, this method configures Django by loading the settings, but also:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;When Django starts, django.setup() is responsible for populating the application registry.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Let&#x27;s start a shell using the command &lt;code&gt;python single.py shell&lt;&#x2F;code&gt;, and let&#x27;s check the application registry:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.apps &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;apps
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; apps.ready
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; apps.get_app_configs()
&lt;&#x2F;span&gt;&lt;span&gt;odict_values([&amp;lt;AppConfig: lwdj&amp;gt;, &amp;lt;AdminConfig: admin&amp;gt;, &amp;lt;AuthConfig: auth&amp;gt;, &amp;lt;ContentTypesConfig: contenttypes&amp;gt;, &amp;lt;SessionsConfig: sessions&amp;gt;, &amp;lt;MessagesConfig: messages&amp;gt;, &amp;lt;StaticFilesConfig: staticfiles&amp;gt;, &amp;lt;AppConfig: rest_framework&amp;gt;])
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c = apps.get_app_config(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.module
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;module &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;(namespace)&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.path
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;GITHUB&#x2F;how_tos&#x2F;how_to_django&#x2F;lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.verbose_name
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.name
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.label
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;c.models: print(m)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;author
&lt;&#x2F;span&gt;&lt;span&gt;book
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Neat!
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We also &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;dev&#x2F;ref&#x2F;applications&#x2F;#how-applications-are-loaded&quot;&gt;read&lt;&#x2F;a&gt; that:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;At this stage, your code shouldn&#x27;t import any models!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is exactly why our models, and everything related to them, do not appear before those 2 lines of code.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;django
&lt;&#x2F;span&gt;&lt;span&gt;django.setup()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Doing otherwise, raises the &lt;code&gt;AppRegistryNotReady&lt;&#x2F;code&gt; exception:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py runserver
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;single.py&amp;quot;, line 90, in &amp;lt;module&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    class Author(models.Model):
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;django&#x2F;db&#x2F;models&#x2F;base.py&amp;quot;, line 105, in __new__
&lt;&#x2F;span&gt;&lt;span&gt;    app_config = apps.get_containing_app_config(module)
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;django&#x2F;apps&#x2F;registry.py&amp;quot;, line 237, in get_containing_app_config
&lt;&#x2F;span&gt;&lt;span&gt;    self.check_apps_ready()
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;django&#x2F;apps&#x2F;registry.py&amp;quot;, line 124, in check_apps_ready
&lt;&#x2F;span&gt;&lt;span&gt;    raise AppRegistryNotReady(&amp;quot;Apps aren&amp;#39;t loaded yet.&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;django.core.exceptions.AppRegistryNotReady: Apps aren&amp;#39;t loaded yet.
&lt;&#x2F;span&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;installed-applications&quot;&gt;&lt;strong&gt;Installed applications&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;I have not yet fully understood this part. &lt;code&gt;APP_LABEL&lt;&#x2F;code&gt; is actually containing the name of the current directory. By putting &lt;code&gt;APP_LABEL&lt;&#x2F;code&gt; inside &lt;code&gt;INSTALLED_APPS&lt;&#x2F;code&gt;, Django was able to find all the Django models existing inside the current directory:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))
&lt;&#x2F;span&gt;&lt;span&gt;sys.path[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] = os.path.dirname(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;APP_LABEL = os.path.basename(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;{{&amp;lt; &#x2F;highlight &amp;gt;}}
&lt;&#x2F;span&gt;&lt;span&gt;{{&amp;lt; highlight python &amp;gt;}}
&lt;&#x2F;span&gt;&lt;span&gt;    INSTALLED_APPS=[
&lt;&#x2F;span&gt;&lt;span&gt;        APP_LABEL,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.admin&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.contenttypes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.sessions&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.staticfiles&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;app-label&quot;&gt;&lt;strong&gt;App label&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;All our models were created outside of a &lt;code&gt;models.py&lt;&#x2F;code&gt; file. They&#x27;re not even in a &lt;em&gt;real&lt;&#x2F;em&gt; Django application. So we were obliged to tell them which application they belongs to. This is done using the &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.10&#x2F;ref&#x2F;models&#x2F;options&#x2F;#app-label&quot;&gt;app_label&lt;&#x2F;a&gt; attribute of the internal &lt;code&gt;class Meta&lt;&#x2F;code&gt; of Django models.
{{&amp;lt; highlight python &amp;gt;}}
class Author(models.Model):
name = models.CharField(max_length=200)
class Meta:
app_label = APP_LABEL&lt;&#x2F;p&gt;
&lt;p&gt;class Book(models.Model):
author = models.ForeignKey(Author, related_name=&#x27;books&#x27;)
title = models.CharField(max_length=400)
class Meta:
app_label = APP_LABEL
{{&amp;lt; &#x2F;highlight &amp;gt;}}
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Really hope you learnt something. Also, I would not be able to write this post, without following the &lt;em&gt;StackTrace&lt;&#x2F;em&gt; leaved by the people who were there before me. A huge thanks to them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dotmobo.github.io&#x2F;django-minimaliste.html&quot;&gt;Créer une application django minimaliste&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;blog.fahhem.com&#x2F;2011&#x2F;10&#x2F;django-models-without-apps-or-everything-django-truly-in-a-single-file&#x2F;&quot;&gt;Django Models without Apps OR Everything Django Truly in a Single File&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zenwalker&#x2F;django-micro&quot;&gt;Django as microframework&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Make</title>
		<published>2016-11-25T00:00:00+00:00</published>
		<updated>2016-11-25T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/mk/" type="text/html"/>
		<id>https://nskm.xyz/posts/mk/</id>
		<content type="html">&lt;p&gt;if you have some &lt;strong&gt;complex and esoteric shell commands&lt;&#x2F;strong&gt; that you have to run on a regular basis, it can be convenient to just package them up &lt;em&gt;somewhere&lt;&#x2F;em&gt;, so you don&#x27;t have to &lt;strong&gt;remember them&lt;&#x2F;strong&gt; or &lt;strong&gt;type them out every time&lt;&#x2F;strong&gt;. &lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Why, I don&#x27;t use Makefiles more often? Even though I know I should. One of the reason may be because, as an Emacs user, automating simple tasks is &lt;em&gt;funny&lt;&#x2F;em&gt; using &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;manual&#x2F;html_node&#x2F;elisp&#x2F;&quot;&gt;Emacs Lisp&lt;&#x2F;a&gt;. Following are simple elisp functions I use to compile a C file, nothing extraordinary:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;lisp&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-lisp &quot;&gt;&lt;code class=&quot;language-lisp&quot; data-lang=&quot;lisp&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;defun &lt;&#x2F;span&gt;&lt;span&gt;my-c-save-compile ()
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Save, and compile c file.&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  (interactive)
&lt;&#x2F;span&gt;&lt;span&gt;  (save-buffer)
&lt;&#x2F;span&gt;&lt;span&gt;  (compile
&lt;&#x2F;span&gt;&lt;span&gt;   (format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;cc -Wall -Wextra -pedantic -std=c11 -g %s -o .&#x2F;bin&#x2F;%s&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;           (buffer-file-name)
&lt;&#x2F;span&gt;&lt;span&gt;           (file-name-base (buffer-file-name)))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;defun &lt;&#x2F;span&gt;&lt;span&gt;my-c-run ()
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Run c code.&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  (interactive)
&lt;&#x2F;span&gt;&lt;span&gt;  (compile (format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;bin&#x2F;%s&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                   (file-name-base (buffer-file-name)))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Another reason I don&#x27;t use Makefiles more often could be, the &lt;a href=&quot;http:&#x2F;&#x2F;www.tldp.org&#x2F;LDP&#x2F;Bash-Beginners-Guide&#x2F;html&#x2F;Bash-Beginners-Guide.html&quot;&gt;Bourne Again Shell&lt;&#x2F;a&gt;. I find it easier to quickly write shell aliases for repetitive tasks. The following is some aliases I &lt;em&gt;sometimes&lt;&#x2F;em&gt; use whenever I&#x27;m doing &lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt; development:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;sh
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# my weird aliases
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_runserver=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py runserver&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_shell=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py shell&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_shellp=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py shell_plus&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_make=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py makemigrations&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_mig=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py migrate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_csu=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py createsuperuser&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_smtpd=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python -m smtpd -n -c DebuggingServer localhost:1025&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Make do have a reputation for being complex. Indeed, it can be very &lt;a href=&quot;http:&#x2F;&#x2F;okmij.org&#x2F;ftp&#x2F;Computation&#x2F;#Makefile-functional&quot;&gt;esoteric&lt;&#x2F;a&gt;. The full &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;make&#x2F;manual&#x2F;make.html&quot;&gt;manual&lt;&#x2F;a&gt; is a 183 pages. Fortunately, you can ignore most of this, Make can be used in a very simple and incredibly useful way. &lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The following, is a Makefile I sometimes use in replacement of the shell aliases above:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;make&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-make &quot;&gt;&lt;code class=&quot;language-make&quot; data-lang=&quot;make&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Makefile for (the project)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Nsukami
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# November 2016
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;SHELL := &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PROJECT := &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;tas&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PYTHON_BIN := &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;VIRTUAL_ENV&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;bin&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEV_SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROJECT&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.settings.dev&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PROD_SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROJECT&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.settings.prod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TEST_SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROJECT&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.settings.test&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;shell dirname &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;realpath &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;lastword &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;MAKEFILE_LIST&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;))))&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PMP = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;python manage.py&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# if not on prod server, use dev settings
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;ifneq &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;shell uname -n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,phobos)
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;DEV_SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROD_SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;endif
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: all - Default target. Does nothing.
&lt;&#x2F;span&gt;&lt;span&gt;all:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Nothing to do by default. Try &amp;#39;make help&amp;#39;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: help - Show list of targets + description
&lt;&#x2F;span&gt;&lt;span&gt;help:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;egrep &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;^# target:&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Mm&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;akefile
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: init - Install that a dev needs to get up and running.
&lt;&#x2F;span&gt;&lt;span&gt;init: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;bootstrap.sh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    cd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;sudo .&#x2F;bootstrap.sh
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: clean - remove all useless files
&lt;&#x2F;span&gt;&lt;span&gt;clean: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clean-pyc clean-build&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: clean-pyc - remove all auto generated files
&lt;&#x2F;span&gt;&lt;span&gt;clean-pyc:
&lt;&#x2F;span&gt;&lt;span&gt;    find . -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*.pyc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -exec rm --force {} +
&lt;&#x2F;span&gt;&lt;span&gt;    find . -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*.pyo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -exec rm --force {} +
&lt;&#x2F;span&gt;&lt;span&gt;    find . -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*~&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -exec rm --force  {} +
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: clean-build - remove all auto generated folders
&lt;&#x2F;span&gt;&lt;span&gt;clean-build:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive build&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive dist&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive htmlcov
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive .coverage
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.egg-info
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: translate - calls the &amp;quot;makemessages&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;translate:
&lt;&#x2F;span&gt;&lt;span&gt;    cd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &amp;amp;&amp;amp; $(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;makemessages --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -a
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: test - calls the &amp;quot;test&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;test:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;test --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;TEST_SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: run - calls the &amp;quot;runserver&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;run:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;runserver --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: update - install (and update) pip requirements
&lt;&#x2F;span&gt;&lt;span&gt;update:
&lt;&#x2F;span&gt;&lt;span&gt;    pip install -U -r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;requirements&#x2F;dev.txt
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: collect - calls the &amp;quot;collectstatic&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;collect:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;collectstatic --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; --noinput
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: rebuild - rebuild tables from models
&lt;&#x2F;span&gt;&lt;span&gt;rebuild:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;makemigrations --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;migrate --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: deploy - let make take care of deployment
&lt;&#x2F;span&gt;&lt;span&gt;deploy:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Should I call fabric here?
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;.ONESHELL:
&lt;&#x2F;span&gt;&lt;span&gt;.PHONY: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;all help translate test clean update collect rebuild run clean-pyc clean-build clean init&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Finally, the other reason, and probably the main reason I don&#x27;t use Makefiles more often, it&#x27;s because of &lt;a href=&quot;http:&#x2F;&#x2F;www.fabfile.org&#x2F;&quot;&gt;Fabric&lt;&#x2F;a&gt;. Following is a fabfile more or less doing the same thing as the Makefile above:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# -*- coding: utf-8 -*- #
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; fabric commands &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;fabric.api &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;env, sudo, cd, local, task, run
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;fabric.contrib.project &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;project
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;os
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Local path configuration (can be absolute or relative to fabfile)
&lt;&#x2F;span&gt;&lt;span&gt;env.hosts = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;localhost&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;env.use_ssh_config = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True
&lt;&#x2F;span&gt;&lt;span&gt;env.ssh_config_path = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;.ssh&#x2F;config&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;env.owner = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;nsukami&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PROJECT = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;tas&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEV_SETTINGS = PROJECT + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.settings.dev&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;PROD_SETTINGS = PROJECT + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.settings.prod&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;TEST_SETTINGS = PROJECT + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.settings.test&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))
&lt;&#x2F;span&gt;&lt;span&gt;PMP = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python manage.py &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;uname():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Prints information about the host. &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;uname -n&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;uname() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;is not &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;phobos&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = DEV_SETTINGS
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = PROD_SETTINGS
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;init():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;init - Install that a dev needs to get up and running.&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;cd(BASE_DIR):
&lt;&#x2F;span&gt;&lt;span&gt;        sudo(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;bootstrap.sh&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;clean():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;clean - remove all useless files&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    clean_pyc()
&lt;&#x2F;span&gt;&lt;span&gt;    clean_build()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;clean_pyc():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;# clean-pyc - remove all auto generated files&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;find . -name &amp;#39;*.pyc&amp;#39; -exec rm --force &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; +&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;find . -name &amp;#39;*.pyo&amp;#39; -exec rm --force &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; +&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;find . -name &amp;#39;*~&amp;#39; -exec rm --force  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; +&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;clean_build():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;clean-build - remove all auto generated folders&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive build&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive dist&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive htmlcov&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive .coverage&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive *.egg-info&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;translate():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;translate - calls the &amp;#39;makemessages&amp;#39; django command&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;cd(BASE_DIR):
&lt;&#x2F;span&gt;&lt;span&gt;        cmd = PMP + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;makemessages --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; -a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(SETTINGS)
&lt;&#x2F;span&gt;&lt;span&gt;        local(cmd)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;test():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;test - calls the &amp;#39;test&amp;#39; django command&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cmd = PMP + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;test --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(SETTINGS)
&lt;&#x2F;span&gt;&lt;span&gt;    local(cmd)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;runserver():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;run - calls the &amp;#39;runserver&amp;#39; django command&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cmd = PMP + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;runserver --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(SETTINGS)
&lt;&#x2F;span&gt;&lt;span&gt;    local(cmd)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;update():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;update - install (and update) pip requirements&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cmd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;pip install -U -r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&#x2F;requirements&#x2F;dev.txt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;    local(cmd)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;We see that Fabric &lt;em&gt;can&lt;&#x2F;em&gt; be used as a build tool even though it isn&#x27;t one. It is easy to read and write, especially for a Python developer. The drawback may be, it does require Python to run. &lt;em&gt;Seriously, who cares?&lt;&#x2F;em&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;New year resolution: &lt;strong&gt;using Makefiles more often.&lt;&#x2F;strong&gt;
&lt;br&gt;&lt;br&gt;
More on the topic:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;make&#x2F;manual&#x2F;make.html&quot;&gt;Make&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=5276339&quot;&gt;Make alternatives&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_build_automation_software&quot;&gt;List of build automation software&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>How to create processes</title>
		<published>2016-08-22T03:40:17+00:00</published>
		<updated>2016-08-22T03:40:17+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/process-creation/" type="text/html"/>
		<id>https://nskm.xyz/posts/process-creation/</id>
		<content type="html">&lt;p&gt;We&#x27;ve seen &lt;a href=&quot;&#x2F;on-processes.md&quot;&gt;processes&lt;&#x2F;a&gt;, We&#x27;ve said lots of things about processes, but we did not talk about process creation. Let&#x27;s see how to create a process in C, in &lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;&quot;&gt;Golang&lt;&#x2F;a&gt;, and in &lt;a href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;en-US&#x2F;&quot;&gt;Rustlang&lt;&#x2F;a&gt; &lt;em&gt;&lt;strong&gt;Disclaimer:&lt;&#x2F;strong&gt; I&#x27;m not doing a comparison to find out which one is better than the other. I just want to explore how the same task can be done using different approaches.&lt;br&gt;&lt;br&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fork-and-exec&quot;&gt;&lt;strong&gt;Fork and Exec:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;UNIX processes are created using the fork() &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;System_call&quot;&gt;system call&lt;&#x2F;a&gt;. Fork is the primary method of process creation on Unix-like operating systems.  Fork is the system call that the parent process uses to &amp;quot;divide&amp;quot; itself, to &amp;quot;fork&amp;quot; into two identical processes. The child process will be the exact copy of the parent except for the return value.&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Exec_(system_call)&quot;&gt;exec()&lt;&#x2F;a&gt; system call and its family of functions are almost always used with fork(). The exec() syscall and the like overwrite the current [stackframe]({{&amp;lt; ref on-processes &amp;gt;}})with the name of the application passed to it.&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;c&quot;&gt;&lt;strong&gt;C:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In C, there is nothing special to do, contrary to Golang and Rustlang. You just really call fork(), then exec(), simple and direct. The following, is an example written in C:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;types.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;wait.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;fork_and_execute();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  fork_and_execute();
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;fork_and_execute() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; pid, status;
&lt;&#x2F;span&gt;&lt;span&gt;  pid = fork();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; if pid equals 0,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(pid == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; we&amp;#39;re dealing with the child process
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;I am the child process, my pid is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, getpid());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; the program we want to execute
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;cmd[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; execvp will search for ls on $PATH
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(execvp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd, cmd) &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; catch any error that may occur during execution
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: exec failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd);
&lt;&#x2F;span&gt;&lt;span&gt;      exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; returned pid is -1, fork operation failed
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(pid &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: forking child process failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;fork&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; The wait system-call blocks the parent process
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and waits for the child-process to end.
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(wait(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;status) != pid){}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;go&quot;&gt;&lt;strong&gt;Go:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In Go, it is recommended to use the &lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;os&#x2F;exec&#x2F;&quot;&gt;exec&lt;&#x2F;a&gt; package. It runs external commands, and wraps &lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;os&#x2F;#StartProcess&quot;&gt;os.StartProcess&lt;&#x2F;a&gt; function for you. Following, is the previous example, this time written in Golang:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;go&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-go &quot;&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;package &lt;&#x2F;span&gt;&lt;span&gt;main
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;syscall&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;os&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;os&#x2F;exec&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; check if ls command exists in the PATH
&lt;&#x2F;span&gt;&lt;span&gt;    binary, lookErr := exec.LookPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;lookErr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;!= nil &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        panic(lookErr)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; the program we want to execute
&lt;&#x2F;span&gt;&lt;span&gt;    args := []string{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; fork new process and execute our program
&lt;&#x2F;span&gt;&lt;span&gt;    execErr := syscall.Exec(binary, args, os.Environ())
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; catch error if any
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;execErr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;!= nil &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        panic(execErr)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;rust&quot;&gt;&lt;strong&gt;Rust:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In Rust, we have &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;process&#x2F;struct.Command.html&quot;&gt;std::process::Command&lt;&#x2F;a&gt;. It is is a type that acts as a process builder and provides fine-grained control over how the new process should be spawned. If we browse the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;std&#x2F;process.rs.html#521&quot;&gt;source code&lt;&#x2F;a&gt;, we can read beginning line 521:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Constructs a new &lt;code&gt;Command&lt;&#x2F;code&gt; for launching the program at&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;path &lt;code&gt;program&lt;&#x2F;code&gt;, with the following default configuration:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;No arguments to the program&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Inherit the current process&#x27;s environment&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Inherit the current process&#x27;s working directory&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Inherit stdin&#x2F;stdout&#x2F;stderr for &lt;code&gt;spawn&lt;&#x2F;code&gt; or &lt;code&gt;status&lt;&#x2F;code&gt;, but create pipes for &lt;code&gt;output&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;p&gt;Basically, it behave a little bit like a call to fork(), followed by a call to exec(). Let&#x27;s rewrite the previous example in Rust:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::process::Command;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = Command::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .arg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .arg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .arg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .output()
&lt;&#x2F;span&gt;&lt;span&gt;                     .expect(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls command failed to start&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;stdout: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, String::from_utf8_lossy(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;output.stdout));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;process&#x2F;struct.Command.html#method.output&quot;&gt;output&lt;&#x2F;a&gt; function executes the command as a child process, waiting for it to finish and collecting all of its output. By default, stdin, stdout and stderr are captured (and used to provide the resulting output).&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;option&#x2F;enum.Option.html#method.expect&quot;&gt;expect&lt;&#x2F;a&gt; function is used for quick and dirty error handling. &lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;strace-trace-system-calls-and-signals&quot;&gt;&lt;strong&gt;Strace, trace system calls and signals:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Somewhere in the strace&#x27;s manual page, we can read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Trace child processes as they are created by currently traced processes as a result of the fork(2), vfork(2) and clone(2) system calls. &lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If everything went normally during the execution of our scripts, we should see, in the strace&#x27;s output, lots of system calls, the most important ones being a call to &lt;strong&gt;clone()&lt;&#x2F;strong&gt;, followed by a call to &lt;strong&gt;exec()&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;4714  clone(child_stack=0, flags=CLONE_CHILD_CLEARTID&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;CLONE_CHILD_SETTID&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;SIGCHLD, child_tidptr=0x7fac5d28da90) = 4715
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;7564  execve(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;bin&#x2F;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; 74 vars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;] &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;unfinished ...&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;fork() was the original UNIX system call. Only used to create new processes, not threads. Also, it is portable.&lt;&#x2F;p&gt;
&lt;p&gt;clone() is a new, versatile system call which can be used to create, depending on the passed option, a UNIX process, or a POSIX thread, or something in between, or something completely different. I invite you to &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;Read The Fabulous Manual&lt;&#x2F;a&gt; about clone().&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t really know if there is something else you can read to learn more on this topic:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;fork.2.html&quot;&gt;Fork&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;exec.3.html&quot;&gt;Exec&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;Clone&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;strace.1.html&quot;&gt;Strace&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Processes</title>
		<published>2016-08-09T03:40:17+00:00</published>
		<updated>2016-08-09T03:40:17+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/processes-introduction/" type="text/html"/>
		<id>https://nskm.xyz/posts/processes-introduction/</id>
		<content type="html">&lt;p&gt;As a Debian user, I often want to see the active processes, sometimes, I want to kill them. I know how to launch a new process, inside my Python scripts. But what is a process?&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;A process is the execution context of a running program. When an executable program is read into memory by the kernel and executed, it becomes a process. Processes are dynamic entities, they are constantly changing as their machine code instructions are executed by the CPU. &lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;With the exception of the &lt;code&gt;init process&lt;&#x2F;code&gt;, every process is the child of another process. And every process has the potential to be the parent of another process. The following is a small C program that will print the current process ID and the corresponding parent process ID:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main (){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; ch;
&lt;&#x2F;span&gt;&lt;span&gt;  printf (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The process ID is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) getpid ());
&lt;&#x2F;span&gt;&lt;span&gt;  printf (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The parent process ID is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) getppid ());
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;( ch != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&amp;amp; ch != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    ch = getchar();
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After execution, you should see something like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;~
&lt;&#x2F;span&gt;&lt;span&gt;+-&amp;gt; .&#x2F;bin&#x2F;ex1
&lt;&#x2F;span&gt;&lt;span&gt;The process ID is 11147
&lt;&#x2F;span&gt;&lt;span&gt;The parent process ID is 9552
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a name=&quot;vas&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;virtual-address-space&quot;&gt;&lt;strong&gt;Virtual address space?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A virtual address space, &lt;code&gt;VAS&lt;&#x2F;code&gt;, is the set of ranges of virtual addresses available to a process. The virtual address space is what a process sees when it executes. A process works with and only sees VAS. The operating system handles mapping VAS to real storage so that this is invisible to the running program.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;We need VAS to prevent process A and process B from writing&#x2F;reading in the same memory addresses. VAS is a way to achieve &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Process_isolation&quot;&gt;process isolation&lt;&#x2F;a&gt;. With VAS, several programs could write to memory location at the same address without stepping over each others results.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;0d8ce4ec2436983400.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;p&gt;&lt;em&gt;Image from &lt;a href=&quot;http:&#x2F;&#x2F;www.tenouk.com&#x2F;ModuleW_files&#x2F;ccompilerlinker007.png&quot;&gt;tenouk.com&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;what-s-inside-vas&quot;&gt;&lt;strong&gt;What&#x27;s inside VAS?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;VAS&lt;&#x2F;code&gt;, is the set of ranges of virtual addresses available to a process, so what is inside a VAS? A typical memory representation of process consists of following sections:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stack:&lt;&#x2F;strong&gt;&lt;br&gt;
VAS section that is used for several related purposes, the main one being to keep track of the point to which each active subroutine should return control when it finishes executing. The return address is pushed onto the stack by the caller. When it finishes, the called subroutine, pops the return address off the stack and transfers control to that address. &lt;br&gt;&lt;br&gt;That section also stores temporary variables created by each function inside the program. The stack is a LIFO data structure, managed and optimized by the CPU quite closely. Every time a function declares a new variable, it is &amp;quot;pushed&amp;quot; onto the stack, you don&#x27;t have to allocate the needed memory by hand. Then every time a function exits, all of the variables pushed onto the stack by that function, are freed for you. Once a stack variable is freed, that region of memory becomes available for other stack variables.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Heap:&lt;&#x2F;strong&gt;&lt;br&gt;
VAS section where dynamic memory allocation usually takes place. Unlike the Stack, this part of the VAS is not managed automatically for you, and is not as tightly managed by the CPU. You are in charge of allocating memory on the heap. You are also responsible for deallocating that memory once you don&#x27;t need it any more. If you fail to do this, your program will have what is known as a memory leak.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialized Data Segment:&lt;&#x2F;strong&gt;&lt;br&gt;
Or simply, Data Segment. VAS section, which contains the global and static variables that are initialized by the programmer. The size of this segment is determined by the size of the values in the program&#x27;s source code, and does not change at run time.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Uninitialized (bss) Data Segment:&lt;&#x2F;strong&gt; &lt;br&gt;
VAS section that contains all global and static variables that are initialized to zero or do not have explicit initialization in the programer&#x27;s source code.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Text (code) Segment:&lt;&#x2F;strong&gt;&lt;br&gt;
VAS section that contains machine instructions of the program. Those machine instructions can be thought of as the text of a novel: It tells the story of what the program does.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;how-to-do-some-introspection&quot;&gt;&lt;strong&gt;How to do some introspection?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;How do we learn about the memory layout of a running process? How do we look at how program are laid out in memory?&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Directly from &#x2F;proc&#x2F;PID&#x2F;maps:&lt;br&gt;&lt;&#x2F;strong&gt;
You can directly ask to the process information pseudo-filesystem: &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man5&#x2F;proc.5.html&quot;&gt;proc&lt;&#x2F;a&gt;. Let&#x27;s see the output of &lt;code&gt;cat &#x2F;proc&#x2F;6026&#x2F;maps&lt;&#x2F;code&gt;. Here &lt;code&gt;6026&lt;&#x2F;code&gt; is the PID of a running process on my Debian:&lt;br&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;00400000-00401000 r-xp 00000000 08:05 3181468            &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;00600000-00601000 rw-p 00000000 08:05 3181468            &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;01698000-016b9000 rw-p 00000000 00:00 0                  [heap]
&lt;&#x2F;span&gt;&lt;span&gt;7f747118a000-7f747132c000 r-xp 00000000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f747132c000-7f747152b000 ---p 001a2000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f747152b000-7f747152f000 r--p 001a1000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f747152f000-7f7471531000 rw-p 001a5000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471531000-7f7471535000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7f7471535000-7f7471555000 r-xp 00000000 08:01 130924     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471734000-7f7471737000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7f7471752000-7f7471755000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7f7471755000-7f7471756000 r--p 00020000 08:01 130924     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471756000-7f7471757000 rw-p 00021000 08:01 130924     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471757000-7f7471758000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7ffc4d89b000-7ffc4d8bc000 rw-p 00000000 00:00 0          [stack]
&lt;&#x2F;span&gt;&lt;span&gt;7ffc4d99b000-7ffc4d99d000 r-xp 00000000 00:00 0          [vdso]
&lt;&#x2F;span&gt;&lt;span&gt;7ffc4d99d000-7ffc4d99f000 r--p 00000000 00:00 0          [vvar]
&lt;&#x2F;span&gt;&lt;span&gt;ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0  [vsyscall]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
The Heap segment and the Stack segment are labelled, easy. The addresses are displayed from the lowest `00400000`, to the highest `ffffffffff601000`. The first segment, `00400000-00401000`, is read-only and executable, so, this is the Code segment. We know that between the Code segment, and the Heap segment, there is the Data segment. If you don&#x27;t want to browse the `&#x2F;proc` directory, there is also the [pmap](http:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;1&#x2F;pmap) command you can use to report the memory map of a process.
&lt;br&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Using the GNU debugger:&lt;&#x2F;strong&gt;
GDB, the &lt;em&gt;awesome&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gdb&#x2F;&quot;&gt;GNU Project debugger&lt;&#x2F;a&gt;, allows you, among others things, to see what is going on &lt;code&gt;inside&lt;&#x2F;code&gt; a running process. For example, from the gdb prompt, you can type &lt;code&gt;info proc mappings&lt;&#x2F;code&gt; to see the current address mapping:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;process 8460
&lt;&#x2F;span&gt;&lt;span&gt;Mapped address spaces:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        Start Addr           End Addr     Size   Offset objfile
&lt;&#x2F;span&gt;&lt;span&gt;          0x400000           0x401000   0x1000      0x0 &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;          0x600000           0x601000   0x1000      0x0 &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;          0x601000           0x622000  0x21000      0x0 [heap]
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7a31000     0x7ffff7bd3000 0x1a2000      0x0 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7bd3000     0x7ffff7dd2000 0x1ff000 0x1a2000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7dd2000     0x7ffff7dd6000   0x4000 0x1a1000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7dd6000     0x7ffff7dd8000   0x2000 0x1a5000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7dd8000     0x7ffff7ddc000   0x4000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ddc000     0x7ffff7dfc000  0x20000      0x0 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7fd7000     0x7ffff7fda000   0x3000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ff5000     0x7ffff7ff8000   0x3000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ff8000     0x7ffff7ffa000   0x2000      0x0 [vdso]
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffa000     0x7ffff7ffc000   0x2000      0x0 [vvar]
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffc000     0x7ffff7ffd000   0x1000  0x20000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffd000     0x7ffff7ffe000   0x1000  0x21000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffe000     0x7ffff7fff000   0x1000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffffffde000     0x7ffffffff000  0x21000      0x0 [stack]
&lt;&#x2F;span&gt;&lt;span&gt;0xffffffffff600000 0xffffffffff601000   0x1000      0x0 [vsyscall]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;And there is more to explore:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;(gdb) help info proc
&lt;&#x2F;span&gt;&lt;span&gt;Show &#x2F;proc process information about any running process.
&lt;&#x2F;span&gt;&lt;span&gt;Specify any process id, or use the program being debugged by default.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;List of info proc subcommands:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;info proc all -- List all available &#x2F;proc info
&lt;&#x2F;span&gt;&lt;span&gt;info proc cmdline -- List command line arguments of the process
&lt;&#x2F;span&gt;&lt;span&gt;info proc cwd -- List current working directory of the process
&lt;&#x2F;span&gt;&lt;span&gt;info proc exe -- List absolute filename for executable of the process
&lt;&#x2F;span&gt;&lt;span&gt;info proc mappings -- List of mapped memory regions
&lt;&#x2F;span&gt;&lt;span&gt;info proc stat -- List process info from &#x2F;proc&#x2F;PID&#x2F;stat
&lt;&#x2F;span&gt;&lt;span&gt;info proc status -- List process info from &#x2F;proc&#x2F;PID&#x2F;status
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Type &amp;quot;help info proc&amp;quot; followed by info proc subcommand name for full documentation.
&lt;&#x2F;span&gt;&lt;span&gt;Type &amp;quot;apropos word&amp;quot; to search for commands related to &amp;quot;word&amp;quot;.
&lt;&#x2F;span&gt;&lt;span&gt;Command name abbreviations are allowed if unambiguous.
&lt;&#x2F;span&gt;&lt;span&gt;(gdb)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;how-to-create-a-process&quot;&gt;&lt;strong&gt;How to create a process?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;1.&lt;strong&gt;fork():&lt;&#x2F;strong&gt;
The fork() system call is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;types.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;wait.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;execute();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  execute();
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;execute() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; pid, status;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;((pid = fork()) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;cmd[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(execvp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd, cmd) &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: exec failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd);
&lt;&#x2F;span&gt;&lt;span&gt;      exit(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: forking child process failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;fork&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F;The parent executes the wait.
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(wait(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;status) != pid){}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I really would like to write more on this topic. Maybe in another post, otherwise the article will be too long, &lt;em&gt;and I have the dishes to do&lt;&#x2F;em&gt;. At least, we&#x27;ve seen that there is an interesting amount of informations behind what is called a process. &lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-hope-you-ve-learned-something-and-if-you-want-to-know-more&quot;&gt;I hope you&#x27;ve learned something, and if you want to know more:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.tldp.org&#x2F;LDP&#x2F;tlk&#x2F;kernel&#x2F;processes.html&quot;&gt;Processes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.kernel.org&#x2F;doc&#x2F;Documentation&#x2F;filesystems&#x2F;proc.txt&quot;&gt;Proc&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man5&#x2F;proc.5.html&quot;&gt;Proc man pages&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;446528&#x2F;&quot;&gt;The &amp;quot;vsyscall&amp;quot; and &amp;quot;vDSO&amp;quot; segments&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gdb&#x2F;&quot;&gt;GDB&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;turnoff.us&#x2F;geek&#x2F;the-jealous-process&#x2F;&quot;&gt;The jealous process&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Network namespaces</title>
		<published>2016-07-08T00:00:00+00:00</published>
		<updated>2016-07-08T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/onn/" type="text/html"/>
		<id>https://nskm.xyz/posts/onn/</id>
		<content type="html">&lt;p&gt;I use LXC containers mainly as isolated environments when I&#x27;m writing code, but also when I just want to try the last version of a package without being obliged to break something on my current configuration. This is the first part of a serie about LXC containers. In this post, I&#x27;ll share with you what I&#x27;ve learned about network namespaces. Everything here will be done under Debian Jessie, as root, I&#x27;m using Python 3.5 and I&#x27;ve pip installed pyroute2.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To keep the schemas as simple as possible, I won&#x27;t mention the interface &lt;code&gt;lo&lt;&#x2F;code&gt; actually available inside the &lt;code&gt;root namespace&lt;&#x2F;code&gt;. The &lt;code&gt;root namespace&lt;&#x2F;code&gt; is the namespace available to you after a fresh boot of your Operating System. This is a small schema of my configuration showing you where we&#x27;ll start: &lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;root_ns.png&quot; alt=&quot;Root namespace&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What we will do:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#namespace-creation&quot;&gt;Create a namespace&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#veth-pair-creation&quot;&gt;Create a virtual ethernet device pair&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#assign-on-side-to-namespace&quot;&gt;Assign one side of the veth pair to the namespace&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#ip-addresses&quot;&gt;Assign IP addresses to each side of the veth pair&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#default-route-for-namespace&quot;&gt;Set the default route for our namespace&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#attach-veth-to-bridge&quot;&gt;Attach the other side of the veth pair to a bridge&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;network-namespaces&quot;&gt;Network namespaces&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;namespace&lt;&#x2F;strong&gt; is a way of scoping a particular set of identifiers. You can use the same identifier multiple times in different namespaces. Most importantly, you can also restrict an identifier set visible to particular processes.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fact: the set of network interfaces and routing tables are shared across your entire Operating System. &lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;580893&#x2F;&quot;&gt;Network namespaces&lt;&#x2F;a&gt; change that fundamental assumption. With network namespaces, you can have different and separate instances of network interfaces and routing tables that operate independent of each other. Let&#x27;s see how it works, using the Python package &lt;a href=&quot;https:&#x2F;&#x2F;pypi.python.org&#x2F;pypi&#x2F;pyroute2&quot;&gt;Pyroute2&lt;&#x2F;a&gt;:
&lt;a name=&quot;namespace-creation&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pyroute2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;IPDB, IPRoute, NetNS, netns, NSPopen
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;subprocess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Popen, PIPE
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; ipdb_namespace1 = IPDB(nl=NetNS(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;namespace1&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; nsp = NSPopen(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;namespace1&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ip&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;addr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;], stdout=PIPE)
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;l &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;nsp.communicate()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...   &lt;&#x2F;span&gt;&lt;span&gt;print(l)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;1: lo: &amp;lt;LOOPBACK&amp;gt; mtu 65536 qdisc noop state DOWN group default &amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;    link&#x2F;loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;We&#x27;ve just created a network namespace named &lt;code&gt;namespace1&lt;&#x2F;code&gt;. The &lt;code&gt;ip addr&lt;&#x2F;code&gt; command launched inside the namespace &lt;code&gt;namespace1&lt;&#x2F;code&gt; tells us that there is only one interface, &lt;code&gt;lo&lt;&#x2F;code&gt;.
&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;ns_created.png&quot; alt=&quot;Namespace1 created&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, we need a way to link our newly created namespace, to the &lt;code&gt;root namespace&lt;&#x2F;code&gt;. To do that, virtual ethernet devices, &lt;code&gt;veth pair&lt;&#x2F;code&gt;, need to be created and configured. A &lt;code&gt;veth pair&lt;&#x2F;code&gt; works like a patch cable, connecting two sides. It consists of two virtual interfaces, one of them is assigned to the root network namespace, while the other lives within the network namespace, &lt;code&gt;namespace1&lt;&#x2F;code&gt;:
&lt;a name=&quot;veth-pair-creation&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; ipdb_root = IPDB() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# root namespace
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; ipdb_root.create(ifname=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;v01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, kind=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, peer=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).commit()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ff:ff:ff:ff:ff:ff&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4098&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ca:a0:d7:39:57:22&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;kind&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;peer&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;v01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;veth_created.png&quot; alt=&quot;Veth pair device created&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Veth pair device created. Both sides of the veth pair device are actually in the &lt;code&gt;root namespace&lt;&#x2F;code&gt;. To link the &lt;code&gt;root namespace&lt;&#x2F;code&gt; to our newly created namespace &lt;code&gt;namespace1&lt;&#x2F;code&gt;, one side of the veth pair device, the peer, should be assigned to &lt;code&gt;namespace1&lt;&#x2F;code&gt;:
&lt;a name=&quot;assign-on-side-to-namespace&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_root.interfaces.vp01 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;v:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...   &lt;&#x2F;span&gt;&lt;span&gt;v.net_ns_fd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;namespace1&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;veth_peer_moved.png&quot; alt=&quot;Veth peer moved&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, let&#x27;s give IP addresses to all of our interfaces, and set everybody up:
&lt;a name=&quot;ip-addresses&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_root.interfaces.v01 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;veth:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.add_ip(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;192.168.1.36&#x2F;24&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.up()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;kind&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;peer&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;f2:2d:aa:9d:16:da&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;v01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ff:ff:ff:ff:ff:ff&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4098&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_namespace1.interfaces.vp01 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;veth:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.add_ip(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;192.168.1.37&#x2F;24&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.up()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;kind&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;26:29:f4:06:8a:ea&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ff:ff:ff:ff:ff:ff&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4098&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_namespace1.interfaces.lo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;i:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...   &lt;&#x2F;span&gt;&lt;span&gt;i.up()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;772&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;00:00:00:00:00:00&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65536&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;00:00:00:00:00:00&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;At this point, we can open a shell and directly check the configuration for &lt;code&gt;v01&lt;&#x2F;code&gt; interface:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip addr show v01
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;6: v01: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether f2:2d:aa:9d:16:da brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.36&#x2F;24 scope global v01
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::f02d:aaff:fe9d:16da&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;We can also, still from the shell, check the available interfaces inside &lt;code&gt;namespace1&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip netns exec namespace1 ip addr show
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
&lt;&#x2F;span&gt;&lt;span&gt;    inet 127.0.0.1&#x2F;8 scope host lo
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 ::1&#x2F;128 scope host
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;5: vp01: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether 26:29:f4:06:8a:ea brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.37&#x2F;24 scope global vpeer01
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::2429:f4ff:fe06:8aea&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;A system uses its routing table to determine which network interface to use when sending packets to remote systems. Let&#x27;s make all traffic leaving &lt;code&gt;namespace1&lt;&#x2F;code&gt; to go through &lt;code&gt;v01&lt;&#x2F;code&gt;:
&lt;a name=&quot;default-route-for-namespace&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip netns exec namespace1 ip route add default via 192.168.1.36
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;default-route-added.png&quot; alt=&quot;Default route added&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I told you I often use LXC containers when I&#x27;m working. For that reason, I always have a bridge configured and up. Then, all the containers are connected to the internet, via the bridge, as &lt;code&gt;ports&lt;&#x2F;code&gt;. Let me show you:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip addr show br0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;4: br0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether 3c:97:0e:65:c0:27 brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.34&#x2F;24 brd 192.168.1.255 scope global br0
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::3e97:eff:fe65:c027&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# brctl show
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;bridge name     bridge id               STP enabled     interfaces
&lt;&#x2F;span&gt;&lt;span&gt;br0             8000.3c970e65c027       no              eth0
&lt;&#x2F;span&gt;&lt;span&gt;                                                        vethLMRO1N
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The &lt;code&gt;br0&lt;&#x2F;code&gt; interface is the interface I use for going outside. In fact, &lt;code&gt;br0&lt;&#x2F;code&gt; is a bridge. &lt;code&gt;eth0&lt;&#x2F;code&gt; and &lt;code&gt;vethLMRON&lt;&#x2F;code&gt; are interfaces, &lt;code&gt;ports&lt;&#x2F;code&gt;, attached to that &lt;a href=&quot;http:&#x2F;&#x2F;www.linuxfoundation.org&#x2F;collaborate&#x2F;workgroups&#x2F;networking&#x2F;bridge&quot;&gt;bridge&lt;&#x2F;a&gt;. &lt;code&gt;v01&lt;&#x2F;code&gt; should be attached to the &lt;code&gt;br0&lt;&#x2F;code&gt; bridge, otherwise, &lt;code&gt;v01&lt;&#x2F;code&gt; won&#x27;t be able to send packets to the outside world:
&lt;a name=&quot;attach-veth-to-bridge&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# brctl addif br0 v01
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~# brctl show
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;bridge name     bridge id               STP enabled     interfaces
&lt;&#x2F;span&gt;&lt;span&gt;br0             8000.3c970e65c027       no              eth0
&lt;&#x2F;span&gt;&lt;span&gt;                                                        vethLMRO1N
&lt;&#x2F;span&gt;&lt;span&gt;                                                        v01
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
![Veth pair device added to bridge]({filename}&#x2F;images&#x2F;ns.png)
&lt;br&gt;&lt;br&gt;
If everything went fine, you should be able to ping an external host from `namespace1`:
```
kintanu:~# ip netns exec namespace1 ping 8.8.8.8
```
```
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
From 192.168.1.34: icmp_seq=1 Redirect Host(New nexthop: 192.168.1.1)
64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=104 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=105 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=105 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=54 time=104 ms
^C
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min&#x2F;avg&#x2F;max&#x2F;mdev = 104.190&#x2F;104.859&#x2F;105.375&#x2F;0.595 ms
kintanu:~#
```
&lt;br&gt;
&lt;p&gt;We&#x27;ve just seen how to create a network namespace, and link that network namespace to the outside world. When playing with LXC containers, you will also heard about &lt;code&gt;control groups&lt;&#x2F;code&gt;, a kernel mechanism that will allow you to allocate resources among user-defined groups of tasks (processes) running on a system. That will be the topic of the next chapter.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align: right;&quot;&gt;All the diagrams were made using [Asciiflow](http:&#x2F;&#x2F;asciiflow.com&#x2F;)&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Introduction</title>
		<published>2015-07-24T00:00:00+00:00</published>
		<updated>2015-07-24T00:00:00+00:00</updated>
		<link rel="alternate" href="https://nskm.xyz/posts/intro/" type="text/html"/>
		<id>https://nskm.xyz/posts/intro/</id>
		<content type="html">&lt;p&gt;Hello, I&#x27;m Patrick, born and raised in central &lt;a href=&quot;#&quot;&gt;Africa&lt;&#x2F;a&gt;, currently based in West Africa, &lt;a href=&quot;#&quot;&gt;Dakar Senegal&lt;&#x2F;a&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;I am an experienced software engineer, passionate about &lt;a href=&quot;#&quot;&gt;free software&lt;&#x2F;a&gt;. I have a strong background in developing backend solutions. With almost 10 years of hands-on experience in the field, I have successfully contributed to &lt;a href=&quot;#&quot;&gt;free software&lt;&#x2F;a&gt; and I have successfully developed and deployed &lt;a href=&quot;#&quot;&gt;numerous&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;software&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;projects&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;across&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;various&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;industries&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My expertise lies in &lt;a href=&quot;#&quot;&gt;free software&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Python programming&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;databases&lt;&#x2F;a&gt;; enabling me to tackle complex challenges and deliver high-quality, scalable software solutions. I thrive in dynamic and collaborative environments, working closely with cross-functional teams to understand requirements, design architectures, and implement robust solutions.&lt;&#x2F;p&gt;
&lt;p&gt;Throughout my career, I have demonstrated a proven track record of delivering projects on time and within budget, while ensuring adherence to best practices and industry standards. I am adept at analyzing existing systems, identifying areas for improvement, and implementing enhancements that optimize performance and user experience.&lt;&#x2F;p&gt;
&lt;p&gt;Over the course of my professional journey, I have had the privilege of &lt;a href=&quot;#&quot;&gt;working as a programming instructor&lt;&#x2F;a&gt; for diverse groups of learners, ranging from beginners to experienced professionals. My &lt;a href=&quot;#&quot;&gt;teaching&lt;&#x2F;a&gt; approach is centered around creating an engaging and supportive &lt;a href=&quot;#&quot;&gt;learning environment&lt;&#x2F;a&gt;, where students can grasp complex concepts with ease and apply them effectively. &lt;&#x2F;p&gt;
&lt;p&gt;Beyond technical skills, I am a team player, strong communicator and effective problem solver. I excel at sharing knowledge, at translating complex technical concepts into clear &amp;amp; non-technical language, fostering effective communication between stakeholders, clients, and development teams.&lt;&#x2F;p&gt;
&lt;p&gt;I am constantly exploring emerging technologies and &lt;a href=&quot;#&quot;&gt;staying up-to-date&lt;&#x2F;a&gt; with industry trends, as I believe in continuous learning and professional growth. I am eager to leverage my skills and expertise to contribute to a dynamic organization, driving innovation and delivering exceptional software solutions.&lt;&#x2F;p&gt;
&lt;!-- Thank you for considering my profile. I look forward to the opportunity to discuss how my skills and experience can benefit your team. --&gt;
</content>
	</entry>
</feed>
