<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pavel Vergeev</title>
    <description>The latest articles on DEV Community by Pavel Vergeev (@vergeev).</description>
    <link>https://dev.to/vergeev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F26732%2Ffbbb29a7-9585-4032-a114-e01a429866a4.jpg</url>
      <title>DEV Community: Pavel Vergeev</title>
      <link>https://dev.to/vergeev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vergeev"/>
    <language>en</language>
    <item>
      <title>Django Celery Beat: How to get the last time a PeriodicTask was run</title>
      <dc:creator>Pavel Vergeev</dc:creator>
      <pubDate>Thu, 13 Feb 2020 21:28:39 +0000</pubDate>
      <link>https://dev.to/vergeev/django-celery-beat-how-to-get-the-last-time-a-periodictask-was-run-39k9</link>
      <guid>https://dev.to/vergeev/django-celery-beat-how-to-get-the-last-time-a-periodictask-was-run-39k9</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Suppose you have the following task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django_project.celery&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;  &lt;span class="c1"&gt;# set up according to https://docs.celeryproject.org/en/stable/django/first-steps-with-django.html#using-celery-with-django
&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_task&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm running!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I've finished!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose further &lt;code&gt;my_task&lt;/code&gt; runs once in several days using &lt;a href="https://github.com/celery/django-celery-beat"&gt;django-celery-beat&lt;/a&gt; in a single worker process.&lt;/p&gt;

&lt;p&gt;The question is: how can &lt;code&gt;my_task&lt;/code&gt; get the last time it was run?&lt;/p&gt;

&lt;h2&gt;
  
  
  Take number one: Bind and Get
&lt;/h2&gt;

&lt;p&gt;The first thing that comes to mind is, find where &lt;code&gt;django-celery-beat&lt;/code&gt; puts the last running time of a &lt;code&gt;PariodicTask&lt;/code&gt; and take that value.&lt;/p&gt;

&lt;p&gt;So first you need to &lt;a href="https://docs.celeryproject.org/en/stable/userguide/tasks.html#bound-tasks"&gt;bind&lt;/a&gt; the task in order to get its name, then get the appropriate &lt;code&gt;PeriodicTask&lt;/code&gt; and take its &lt;code&gt;last_run_at&lt;/code&gt; attribute, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;last_run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PeriodicTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;  &lt;span class="c1"&gt;# notice PeriodicTask.name and self.name are different things
&lt;/span&gt;    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;last_run_at&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"I'm running! Last time I ran at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_run_at&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I've finished!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The problem&lt;/strong&gt;: &lt;code&gt;PeriodicTask&lt;/code&gt;s will accumulate each time you restart celery process. Soon you'll be getting&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;django_celery_beat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PeriodicTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MultipleObjectsReturned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;returned&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="n"&gt;PeriodicTask&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;returned&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Take number two: Bind and Filter
&lt;/h2&gt;

&lt;p&gt;In order to avoid &lt;code&gt;MultipleObjectsReturned&lt;/code&gt; exception, we can filter out all irrelevant periodic tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;last_run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PeriodicTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;order_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'last_run_at'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;last_run_at&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"I'm running! Last time I ran at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_run_at&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I've finished!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The first problem&lt;/strong&gt;: If we run &lt;code&gt;my_task&lt;/code&gt; more often than once in five minutes, &lt;code&gt;last_run_at&lt;/code&gt; is going to get duplicated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[2020-02-13 20:15:41,884: WARNING/ForkPoolWorker-2] I'm running! Last time I ran at 2020-02-13 17:13:00.616557+00:00
[2020-02-13 20:15:51,886: WARNING/ForkPoolWorker-2] I've finished!
[2020-02-13 20:15:51,956: INFO/ForkPoolWorker-2] Task integration.tasks.test_task[1e413b12-455c-4740-8438-d6d1f8b18a35] succeeded in 10.409016128978692s: None
[2020-02-13 20:16:01,787: WARNING/ForkPoolWorker-2] I'm running! Last time I ran at 2020-02-13 17:13:00.616557+00:00
[2020-02-13 20:16:11,788: WARNING/ForkPoolWorker-2] I've finished!
[2020-02-13 20:16:11,825: INFO/ForkPoolWorker-2] Task integration.tasks.test_task[80a4467f-d0b2-4839-a0a4-1270bf02c2e8] succeeded in 10.18468949093949s: None
[2020-02-13 20:16:21,734: INFO/MainProcess] Received task: integration.tasks.test_task[5d4c126e-da9d-4986-8d37-d2d9a072bf60]
[2020-02-13 20:16:21,906: WARNING/ForkPoolWorker-2] I'm running! Last time I ran at 2020-02-13 17:16:01.635268+00:00
[2020-02-13 20:16:31,907: WARNING/ForkPoolWorker-2] I've finished!
[2020-02-13 20:16:31,939: INFO/ForkPoolWorker-2] Task integration.tasks.test_task[5d4c126e-da9d-4986-8d37-d2d9a072bf60] succeeded in 10.203773486078717s: None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fortunately, the problem does not persist if the task is run once in several days. So it would be a valid solution, as long as you don't need to change the schedule of the periodic task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second problem&lt;/strong&gt;: Suppose you do need to change the schedule of the periodic task. You actually &lt;a href="https://stackoverflow.com/q/60210485/3694363"&gt;cannot do that&lt;/a&gt;, or at least I haven't found a way to do that with code. So after PeriodicTask gets reinstantiated with the new schedule, &lt;code&gt;last_run_at&lt;/code&gt; becomes None.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The third problem&lt;/strong&gt;: &lt;code&gt;last_run_at&lt;/code&gt; also becomes &lt;code&gt;None&lt;/code&gt; if you want to &lt;a href="https://docs.celeryproject.org/en/stable/userguide/periodic-tasks.html#time-zones"&gt;change the time zone&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So what I'm saying is, &lt;code&gt;last_run_at&lt;/code&gt; is not a reliable solution for a long-running task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take number three: Store it somewhere else
&lt;/h2&gt;

&lt;p&gt;By this time I knew what I wanted: a reliable way to store the last running time of a task that gets executed rarely in a single process. So I've decided to just store it in the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# models.py
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PeriodicTaskRun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'Task Name'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto_now_add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# tasks.py
&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;last_run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PeriodicTaskRun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;PeriodicTaskRun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"I'm running! Last time I ran at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I've finished!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you know any caveats to this solution I should know about, or if you have a better one, please let me know in the comments!&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>celery</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Let's Run a Tor Bridge! Quick Reference Guide</title>
      <dc:creator>Pavel Vergeev</dc:creator>
      <pubDate>Tue, 03 Sep 2019 16:45:23 +0000</pubDate>
      <link>https://dev.to/vergeev/let-s-run-a-tor-bridge-quick-reference-guide-o3</link>
      <guid>https://dev.to/vergeev/let-s-run-a-tor-bridge-quick-reference-guide-o3</guid>
      <description>&lt;p&gt;In its &lt;a href="https://newsletter.torproject.org/archive/2019-08-30-docsHackathon-run-a-tor-bridge-releases-events/text/"&gt;recent newletter&lt;/a&gt; the Tor Project asked for help with setting up new, uncensored bridges. Since this is a good way to contribute to the project, I went ahead and did it. While doing so, I've compiled this quick reference guide on how to run a bridge relay and why doing so is a good idea.  &lt;/p&gt;

&lt;h1&gt;
  
  
  What is Tor
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=JWII85UlzKw"&gt;Watch a video overview of Tor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Tor is a network for circumventing censorship and protecting identity online.&lt;/p&gt;

&lt;h1&gt;
  
  
  How Tor works
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://2019.www.torproject.org/about/overview.html.en#thesolution"&gt;Read detailed description of Tor inner workings&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: The Tor browser connects to a network of publicly-listed interconnected nodes. They toss the packets to each other in a randomized fashion, anonymizing the sender of the packets.&lt;/p&gt;

&lt;h1&gt;
  
  
  What does a Tor bridge do
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.torproject.org/docs/bridges.html"&gt;Read documentation for the Tor bridges&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Bridge relays allow to connect to Tor network even if it's banned by the government. Also, the bridges hide the fact that a person uses Tor.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why should you run a bridge
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://blog.torproject.org/run-tor-bridges-defend-open-internet"&gt;Read the post asking to run more bridges&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: It allows people living in oppressive regimes to have access to the open internet. Free access to information is a basic human right.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to run a bridge
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Rent a VPS or use the one already at your disposal. I found &lt;a href="https://www.digitalocean.com/"&gt;DigitalOcean&lt;/a&gt; the most convenient provider to use, but went ahead with &lt;a href="https://vscale.io"&gt;my local provider&lt;/a&gt; to reduce the cost of running the relay.&lt;/li&gt;
&lt;li&gt;Follow the installation instructions. &lt;a href="https://community.torproject.org/relay/setup/bridge/docker/"&gt;Docker installation&lt;/a&gt; is the easiest one.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Monitoring
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://community.torproject.org/relay/setup/bridge/post-install/"&gt;Post-install notes&lt;/a&gt; describe the process. You can also count the number of users by viewing the relay logs. It can take up to several month before your bridge gets its first user. It's advised to be patient and wait until your bridge accumulates users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Go to the &lt;a href="https://metrics.torproject.org/rs.html"&gt;relay search&lt;/a&gt;, and type in your relay fingerprint. Here's the &lt;a href="https://metrics.torproject.org/rs.html#details/EDA4827F76C8815EE3D33B20E942C69899EACC4E"&gt;example of the page you'll get&lt;/a&gt;. Bookmark it, and you'll be able to monitor your bridge activity.&lt;/p&gt;




&lt;p&gt;Big thanks to Philipp Winter of the Tor Project for helping me to set up my first bridge.&lt;/p&gt;

&lt;p&gt;If you find yourself in need of advice, don't hesitate to email me to &lt;a href="mailto:pavel@vergeev.site"&gt;pavel@vergeev.site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tor</category>
      <category>censorship</category>
      <category>linux</category>
    </item>
    <item>
      <title>Productive Full-Stack Development with PyCharm</title>
      <dc:creator>Pavel Vergeev</dc:creator>
      <pubDate>Sun, 27 Jan 2019 20:30:33 +0000</pubDate>
      <link>https://dev.to/vergeev/productive-full-stack-development-with-pycharm-3ah7</link>
      <guid>https://dev.to/vergeev/productive-full-stack-development-with-pycharm-3ah7</guid>
      <description>&lt;p&gt;It took me a long time to figure out which area of software development I like. So I've tried a bunch of different technologies, and many different tools that accompany them. I've spent &lt;a href="https://gist.github.com/vergeev/94b161316906b4c7769d5eff6d107ad8"&gt;three years&lt;/a&gt; coding with Vim, wrote &lt;a href="https://github.com/vergeev/checkmate"&gt;a whole project&lt;/a&gt; using Netbeans, and gradually tried every popular text editor for web development out there, including VSCode.&lt;/p&gt;

&lt;p&gt;Seeing VSCode getting so much attention, with people like Kenneth Reitz &lt;a href="https://www.kennethreitz.org/essays/why-you-should-use-vs-code-if-youre-a-python-developer"&gt;recommending it for Python development&lt;/a&gt;, I thought it would be refreshing to talk about completely different development setup.&lt;/p&gt;

&lt;p&gt;I discovered some PyCharm features after I saw them used in other editors. With this post, I hope to do the same for you: encourage you to explore your editor more thoroughly, getting the most out of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recognizing the strengths
&lt;/h2&gt;

&lt;p&gt;There is a couple of things IDEs do best, so I tried to center my workflow around them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigating the codebase.&lt;/li&gt;
&lt;li&gt;Integrating everything in one place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What follows is the list of features I use almost every day. I also give links to appropriate documentation pages. If there's a keyboard shortcut, I will indicate it in brackets (having in mind Apple keyboard layout).&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigating the codebase
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Common-sense features
&lt;/h3&gt;

&lt;p&gt;A common thing to have among the editors is "find everything". In PyCharm, it's &lt;code&gt;⇧⇧&lt;/code&gt; shortcut.&lt;/p&gt;

&lt;p&gt;"Jump to declaration" (&lt;code&gt;⌘B&lt;/code&gt;) would not surprise anyone, too. In PyCharm it works in many different contexts, with no configuration whatsoever. So if I wanted to find SCSS class declaration, I would press &lt;code&gt;⌘B&lt;/code&gt; and get&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1XcvgRv0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dvj3a1nubvn2u39pqao6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1XcvgRv0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dvj3a1nubvn2u39pqao6.png" alt="" width="880" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Same shortcut for JS symbols, Django Template Language, and simply opening an included file. And if I use &lt;code&gt;⌘B&lt;/code&gt; on the declaration itself, it will show the usages.&lt;/p&gt;

&lt;p&gt;To find a string, I use global search (&lt;code&gt;⌘⇧F&lt;/code&gt;). The nice thing about it is that it allows me to search in the source code of the project dependencies, even if they are located in a different folder.&lt;/p&gt;

&lt;p&gt;The "take me back" button (&lt;code&gt;⌥⌘←&lt;/code&gt;) comes in handy when I found what I was looking for.&lt;/p&gt;

&lt;p&gt;There's also multi-cursor with different editing shortcuts that I like, but I'll avoid reciting &lt;a href="https://www.jetbrains.com/help/pycharm/basic-editing-procedures.html"&gt;the manual&lt;/a&gt;. Everybody has these features anyway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Things I didn't know I needed
&lt;/h3&gt;

&lt;p&gt;Ubiquitous and reliable hints is something I always miss when I'm using a simple text editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FrMIexoA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4mpax09dej7g7mdgr5h5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FrMIexoA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4mpax09dej7g7mdgr5h5.png" alt="" width="880" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't have to google the bootstrap classes anymore! It also hints me the names of the attributes I override, a thing I tend to do all the time while working with Django.&lt;/p&gt;

&lt;p&gt;The hints are also useful for imports. But I don't use them for that, because PyCharm has built-in &lt;a href="https://www.jetbrains.com/help/pycharm/settings-auto-import.html"&gt;auto import&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vim bindings is something I wanted from every editor I tried. This is not the case with PyCharm with its select-nearest-block-that-makes-sense feature (&lt;code&gt;⌥↑&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z3Q_ZSjq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4iwo3uh1y4gp4intinhw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z3Q_ZSjq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4iwo3uh1y4gp4intinhw.gif" alt="" width="396" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, the bonus for non-native English speakers such as myself: the spellcheck. In one of my projects, we had two classes: &lt;code&gt;Enhancement&lt;/code&gt; and &lt;code&gt;EnchancementTemplate&lt;/code&gt;. My teammate made a typo in the second name, and it would have remained unnoticed if PyCharm didn't underline &lt;code&gt;Enchancement&lt;/code&gt; during the code review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating everything in one place
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;I don't fully remember how to deploy the project I'm working on.&lt;/p&gt;

&lt;p&gt;All I know is that clicking the green "start" button at the corner will do all the necessary work for me. It will even reload the server once I change the source code.&lt;/p&gt;

&lt;p&gt;This is enabled by the thing PyCharm calls &lt;a href="https://www.jetbrains.com/help/pycharm/creating-and-editing-run-debug-configurations.html"&gt;Configurations&lt;/a&gt;. In Django project, all this thing asks for is environment variables. But it allows me to do much more than that.&lt;/p&gt;

&lt;p&gt;In my project, Django runs on its own, but Redis and Postgres run in their own containers. So I made my Django configuration run &lt;code&gt;docker-compose up -d&lt;/code&gt; each time I start the project. This way, I lifted the mental toll of having to remember this detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging
&lt;/h3&gt;

&lt;p&gt;Once I configured how I run the project, I got the debugger configuration for free. The only difference is that I click on the green bug instead of the green triangle.&lt;/p&gt;

&lt;p&gt;In order to insert a breakpoint, I don't need to insert any code. I click on the line I want my breakpoint to be on, and trigger the target code. No more forgetting to remove &lt;code&gt;import pdb; pdb.set_trace()&lt;/code&gt; for me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PZKFlY-r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qk1inpktbbr0noox4o5s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PZKFlY-r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qk1inpktbbr0noox4o5s.png" alt="" width="880" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I hit the breakpoint, I click "Evaluate Expression" (the little calculator icon) and here I have the same interactive shell I had in &lt;code&gt;pdb&lt;/code&gt; with an addition of hints and autocomplete.&lt;/p&gt;

&lt;p&gt;I love that debugger behaves nicely even if two or more requests come in and trigger the same breakpoint several times. With &lt;code&gt;pdb&lt;/code&gt;, this situation was a nightmare.&lt;/p&gt;

&lt;h3&gt;
  
  
  VCS and task tracking
&lt;/h3&gt;

&lt;p&gt;When I first started using PyCharm, I did all my version control from the terminal. To make things comfy, I used a lot of &lt;a href="https://dev.to/robertcoopercode/using-aliases-to-speed-up-your-git-workflow-2f5a"&gt;git aliases&lt;/a&gt;. Then I dug a little deeper into how PyCharm &lt;a href="https://www.jetbrains.com/help/pycharm/version-control-integration.html"&gt;handles the VCS&lt;/a&gt; and liked it.&lt;/p&gt;

&lt;p&gt;I don't need to remember the details of how VCS is handled. Any time I have something to commit, I press &lt;code&gt;⌘K&lt;/code&gt;, deselect the things I don't want to commit yet, and write the commit message. As someone who's obsessed with &lt;code&gt;git add --patch&lt;/code&gt; and atomic commits, I find it wonderful that I can visually select the changes I'm going to commit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--85mIieEk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oo22vbhq96ibx1sijl2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--85mIieEk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oo22vbhq96ibx1sijl2a.png" alt="" width="880" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that PyCharm knows when I commit, it would be nice if it could track the ticket I'm commiting for, right? And this can be done: I connected the corporate Gitlab server with &lt;code&gt;Tools | Tasks &amp;amp; Contexts | Configure Servers&lt;/code&gt; and PyCharm fetched the tickets. Now I have different sets of tabs and changes open for each task, and can switch to a new task more easily. I can even &lt;a href="https://www.jetbrains.com/help/pycharm/managing-tasks-and-context.html#time_tracking"&gt;measure the time&lt;/a&gt; I spent working in each context and send it to my issue tracker.&lt;/p&gt;

&lt;p&gt;Sometimes I forget to commit often and end up losing important changes. &lt;a href="https://www.jetbrains.com/help/pycharm/local-history.html"&gt;Local History&lt;/a&gt; allows me to roll them back and already saved me hours of repetitive work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terminal
&lt;/h3&gt;

&lt;p&gt;Two great things about it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It remembers the opened tabs and history for each of them.&lt;br&gt;
So one of my tabs is always opened in case I need SSH Port Forwarding, and in the other I do &lt;code&gt;fab deploy&lt;/code&gt; to deploy the code to production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Virtual Environment is activated automatically, so &lt;code&gt;pip install&lt;/code&gt; works exactly as I expect.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The glaring problem with it is inability for the terminal to share environment with &lt;code&gt;Configurations&lt;/code&gt; without copy-paste, so &lt;code&gt;python manage.py makemigrations&lt;/code&gt; might end up doing migrations for the wrong database. I show how to ameliorate the problem in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python Console
&lt;/h3&gt;

&lt;p&gt;It's nice to be able to run arbitrary code inside the Django project. The problem is that I have to remember to set the correct environment for &lt;code&gt;python manage.py shell&lt;/code&gt;. And again, I want my hints and autocomplete.&lt;/p&gt;

&lt;p&gt;To achieve that, I install a couple of external things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/Ashald/EnvFile"&gt;EnvFile&lt;/a&gt; plugin for PyCharm&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/theskumar/python-dotenv"&gt;dotenv&lt;/a&gt; package for Python&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I tell my configurations to load variables from the &lt;code&gt;.env&lt;/code&gt; file, like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LJmI3i6O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6gphy82wkfv47uv3u1md.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LJmI3i6O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6gphy82wkfv47uv3u1md.png" alt="" width="880" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I go &lt;code&gt;Preferences | Build, Execution, Deployment | Console | Django Console&lt;/code&gt; and in the &lt;code&gt;Starting script&lt;/code&gt; area write&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Python %s on %s'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;django&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Django %s'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_version&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;WORKING_DIR_AND_PYTHON_PATHS&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# this will allow to load the correct environment for the shell
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="n"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dotenv_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'.env'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# this is needed if the project uses django-configurations package
# import configurations
# configurations.setup()
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;'setup'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;django_manage_shell&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;django_manage_shell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROJECT_ROOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# and this will allow to call any "python manage.py ..." command from the shell
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.core.management&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;call_command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can open Python Console to run migrations and freely interact with Django models while getting autocomplete and the default IDE shortcuts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3go8ldMx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/kw7unmmepdsvtdo4z1m3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3go8ldMx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/kw7unmmepdsvtdo4z1m3.png" alt="" width="880" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this very shell I can even interact with the data on the remote database. To do that, I forward the remote database to my local host (see &lt;a href="https://unix.stackexchange.com/questions/115897/whats-ssh-port-forwarding-and-whats-the-difference-between-ssh-local-and-remot"&gt;how remote port forwarding works&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh -L 5431:127.0.0.1:5432 user@example.org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then I tell Django that the production database is located at &lt;code&gt;127.0.0.1:5432&lt;/code&gt; using &lt;a href="https://docs.djangoproject.com/en/2.1/topics/db/multi-db/"&gt;Django's support for multiple databases&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now the following code in the Python Console will get me the number of users on the production database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'production'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Jupyter Notebook
&lt;/h3&gt;

&lt;p&gt;Integration of Jupyter Notebook with Django is similar to integrating Python Console. Open the &lt;code&gt;.ipynb&lt;/code&gt; in PyCharm. As the first cell, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Python %s on %s'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;django&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Django %s'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_version&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;WORKING_DIR_AND_PYTHON_PATHS&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# this will allow to load the correct environment for the shell
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="n"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dotenv_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'.env'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# this is needed if the project uses django-configurations package
# import configurations
# configurations.setup()
&lt;/span&gt;
&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you have the Django-Jupyter-PyCharm toolchain ready to go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KrEsZd5y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6x3wm9izr9smc8a46ziu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KrEsZd5y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6x3wm9izr9smc8a46ziu.png" alt="" width="880" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using port forwarding trick described above, you can even do the computations on the production data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database
&lt;/h3&gt;

&lt;p&gt;If you didn't like the idea of local code messing with production data, you can connect to the database using a &lt;a href="https://www.jetbrains.com/help/pycharm/settings-tools-database.html"&gt;dedicated tool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It was of great help when the ORM was not available. And again, autocomplete and database inspection made life so much easier.&lt;/p&gt;

&lt;p&gt;This thing is also well-documented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sass
&lt;/h3&gt;

&lt;p&gt;In order to get Sass/SCSS files compile automatically, I had to set up &lt;a href="https://www.jetbrains.com/help/pycharm/transpiling-sass-less-and-scss-to-css.html"&gt;file watchers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For my project, the default settings were OK, but generally file watchers ask you to provide the path where you want to put the compiled files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scratches
&lt;/h3&gt;

&lt;p&gt;I'm writing this post in PyCharm. I use a &lt;a href="https://www.jetbrains.com/help/pycharm/scratches.html"&gt;scratch file&lt;/a&gt;, and the process looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RAm5JM7g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q214u2t8x9i0yd2hpsqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RAm5JM7g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q214u2t8x9i0yd2hpsqy.png" alt="" width="880" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alongside the scratch file, I have the example project opened.&lt;/p&gt;

&lt;p&gt;I use scratch files primarily while I'm designing some complex features.&lt;/p&gt;

&lt;p&gt;Scratch files are also easily exported to Github Gist: &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8FnHTcdh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lxej86g3vfxgiosxjccn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8FnHTcdh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lxej86g3vfxgiosxjccn.png" alt="" width="880" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating PyCharm
&lt;/h3&gt;

&lt;p&gt;Until recently, I used to update PyCharm by downloading a new version manually from the website and replacing the binary.&lt;/p&gt;

&lt;p&gt;Now &lt;a href="https://www.jetbrains.com/toolbox/app/"&gt;there's a tool for that&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to explore?
&lt;/h2&gt;

&lt;p&gt;I came up with the workflow I currently have because other people shared how they do stuff. I got familiar with the idea of the one-step build thanks to Makefile. I found integrated debugger in PyCharm after I read about that exact feature for VSCode. I decided I needed comfortable Python shell when I saw my friend using IPython.&lt;/p&gt;

&lt;p&gt;This is why I wrote this post: so you could discover new features you like and integrate them into your workflow.&lt;/p&gt;

&lt;p&gt;I don't want to stop with what I have. Let me know how you prefer to get things done, I probably have a lot to learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/"&gt;The Law of Leaky Abstractions&lt;/a&gt; — why you shouldn't use an IDE if you only starting out.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/allanmacgregor/vim-is-the-perfect-ide-e80"&gt;Vim Is The Perfect IDE&lt;/a&gt; — while I am avoiding CLI as much as possible, this post offers the opposite approach.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/codemouse92/the-curse-of-the-ide-3j7n"&gt;Curse of the IDE&lt;/a&gt; — problems with IDEs you should be aware of.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/danlebrero/master-your-ide"&gt;Master your IDE&lt;/a&gt; — a short post with direct instructions.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ide</category>
      <category>pycharm</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Testing against unmanaged models in Django</title>
      <dc:creator>Pavel Vergeev</dc:creator>
      <pubDate>Tue, 15 Aug 2017 19:58:12 +0000</pubDate>
      <link>https://dev.to/vergeev/testing-against-unmanaged-models-in-django</link>
      <guid>https://dev.to/vergeev/testing-against-unmanaged-models-in-django</guid>
      <description>&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;My Django application is supposed to read the tables of an already existing database. So the models of the database are generated using &lt;code&gt;inspectdb&lt;/code&gt; command. They look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;second_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# other properties
&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;managed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="n"&gt;db_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'user'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;managed = False&lt;/code&gt; property tells Django not to create the table as part of &lt;code&gt;migrate&lt;/code&gt; command and not to delete it after &lt;code&gt;flush&lt;/code&gt;. The catch here is that Django &lt;a href="https://docs.djangoproject.com/en/1.11/ref/models/options/#managed"&gt;won't create the table&lt;/a&gt; during testing either. So when I wanted to test my code against non-production database, I ran into the following issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The need to create all of the tables for unmanaged models by hand just to run the tests. Otherwise I was getting &lt;code&gt;django.db.utils.OperationalError: no such table: user&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It was not obvious to me how to generate fixtures for the unmanaged models. If the model is managed, you can run the migrations on the test database, populate the tables with the help of &lt;code&gt;shell&lt;/code&gt; command and save it with &lt;code&gt;dumpdata&lt;/code&gt;. But the tables of unmanaged models are not created during migrations, there's nothing to populate. Again, I had to create everything by hand.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My goal was to find a way to automate the process, making both testing and collaboration easier. Relevant bits and pieces of are scattered across the Internet. This is an attempt to collect them in one place.&lt;/p&gt;

&lt;h1&gt;
  
  
  The simple solution
&lt;/h1&gt;

&lt;p&gt;Before the test runner launches the tests, it runs the migrations creating the tables for managed models. The migrations themselves are Python code that creates the models and sets the &lt;code&gt;managed&lt;/code&gt; property. It is possible to modify a migration so that it sets &lt;code&gt;managed&lt;/code&gt; to &lt;code&gt;True&lt;/code&gt; while we are testing and &lt;code&gt;False&lt;/code&gt; otherwise for unmanaged models.&lt;br&gt;
To do that, we will create &lt;code&gt;IS_TESTING&lt;/code&gt; variable in &lt;code&gt;settings.py&lt;/code&gt; and set it to &lt;code&gt;True&lt;/code&gt; when we are testing. We will also modify the migration code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;

&lt;span class="c1"&gt;# ...
&lt;/span&gt;&lt;span class="n"&gt;operations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'User'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="c1"&gt;# ...
&lt;/span&gt;        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;'db_table'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;# 'managed': False,
&lt;/span&gt;            &lt;span class="s"&gt;'managed'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IS_TESTING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the table will be created whenever the migration is run with &lt;code&gt;IS_TESTING = True&lt;/code&gt;.&lt;br&gt;
The idea belongs to Kyle Valade, who described it &lt;a href="https://kdazzle.svbtle.com/testing-with-unmanaged-databases-in-django"&gt;in his blog&lt;/a&gt;.&lt;br&gt;
To generate fixtures, the method with &lt;code&gt;shell&lt;/code&gt; command described earlier will work.&lt;br&gt;
The downside here is that you have to remember to modify the migration of every unmanaged model.&lt;/p&gt;
&lt;h1&gt;
  
  
  Creating a custom test runner
&lt;/h1&gt;

&lt;p&gt;A more complex solution is to create a custom test runner that will convert all unmanaged models to managed before running a test and revert the effect afterwards.&lt;br&gt;
We'll put the runner in &lt;code&gt;appname/utils.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DiscoverRunner&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnManagedModelTestRunner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DiscoverRunner&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup_test_environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.apps&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;
        &lt;span class="n"&gt;get_models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_models&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unmanaged_models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;get_models&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;managed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unmanaged_models&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;managed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UnManagedModelTestRunner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;setup_test_environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;teardown_test_environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UnManagedModelTestRunner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;teardown_test_environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unmanaged_models&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;managed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will tell Django to use this runner by adding &lt;code&gt;TEST_RUNNER = 'app_name.utils.UnManagedModelTestRunner'&lt;/code&gt; to our settings.&lt;br&gt;
We are not yet ready because the &lt;code&gt;User&lt;/code&gt; model &lt;a href="https://stackoverflow.com/questions/18085245/running-tests-with-unmanaged-tables-in-django"&gt;has custom table name&lt;/a&gt; &lt;code&gt;user&lt;/code&gt;. This is why we need to create the test tables without running migrations. There's &lt;a href="https://pypi.python.org/pypi/django-test-without-migrations/"&gt;a small app&lt;/a&gt; for that. It's installed by running &lt;code&gt;pip install&lt;/code&gt; and adding it to &lt;code&gt;INSTALLED_APPS&lt;/code&gt;. Our tests will work if we run them with &lt;code&gt;-n&lt;/code&gt; switch: &lt;code&gt;python manage.py test -n&lt;/code&gt;. As a consequence, we will lose the ability to see if any of our migrations are broken (which is probably fine if all of them are generated by Django).&lt;/p&gt;

&lt;p&gt;The idea of creating a custom test runner belongs to Tobias McNulty, who posted it in &lt;a href="http://blog.birdhouse.org/2015/03/25/django-unit-tests-against-unmanaged-databases"&gt;Caktus Group blog&lt;/a&gt;. The code from his post had to be &lt;a href="https://stackoverflow.com/a/36234846/3694363"&gt;updated&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When it comes to maintaining the code, there are complications. First, if we wanted to use some other test runner, we'd have to inherit from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DiscoverRunner&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django_nose&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NoseTestSuiteRunner&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnManagedModelTestRunner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NoseTestSuiteRunner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DiscoverRunner&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second, even if the &lt;code&gt;django-test-without-migrations&lt;/code&gt; app is simple, it &lt;a href="https://github.com/henriquebastos/django-test-without-migrations/issues/13"&gt;doesn't mean&lt;/a&gt; it can't be broken by a new version of Django, so we need to be prepared to troubleshoot it.&lt;br&gt;
Third, we have to generate fixtures in an unusual way. The tables of our unmanaged models are only available in &lt;code&gt;setUp()&lt;/code&gt; method, so to generate the fixtures we would have to add and dump data &lt;a href="https://stackoverflow.com/a/16076115/3694363"&gt;in the source code&lt;/a&gt; of the test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.core.management&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;call_command&lt;/span&gt;

&lt;span class="c1"&gt;# ...
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="c1"&gt;# ...
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sysout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'fixtures/users.json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;call_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'dumpdata'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'app_name'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sysout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After we ran the code, we can remove it and load the fixture in our tests &lt;a href="https://stackoverflow.com/questions/2470634/loading-fixtures-in-django-unit-tests"&gt;the usual way&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The common weakness
&lt;/h1&gt;

&lt;p&gt;When the tests run, they will treat the unmanaged models as managed. They won't fail if someone accidentally adds a field to an unmanaged model. The only way I know to get around this is to create the tables by hand.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final word
&lt;/h1&gt;

&lt;p&gt;This is all I've got on the topic. If you happen to know another solution, I'd be happy to learn about it.&lt;/p&gt;

</description>
      <category>python</category>
      <category>testing</category>
      <category>database</category>
      <category>django</category>
    </item>
    <item>
      <title>How to test input processing in Python 3</title>
      <dc:creator>Pavel Vergeev</dc:creator>
      <pubDate>Tue, 25 Jul 2017 17:02:03 +0000</pubDate>
      <link>https://dev.to/vergeev/how-to-test-input-processing-in-python-3</link>
      <guid>https://dev.to/vergeev/how-to-test-input-processing-in-python-3</guid>
      <description>&lt;p&gt;Testing functions that use &lt;code&gt;input()&lt;/code&gt; is not a straightforward task. This tutorial shows how to do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Contest programming problem solutions are usually tested automatically. So the input is just a set of strings with predefined format that fed into standard input.&lt;/p&gt;

&lt;p&gt;Suppose, for example, a problem requires us to read in N stacks of different sizes. Then input might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3
4 1 2 3 2
1 2
0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, 3 is the number of stacks to read in. The first number on each subsequent line is the size of the stack (which is not required in Python, but is helpful in other languages), followed by its elements. &lt;/p&gt;

&lt;p&gt;To extract data from the input, a few manipulations have to be made:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_input_stacks&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;stacks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;str_stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;str_stack&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;stacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;stacks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it doesn't take a lot of effort to make a mistake here. In fact, I already made one in the code above. So, it would be nice to have automatic tests for this kind of functions too.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;One of the solutions I found on &lt;a href="https://stackoverflow.com/questions/18161330/using-unittest-mock-to-patch-input-in-python-3" rel="noopener noreferrer"&gt;StackOverflow&lt;/a&gt; when applied to my problem looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from unittest.mock import patch
import unittest

import containers

class ContainersTestCase(unittest.TestCase):

    def test_get_input_stacks_processed_input_correctly(self):
        user_input = [
            '3',
            '4 1 2 3 2',
            '1 2',
            '0',
        ]
        expected_stacks = [
            [1, 2, 3, 2],
            [2],
            [],
        ]
        with patch('builtins.input', side_effect=user_input):
            stacks = containers.get_input_stacks()
        self.assertEqual(stacks, expected_stacks)


if __name__ == '__main__':
    unittest.main()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I run the test, I see that it fails:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F423ihf6bar3cdewuzh8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F423ihf6bar3cdewuzh8c.png" alt="screenshot" width="541" height="294"&gt;&lt;/a&gt;&lt;br&gt;
The problem is that I read in the size of the stack as an element of the stack. Instead, I should just ignore it: &lt;code&gt;str_stack = input().split(' ')[1:]&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  How the solution works
&lt;/h1&gt;

&lt;p&gt;This is the most interesting line in the test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;builtins.input&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;side_effect&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I assume it is known how &lt;a href="http://effbot.org/zone/python-with-statement.htm" rel="noopener noreferrer"&gt;with statement&lt;/a&gt; works. &lt;code&gt;unittest.mock.patch&lt;/code&gt; &lt;a href="https://docs.python.org/3/library/unittest.mock.html#patch" rel="noopener noreferrer"&gt;has&lt;/a&gt; several keyword arguments that modify its behavior, but in this case, it simply replaces built-in &lt;code&gt;input()&lt;/code&gt; function with a &lt;code&gt;unittest.mock.MagicMock&lt;/code&gt; object. One of the properties of the object is to return its &lt;code&gt;return_value&lt;/code&gt; unless its &lt;code&gt;side_effect&lt;/code&gt; returns something else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;unittest.mock&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;43&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;43&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;something_else&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt; 
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;side_effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;something_else&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;side_effect&lt;/code&gt;, unlike &lt;code&gt;return_value&lt;/code&gt;, is a function. &lt;code&gt;side_effect&lt;/code&gt; can also be an exception object (then the exception will be raised when the mock is called) or an iterable. If it's an iterable, the mock yields a new value every time it's called:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;side_effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;Traceback &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;stdin&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;939&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;__call__&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_mock_self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_mock_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;998&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_mock_call&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;StopIteration&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and this is what we are trying to achieve by mocking &lt;code&gt;input()&lt;/code&gt;: a different predefined value each time it is called. This is why we are passing &lt;code&gt;side_effect=user_input&lt;/code&gt; to the &lt;code&gt;patch()&lt;/code&gt; function (&lt;code&gt;side_effect&lt;/code&gt; is both a property of &lt;code&gt;MagicMock&lt;/code&gt; and a keyword argument of &lt;code&gt;patch()&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;4 1 2 3 2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1 2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;builtins.input&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;side_effect&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The argument &lt;code&gt;'builtins.input'&lt;/code&gt; contains a name that points to the &lt;code&gt;input()&lt;/code&gt; function. What &lt;code&gt;patch()&lt;/code&gt; does is it basically makes this name point to the &lt;code&gt;MagicMock&lt;/code&gt; object until the end of the &lt;code&gt;with&lt;/code&gt; block. An object in Python can have multiple names, so patch the right one (&lt;a href="https://docs.python.org/3/library/unittest.mock.html#where-to-patch" rel="noopener noreferrer"&gt;here's how&lt;/a&gt;). &lt;a href="https://docs.python.org/3/library/builtins.html" rel="noopener noreferrer"&gt;builtins&lt;/a&gt; is a module where built-in function names are located:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;builtins&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;builtins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hi&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each time the function &lt;code&gt;get_input_stacks()&lt;/code&gt; calls the patched &lt;code&gt;input()&lt;/code&gt; it gets the next string in the &lt;code&gt;user_input&lt;/code&gt; list. This is the behavior we wanted.&lt;/p&gt;

&lt;h1&gt;
  
  
  Where to go from here
&lt;/h1&gt;

&lt;p&gt;To get a better understanding of the capabilities offered by &lt;code&gt;unittest.mock&lt;/code&gt;, it is best to read &lt;a href="https://docs.python.org/3/library/unittest.mock.html" rel="noopener noreferrer"&gt;the manual&lt;/a&gt;. As an exercise, I would suggest testing a function that does the reverse of &lt;code&gt;get_input_stacks()&lt;/code&gt; by patching &lt;code&gt;print()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>python</category>
      <category>testing</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
