<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Anselmos Blog</title><link href="http://witkowskibartosz.com/blog/" rel="alternate"></link><link href="http://witkowskibartosz.com/blog/feeds/all.atom.xml" rel="self"></link><id>http://witkowskibartosz.com/blog/</id><updated>2018-04-08T22:00:00+02:00</updated><entry><title>Web based terminal emulators</title><link href="http://witkowskibartosz.com/blog/web_based_terminal_emulators.html" rel="alternate"></link><published>2018-04-08T22:00:00+02:00</published><updated>2018-04-08T22:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-04-08:/blog/web_based_terminal_emulators.html</id><summary type="html">&lt;p&gt;Let's find out what web based terminal emulator there are.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Let's find out what web based terminal emulator there are.&lt;/p&gt;
&lt;p&gt;In this article I'm only going to guide you to the possible emulators.&lt;/p&gt;
&lt;p&gt;Each of the emulator will have it's own article.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="web_based_terminal_emulators.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;The list&lt;/h2&gt;
&lt;p&gt;This is the list of Web based terminal emulators that I've found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/antonylesuisse/qweb"&gt;Antonylesuisse QWeb&lt;/a&gt; - [How to use QWeb]&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.google.com/archive/p/shellinabox/"&gt;ShellInABox&lt;/a&gt; - [How to use ShellInABox]&lt;/li&gt;
&lt;li&gt;&lt;a href="http://anyterm.org/"&gt;AnyTerm&lt;/a&gt; - [AnyTerm web based terminal emulator]&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/liftoff/GateOne"&gt;GateOne&lt;/a&gt; - [How to use GateOne emulator]&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chjj/tty.js/"&gt;tty.js&lt;/a&gt; - [Using TTY.js as an web-based terminal emulator]&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/yudai/gotty"&gt;Gotty&lt;/a&gt; - [Using gotty to share terminal emulator on web]&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tmate-io/tmate-slave"&gt;Tmate.io&lt;/a&gt; - [Making your own tmux tmate server]&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/krishnasrinivas/wetty"&gt;Wetty&lt;/a&gt; - [Using Wetty as an alternative to ajax/any-term]&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tsl0922/ttyd"&gt;ttyd&lt;/a&gt; - [Creating ttyd server to share terminal on web]&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tsl0922/ttyd"&gt;Termshare&lt;/a&gt; - [Using Termshare terminal sharing server]&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mosh.org/"&gt;Mosh&lt;/a&gt; - [Using Mosh as an ssh alternative for mobile terminal]&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="web_based_terminal_emulators.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/yudai/gotty"&gt;GitHub - yudai/gotty: Share your terminal as a web application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/yudai/gotty/releases"&gt;Releases · yudai/gotty · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/moul/gotty-client"&gt;GitHub - moul/gotty-client: terminal client for GoTTY&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tmate.io/"&gt;tmate • Instant terminal sharing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tmate-io/tmate-slave"&gt;GitHub - tmate-io/tmate-slave: tmate slave server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/paradoxxxzero/butterfly"&gt;GitHub - paradoxxxzero/butterfly: A web terminal based on websocket and tornado&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mosh.org/"&gt;Mosh: the mobile shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://unix.stackexchange.com/questions/40350/what-is-the-best-text-mode-browser"&gt;terminal - What is the best text-mode browser? - Unix &amp;amp; Linux Stack Exchange&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1944818/whats-a-good-browser-based-terminal-emulator"&gt;webbrowser control - What's a good browser-based terminal emulator? - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lwn.net/Articles/670062/"&gt;DomTerm: A web-based rich terminal emulator [LWN.net]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cybelesoft.com/blog/new-technology-sunrise-pure-web-terminal-emulator-coming-soon/"&gt;Pure web, HTML5 Based Terminal Emulator Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Web-based_SSH"&gt;Web-based SSH - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! 
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;</content><category term="tmate"></category><category term="gotty"></category><category term="tmuxp"></category><category term="tmux"></category><category term="screen"></category></entry><entry><title>PYTHONSTARTUP What it is and How to use it</title><link href="http://witkowskibartosz.com/blog/pythonstartup_what_it_is_and_how_to_use_it.html" rel="alternate"></link><published>2018-04-07T23:05:00+02:00</published><updated>2018-04-07T23:05:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-04-07:/blog/pythonstartup_what_it_is_and_how_to_use_it.html</id><summary type="html">&lt;p&gt;Let's find out what PYTHONSTARTUP is and how can we use it.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Let's find out what PYTHONSTARTUP is and how can we use it.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="pythonstartup_what_it_is_and_how_to_use_it.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;According to &lt;a href="https://docs.python.org/3/using/cmdline.html#envvar-PYTHONSTARTUP"&gt;documentation&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PYTHONSTARTUP&lt;/p&gt;
&lt;p&gt;If this is the name of a readable file, the Python commands in that file are executed before the first prompt is displayed in interactive mode.
The file is executed in the same namespace where interactive commands are executed so that objects defined or imported in it can be used without qualification in the interactive session.
You can also change the prompts sys.ps1 and sys.ps2 and the hook sys.&lt;strong&gt;interactivehook&lt;/strong&gt; in this file.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To put it into perspective, let's check how to use it.&lt;/p&gt;
&lt;p&gt;Let's create a &lt;code&gt;.pythonrc&lt;/code&gt; file with this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"how_use_pythonstartup"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then lets setup &lt;code&gt;PYTHONSTARTUP&lt;/code&gt; with this bash command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;PYTHONSTARTUP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.pythonrc
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let's call python interactive mode with &lt;code&gt;python&lt;/code&gt;, and you will find something similar to this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="mf"&gt;2.7&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Nov&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt; &lt;span class="mi"&gt;2017&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GCC&lt;/span&gt; &lt;span class="mf"&gt;4.8&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;linux2&lt;/span&gt;
&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="s2"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"copyright"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"credits"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"license"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;how_use_pythonstartup&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It means that we basically were able to hack into interactive mode before starting of it.&lt;/p&gt;
&lt;p&gt;This works only on an interactive mode.&lt;/p&gt;
&lt;h2&gt;Examples of pythonrc&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.rasadacrea.com/en/web-training-courses/using-the-python-interpreter"&gt;Rasadacrea&lt;/a&gt; example of pythonrc gives us possibility to use tab completion :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;readline&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;rlcompleter&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;atexit&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="c1"&gt;# tab completion&lt;/span&gt;
&lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_and_bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tab: complete'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# history file&lt;/span&gt;
&lt;span class="n"&gt;histfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'HOME'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'.pythonhistory'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_history_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;histfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;IOError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="n"&gt;atexit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write_history_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;histfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;histfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rlcompleter&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="pythonstartup_what_it_is_and_how_to_use_it.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/using/cmdline.html#envvar-PYTHONSTARTUP"&gt;1. Command line and environment — Python 3.6.5 documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.rasadacrea.com/en/web-training-courses/using-the-python-interpreter"&gt;python courses : how to use the python interpreter on ubuntu, RasadaCrea Grenoble - Lyon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jezdez-archive/python-startup/blob/master/startup.py"&gt;python-startup/startup.py at master · jezdez-archive/python-startup · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/berdario/pew/issues/90"&gt;No history in python3 inside the virtualenv · Issue #90 · berdario/pew · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/29690397/can-someone-tell-me-the-purpose-of-pythonstartup"&gt;python - Can someone tell me the purpose of PYTHONSTARTUP? - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/4015656/use-pythonstartup-to-interactively-test-a-python-file-in-the-interpreter"&gt;Use PYTHONSTARTUP to interactively test a python file in the interpreter - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://brandon.invergo.net/news/2014-03-21-Enhancing-the-Python-interpreter-with-a-start-up-script.html"&gt;Brandon Invergo - Enhancing the Python interpreter with a start-up script&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="pythonstartup"></category></entry><entry><title>How to use python debug with pdb</title><link href="http://witkowskibartosz.com/blog/how_to_use_python_debug_with_pdb.html" rel="alternate"></link><published>2018-04-06T18:05:00+02:00</published><updated>2018-04-06T18:05:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-04-06:/blog/how_to_use_python_debug_with_pdb.html</id><summary type="html">&lt;p&gt;Python has a debugger called pdb. Let's find out how can we use it instead of Pycharm.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Python has a debugger called pdb. Let's find out how can we use it instead of Pycharm.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="how_to_use_python_debug_with_pdb.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Calling PDB Stack Trace&lt;/h2&gt;
&lt;p&gt;There is a &lt;a href="https://docs.python.org/3.6/library/pdb.html#pdb.Pdb"&gt;PDB class&lt;/a&gt; that enables python debugging without additional python packages.&lt;/p&gt;
&lt;p&gt;To use it, call stack-trace like that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pdb&lt;/span&gt;

&lt;span class="n"&gt;pdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The line in which you will put &lt;code&gt;pdb.set_trace()&lt;/code&gt; is the one from which pdb will invoke stack-trace.&lt;/p&gt;
&lt;p&gt;There is also a way in which you will start function without setting particular line at which stack-trace should start:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pdb&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;yourmodulename&lt;/span&gt;
&lt;span class="n"&gt;pdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'yourmodulename.yourfunction()'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Using PDB - commands to move in pdb stack-trace&lt;/h2&gt;
&lt;p&gt;PDB stack trace is interactive - in a similar way as in Pycharm.&lt;/p&gt;
&lt;p&gt;You can use commands in pdb to analyze stack-trace.&lt;/p&gt;
&lt;p&gt;You can either write one letter of the command or full name of command - but some of the commands needs to be written in a full-length.&lt;/p&gt;
&lt;p&gt;The most used commands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;u(p) - moves current stack-trace frame up&lt;/li&gt;
&lt;li&gt;d(own) - moves current stack-trace frame down&lt;/li&gt;
&lt;li&gt;b(reak) [([filename:]lineno | function) [, condition]]&lt;ul&gt;
&lt;li&gt;without argument lists all set-up breaks. &lt;/li&gt;
&lt;li&gt;first argument sets up breakpoint at specific filename/function and line number.&lt;/li&gt;
&lt;li&gt;second argument gives option to break only on specific python condition&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;cl(ear)  [filename:lineno | bpnumber [bpnumber ...]]&lt;ul&gt;
&lt;li&gt;without argument clears list of all set-up breaks.&lt;/li&gt;
&lt;li&gt;with first or second argument, gives option to distinct which breakpoints needs to be cleared.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;s(tep) - executes current line&lt;/li&gt;
&lt;li&gt;n(ext) - moves to next line of funtion or returns if not found.&lt;/li&gt;
&lt;li&gt;r(eturn) - continue execution until current function returns.&lt;/li&gt;
&lt;li&gt;q(uit) - quit from debugger.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The full documentation about commands can be found &lt;a href="https://docs.python.org/3.6/library/pdb.html#debugger-commands"&gt;at the pdb documentation page on python docs&lt;/a&gt;&lt;/p&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="how_to_use_python_debug_with_pdb.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;pdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="how_to_use_python_debug_with_pdb.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="how_to_use_python_debug_with_pdb.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3.6/library/pdb.html#pdb.Pdb"&gt;27.3. pdb â The Python Debugger — Python 3.6.5 documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/2/library/bdb.html#module-bdb"&gt;26.1. bdb â Debugger framework — Python 2.7.14 documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="pdb"></category></entry><entry><title>How to Automate web-scraping vocabulary into pdf</title><link href="http://witkowskibartosz.com/blog/how_to_automate_web_scraping_vocabulary_into_pdf.html" rel="alternate"></link><published>2018-04-05T23:00:00+02:00</published><updated>2018-04-05T23:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-04-05:/blog/how_to_automate_web_scraping_vocabulary_into_pdf.html</id><summary type="html">&lt;p&gt;Lately I've found this vocabulary.com site that give a lot of knowledge. Let's check how can we automate reading of new vocabulary by scraping data from site into pdf.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Lately I've found this &lt;a href="https://www.vocabulary.com/articles/chooseyourwords/"&gt;vocabulary.com&lt;/a&gt; site that give a lot of knowledge. Let's check how can we automate reading of new vocabulary by scraping data from site into pdf.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="how_to_automate_web_scraping_vocabulary_into_pdf.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Scraping data from vocabulary.com&lt;/h2&gt;
&lt;p&gt;First what we need is to gather links from vocabulary.com at &lt;a href="https://www.vocabulary.com/articles/chooseyourwords/"&gt;Choose Your Words&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Script like that should do that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;

&lt;span class="n"&gt;domain_href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://www.vocabulary.com/'&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{}articles/chooseyourwords/'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain_href&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;bsobj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;distinct_links&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;link&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bsobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"chooseyourwords"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;distinct_links&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;domain_href&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distinct_links&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After gathering unique links we need to disassemble it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;disassemble_vocabulary_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&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;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bsobj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&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;bsobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'div'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"articlebody"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The script in one piece looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_vocabulary_links&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;domain_href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://www.vocabulary.com/'&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{}articles/chooseyourwords/'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain_href&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;bsobj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;distinct_links&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;link&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bsobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"chooseyourwords"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;distinct_links&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;domain_href&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;distinct_links&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&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;disassemble_vocabulary_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&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;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bsobj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&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;bsobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'div'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"articlebody"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;link_to_vocabulary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_vocabulary_links&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;link&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;link_to_vocabulary&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;disassemble_vocabulary_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Saving html data into pdf&lt;/h2&gt;
&lt;p&gt;Let's use &lt;a href="https://pypi.python.org/pypi/pdfkit"&gt;pdfkit&lt;/a&gt; to make new pdf.
It's using &lt;code&gt;wkhtmltopdf&lt;/code&gt;, so first we need to install it with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get install wkhtmltopdf
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then we can use &lt;code&gt;pipenv install pdfkit&lt;/code&gt; to make &lt;code&gt;pdfkit&lt;/code&gt; library available at env.&lt;/p&gt;
&lt;p&gt;Making use of your html that we have scraped with this script:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;html_to_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pdfkit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"{}.pdf"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"chooseyourwords"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Source code&lt;/h2&gt;
&lt;p&gt;The output is not yet most prettiest, but still we have data in a pdf.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pdfkit&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_vocabulary_links&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;domain_href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://www.vocabulary.com/'&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{}articles/chooseyourwords/'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain_href&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;bsobj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;distinct_links&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;link&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bsobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"chooseyourwords"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;distinct_links&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;domain_href&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;distinct_links&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&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;disassemble_vocabulary_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&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;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bsobj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&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;bsobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'div'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"articlebody"&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;html_to_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;file_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"chooseyourwords"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdfkit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"{}.pdf"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;link_to_vocabulary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_vocabulary_links&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;link&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;html_to_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;disassemble_vocabulary_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="how_to_automate_web_scraping_vocabulary_into_pdf.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.vocabulary.com/articles/chooseyourwords"&gt;Page Not Found : Vocabulary.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pypi.python.org/pypi/pdfkit"&gt;pdfkit 0.6.1 : Python Package Index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/JazzCore/python-pdfkit"&gt;GitHub - JazzCore/python-pdfkit: Wkhtmltopdf python wrapper to convert html to pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/"&gt;Beautiful Soup Documentation — Beautiful Soup 4.4.0 documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/2252726/how-to-create-pdf-files-in-python"&gt;How to create PDF files in Python - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pythonhosted.org/PyPDF2/index.html"&gt;PyPDF2 Documentation — PyPDF2 1.26.0 documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://automatetheboringstuff.com/chapter13/"&gt;Automate the Boring Stuff with Python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="vocabulary"></category><category term="pdf"></category><category term="automation"></category></entry><entry><title>How to use sed as a refactor tool replacement</title><link href="http://witkowskibartosz.com/blog/how_to_use_sed_as_a_refactor_tool_replacement.html" rel="alternate"></link><published>2018-04-04T06:30:00+02:00</published><updated>2018-04-04T06:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-04-04:/blog/how_to_use_sed_as_a_refactor_tool_replacement.html</id><summary type="html">&lt;p&gt;Today let's check how to use SED tool that can be used for text replacement.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today let's check how to use SED tool that can be used for text replacement.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="how_to_use_sed_as_a_refactor_tool_replacement.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;You can replace text in files using &lt;a href="https://www.gnu.org/software/sed/manual/sed.html"&gt;sed&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sed -i -e &lt;span class="s1"&gt;'s/few/asd/g'&lt;/span&gt; file.ext
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can also make use of &lt;code&gt;ack2&lt;/code&gt; for searching and combine it with &lt;code&gt;sed&lt;/code&gt; to create a simplier script than making each call to each individual file.&lt;/p&gt;
&lt;p&gt;Let's first find out if &lt;code&gt;ack2&lt;/code&gt; will give as an output list of files in which it will find searched phrase. Using &lt;code&gt;ack2 --help&lt;/code&gt; we find out, that &lt;code&gt;-l&lt;/code&gt; flag gives us a list of files with seached phrase.&lt;/p&gt;
&lt;p&gt;We can now combine those two using only bash script with for-loop.&lt;/p&gt;
&lt;p&gt;Let's loop each found file from &lt;code&gt;ack2&lt;/code&gt; and then pass the file path to &lt;code&gt;sed&lt;/code&gt; which will replace searched phrase with replacement phrase.&lt;/p&gt;
&lt;p&gt;This can then be used as a similar functionality to refactoring name in pycharm (take into consideration it will replace in all files if finds so it's not a full-time replacement for pycharm).&lt;/p&gt;
&lt;p&gt;Our script will look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="k"&gt;$(&lt;/span&gt;ack2 -l &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    sed -i -e &lt;span class="s2"&gt;"s/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;/g"&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To use it, let's call this script &lt;code&gt;refactor_text.sh&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;refactor_text.sh some_ugly_name_for_variable some_prettier_variable
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which will look for &lt;code&gt;some_ulgy_name_for_variable&lt;/code&gt; in all files from directory you are executing script and replace it with &lt;code&gt;some_prettier_variable&lt;/code&gt; in those files which content matches searching phrase.&lt;/p&gt;
&lt;p&gt;I've added it into my &lt;a href="https://github.com/anselmos/linux-utils/blob/master/refactor_text.sh"&gt;linux-utils repository as a refactor_text.sh&lt;/a&gt;.&lt;/p&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="how_to_use_sed_as_a_refactor_tool_replacement.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#! /bin/sh&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# refactor_text.sh&lt;/span&gt;
&lt;span class="c1"&gt;# Copyright (C) 2018 [Anselmos](github.com/anselmos) &amp;lt;anselmos@users.noreply.github.com&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Distributed under terms of the MIT license.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="k"&gt;$(&lt;/span&gt;ack2 -l &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    sed -i -e &lt;span class="s2"&gt;"s/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;/g"&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;refactor_text.sh some_ugly_name_for_variable some_prettier_variable
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="how_to_use_sed_as_a_refactor_tool_replacement.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="how_to_use_sed_as_a_refactor_tool_replacement.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html"&gt;BASH Programming - Introduction HOW-TO: Loops for, while and until&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://unix.stackexchange.com/questions/159367/using-sed-to-find-and-replace"&gt;shell script - Using 'sed' to find and replace - Unix &amp;amp; Linux Stack Exchange&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/597687/changing-variable-names-in-vim"&gt;Changing Variable Names in Vim - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://unix.stackexchange.com/questions/159367/using-sed-to-find-and-replace"&gt;shell script - Using 'sed' to find and replace - Unix &amp;amp; Linux Stack Exchange&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lifewire.com/example-uses-of-sed-2201058"&gt;Examples of How the Linux Sed Command Is Used&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="sed"></category><category term="ack2"></category></entry><entry><title>Fixing pelican_link_to_title no title problem</title><link href="http://witkowskibartosz.com/blog/fixing_pelican_link_to_title_no_title_problem.html" rel="alternate"></link><published>2018-04-03T12:15:00+02:00</published><updated>2018-04-03T12:15:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-04-03:/blog/fixing_pelican_link_to_title_no_title_problem.html</id><summary type="html">&lt;p&gt;Yesterday when using pelican_link_to_title plugin I've found a 'no title found' problem. Let's focus on that and fix it.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Yesterday when using pelican_link_to_title plugin I've found a 'no title found' problem. Let's focus on that and fix it.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="fixing_pelican_link_to_title_no_title_problem.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;The issue&lt;/h2&gt;
&lt;p&gt;Yesterday I wanted to use &lt;code&gt;pelican_link_to_title&lt;/code&gt; plugin with a file instead of html page. I've forgot that plugin is reading html page which can cause issue while using a file.&lt;/p&gt;
&lt;p&gt;Issue I've got while using a link to file was simlar to this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pelican_link_to_title&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pelican_link_to_title&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="s2"&gt;", line 36, in read_page&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
&lt;span class="ne"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'NoneType'&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Fixing the problem&lt;/h2&gt;
&lt;p&gt;Originally the plugin was meant to save page titles. It was meant for html pages. While I used it, one day I added a link to file. It crashed. The problem was rather conceptional than technical - in idea of the plugin.&lt;/p&gt;
&lt;p&gt;To fix the problem we need to find, if the link is actually an html page or not.&lt;/p&gt;
&lt;h2&gt;Checking if link is html page.&lt;/h2&gt;
&lt;p&gt;While searching for solution for finding if page is html page or not I've found &lt;a href="https://stackoverflow.com/a/25392456"&gt;this StackOverflow issue comment&lt;/a&gt; that describes a solution of accessing url with &lt;code&gt;HEAD&lt;/code&gt; request.&lt;/p&gt;
&lt;p&gt;It will give only metadata information - without content - different from request with &lt;code&gt;GET&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The part of solution with head request looks like this in plugin:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"text/html"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"content-type"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&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;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Source of plugin fixed.&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class="sd"&gt;""" This is a main script for pelican_link_to_title """&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pelican&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;link_to_title_plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;"Link_to_Title plugin "&lt;/span&gt;
    &lt;span class="n"&gt;article_ahreftag&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;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ahref_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ahref'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ahref_tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;article_ahreftag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ahref_tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soup&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;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soup&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;article_ahreftag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&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;tag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;p_tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"http://"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"https://"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"utf-8"&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;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&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;redis&lt;/span&gt;
    &lt;span class="n"&gt;redconn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redconn&lt;/span&gt;&lt;span class="o"&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;url_page&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;found&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;header_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"text/html"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;header_response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"content-type"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&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;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
            &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"html.parser"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
            &lt;span class="n"&gt;redconn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&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;title&lt;/span&gt;
        &lt;span class="k"&gt;else&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;get_non_html_page_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&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;found&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_non_html_page_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header_response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;file_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;file_ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file_str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;url_domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_ext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# file with extension in url.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"Url to {} file: {} on domain: {}"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_ext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;file_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url_domain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# no file with extension in url&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"Url to: {}"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&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;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;""" Registers Plugin """&lt;/span&gt;
    &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link_to_title_plugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="fixing_pelican_link_to_title_no_title_problem.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"text/html"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"content-type"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="c1"&gt;# this url_page is an text/html page type content.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="fixing_pelican_link_to_title_no_title_problem.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="fixing_pelican_link_to_title_no_title_problem.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/anselmos/pelican-link-to-title/master/pelican_link_to_title.py"&gt;Url to py file: pelican_link_to_title.py on domain: raw.githubusercontent.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/25392321/python-requests-check-if-url-is-not-html-webpage"&gt;Python-requests: Check if URL is not HTML webpage - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/List_of_HTTP_header_fields"&gt;List of HTTP header fields - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers"&gt;HTTP headers - HTTP | MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="pelican"></category><category term="pelican_engine"></category><category term="pelican-plugin"></category><category term="pelican_link_to_title"></category></entry><entry><title>Accessing Polar A300 data with polaraccesslink api</title><link href="http://witkowskibartosz.com/blog/accessing_polar_a300_data_with_polaraccesslink_api.html" rel="alternate"></link><published>2018-04-02T17:10:00+02:00</published><updated>2018-04-02T17:10:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-04-02:/blog/accessing_polar_a300_data_with_polaraccesslink_api.html</id><summary type="html">&lt;p&gt;Lately as a gift I got a Polar A300 watch that gives a lot of data to user. There are web and mobile application to it. Check out the API that you can use to access data for your own application!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Lately as a gift I got a &lt;a href="https://www.polar.com/en/products/lifestyle/A300"&gt;Polar A300 watch&lt;/a&gt; that gives a lot of data to user. There is a web and mobile application to it. Check out the API that you can use to access data for your own application!&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="accessing_polar_a300_data_with_polaraccesslink_api.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;API&lt;/h2&gt;
&lt;p&gt;There is &lt;a href="https://www.polar.com/accesslink-api/"&gt;PolarAccessLink API&lt;/a&gt; from which you can access data gathered by A300 watch.&lt;/p&gt;
&lt;p&gt;From this API I've found &lt;a href="https://github.com/polarofficial/accesslink-example-python"&gt;python example usage for polaraccesslink on github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To create your ClientId and ClientSecret used in the polar-example, first create your Polar account and then login at &lt;a href="https://admin.polaraccesslink.com/"&gt;PolarAccesLink Admin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then click on &lt;code&gt;Create a Client&lt;/code&gt;, fill all the forms and as a result you will have ClientId and Client Secret.&lt;/p&gt;
&lt;h2&gt;Reusing Example code&lt;/h2&gt;
&lt;p&gt;First let's clone our example repository with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git clone https://github.com/polarofficial/accesslink-example-python.git
&lt;span class="nb"&gt;cd&lt;/span&gt; accesslink-example-python/
pipenv --python &lt;span class="m"&gt;3&lt;/span&gt;.6
pipenv install requests
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Update the &lt;code&gt;config.yaml&lt;/code&gt; with ClientId and ClientSecret.&lt;/p&gt;
&lt;p&gt;Then let's create OAuth access token, first starting auth_service available at &lt;a href="http://localhost:5000/"&gt;localhost:5000&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv run python authorization.py
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Access the &lt;a href="http://localhost:5000/"&gt;localhost:5000&lt;/a&gt; from which you will login to your own UserId and create your OAuth Token for application.&lt;/p&gt;
&lt;p&gt;You can now use the api with example and extend it's usage beyond what is available at :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv run python accesslink_example.py
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="accessing_polar_a300_data_with_polaraccesslink_api.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://flow.polar.com/"&gt;
    
        Polar Flow
    
    &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://flow.polar.com/start"&gt;
            
                Get started -  Polar Flow
            
        &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/polarofficial/accesslink-example-python"&gt;GitHub - polarofficial/accesslink-example-python: This is an example application that uses the Polar Open AccessLink API.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.polar.com/accesslink-api/swagger.yaml"&gt; Polar Access Link API in swagger.yaml file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://admin.polaraccesslink.com"&gt;PolarAccess Link Admin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.polar.com/accesslink-api/"&gt;Polar Accesslink API v3.14.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="polar"></category><category term="polar-a300"></category><category term="polaraccesslink"></category><category term="polar-api"></category><category term="biking-endorphines"></category></entry><entry><title>Ascii Easter bunny from picture</title><link href="http://witkowskibartosz.com/blog/ascii_easter_bunny_from_picture.html" rel="alternate"></link><published>2018-04-01T12:32:00+02:00</published><updated>2018-04-01T12:32:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-04-01:/blog/ascii_easter_bunny_from_picture.html</id><summary type="html">&lt;p&gt;It's Easter for Christians. Check out how to use a script to change Easter-Bunny picture into ascii-based image.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Happy Easter!&lt;/p&gt;
&lt;p&gt;Let's find a script that enables us to change image to ascii text!&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="ascii_easter_bunny_from_picture.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Img2Txt&lt;/h2&gt;
&lt;p&gt;Firstly let's check &lt;a href="https://github.com/hit9/img2txt"&gt;img2txt&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;p&gt;To install that type of utility I use pipsi. Install using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipsi install img2txt.py
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Testing img2txt&lt;/h3&gt;
&lt;p&gt;Since it's Easter I decided to check some of the Easter-Bunny pictures &lt;a href="https://happyeasterbasket.com/easter-bunny-images-pictures-clipart-drawing/"&gt;as in this blog&lt;/a&gt; to use it with img2txt.&lt;/p&gt;
&lt;p&gt;Image I'm going to use to check img2txt:
&lt;img alt="bunny_eggs" src="images/easter_bunny_eggs.jpg"/&gt;.&lt;/p&gt;
&lt;p&gt;And the result looks like this:
&lt;pre&gt;---------;;-;------:::::::-:::::;;;;;;.;;;;;;;--:!&amp;gt;&amp;gt;7777777777777777777&amp;gt;7777777777777777777777777777
-------;;;;;;------------------;;......;;;;;;;;;-:::!!!!!!!!!!&amp;gt;&amp;gt;&amp;gt;&amp;gt;7&amp;gt;&amp;gt;&amp;gt;!::!&amp;gt;&amp;gt;777777777777777777777777
-----;;;;;;;------------------;..................;;;;:!:::::::!!!!:-;;;...;;;:7777777777777777777777
-;;;;;;;;;;;------------------;......................;-:::::::::::;..........;77777777&amp;gt;&amp;gt;&amp;gt;77777777777
;;;;;;;;;;;-----------;;-----;;......................;;::::::::--;..........;;-7777&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;77777777
;;;;;;;;;;----------;;----;--;;.............;.......;;---------;..............;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;!!!&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;7777777
;;;;;;;;;;;;------;;;-;;;;;--;;;..........;;..........;;-------;...............-!!!!!!!!!&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;7777&amp;gt;
;;;;;;;;;;;;;;-;;;;;;;;;;;;;-;..;;;;;;;;;;;;;.............;;--;................;-::::::::!!!&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
;;;;;;;;;;;;;;-;;;;-;;-&amp;gt;&amp;gt;!;7Q?!;.!!.!..;;;;;;..............;;;;................;------::::::!!!!!&amp;gt;&amp;gt;&amp;gt;
;;;;;;;;;;;;;;;;;;;;;.....:$?!&amp;gt;$C;&amp;gt;7!:;!.;;;;..............;;;;...............;;;-;;----::::::::::::
;;;;;;;;;;;;;;;;-;..;:!7CO$$C!7$C$O;OC&amp;gt;!7-;;;;;;...........;;;;...............;;....;;----:::::::---
;;;;;;;;;;;;;;;;;7:-;!7COOOO$OC$$OO?O!$O;;-.;;;;............;;;......................;--------------
;;;;;;;;;;;;;;;!.&amp;gt;?&amp;gt;-$$O$Q$O$$O$Q?!?!O$7C7C;:;;;;;;.........;;;;;...................;;--------------
;;;;;;;;;;;;;;.&amp;gt;?-;7$$$$O$C!C?!&amp;gt;O77!?$$&amp;gt;&amp;gt;CC!;;;;;;;;;;;...;;;;;;;;;...............;;;;;;----;;;;;;;;
;;;;;;;;;;;;;-O.:O$OOQC&amp;gt;$$?C$7:$!7&amp;gt;&amp;gt;OQ!&amp;gt;7?7!7C;;;;;;;;;;;;;;;;;;;;;;;...........;;;;;;;-;;;;;;;;;;;;
;;;;;;;;;;;;.-7?O7$$?COO-C&amp;gt;7$C!&amp;gt;?7!:C-7&amp;gt;7!7&amp;gt;7-!-;;;;;;;;;;;;;;;;;;;;;;;.;;;;;;;.;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;!?&amp;gt;C;O$$$CO$;OQ?7$&amp;gt;-&amp;gt;??!!?-777!CO&amp;gt;?$!-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;:C--:7$$$.7:O$;CC;Q:CO7!?!&amp;gt;-77&amp;gt;!O$O7-!-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;C;.?$7OO&amp;gt;OOO;QCQQCOC$C!C!&amp;gt;7:7?7!?$$$7O!:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;!-.??:O?!C:$OO-$COCC?&amp;gt;::!-C?-&amp;gt;7!7:QCOO:&amp;gt;!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.;;;;;
;;;;;;;;.7:7&amp;gt;;$$C;CCOQ$OQ7O-!...--:!?:&amp;gt;7!7!OO&amp;gt;$7!--;;;;;;;;;;;;;;;;;;;;.;;;;;;;;;;;;;;;;;;;;;..;;;;;
;;;;;;;.-!&amp;gt;C;OOC$O?.C$C&amp;gt;CQ-  .:!!:-&amp;gt;O&amp;gt;!&amp;gt;O7C&amp;gt;CO$??!:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;....;;..
...;;;;.--7:!O&amp;gt;-C$C?:CO&amp;gt;:: .;:!?!::!!&amp;gt;::$77Q$$QO??!:;;;;;;;;;;;;;....;;;;;;;;;;;;;;;;;;;;;;......;..
........:7C-$$$CO&amp;gt;$OO!CO;..:???7?77!C?&amp;gt;?&amp;gt;CQ:$-$O&amp;gt;?&amp;gt;&amp;gt;;;;;;;;;;;;.....;;;;;;;;;;;;;;;;;;;;;;..........
........:?.7O?OO&amp;gt;COQC7:?..:&amp;gt;77?--::7??7O!CQO$7?$?!7&amp;gt;-..;;;;;;;.....;;;;;;;;;;;;;;;;;;;;;;;..........
.......-7:?&amp;gt;OCOOQO-?Q?:-..!??C!&amp;gt;?!:&amp;gt;?&amp;gt;C$!!?7CO$$C&amp;gt;&amp;gt;&amp;gt;:....;;;;.....;;;;;;;;;;;;;;;;;;;;;;;;..........
.......-C:??!O7:C$?:OOO-..?OC&amp;gt;$HH??QC&amp;gt;&amp;gt;&amp;gt;--:O$$O$O?!77;............;;;;;;;;;;;;;;;.;;;;;;;;..........
;.....;:;7:$O?C7;7O$OC:..;?C7-$HHO&amp;gt;C7!;:::!!CQ$OO?&amp;gt;&amp;gt;C;............;;;;..;..;;...;....;;;;;..........
;;;;;..&amp;gt;&amp;gt;!&amp;gt;QO$OC7;Q$$?-..-&amp;gt;C!:O$HO!!:!!::-!::O$COC7-$;............;;;;..................;;..........
;;;;;..:&amp;gt;:!$$;-!OQ$?77;..!77?!&amp;gt;O&amp;gt;!?!&amp;gt;:-!!;!!-!$$OC:-C;................................;;......;;;.;.
;;;;...:!7&amp;gt;OO!!7CO7::!...-:!:-!7?!------!-7:-:?CO?:7!;...............................;......;;;;;.;.
;;.....&amp;gt;!-7$OC$Q$7--:;...;77:7!&amp;gt;!!:---!!!!&amp;gt;!::&amp;gt;?O7!!-;.....................................;;;;;....
;......&amp;gt;!;:C7C$O?&amp;gt;:!!;;-;.!C?-77!!-::&amp;gt;&amp;gt;!:7&amp;gt;-!-!&amp;gt;?7&amp;gt;!-...............................................
;;;;;;.&amp;gt;!;-C-O$??&amp;gt;:7!-.!;;-CO?!?C&amp;gt;!7!&amp;gt;!:!&amp;gt;-!-!-&amp;gt;C7&amp;gt;-?..;.;;;;;;;....................................
;-;;;;;!!;;?!O$C&amp;gt;7&amp;gt;7&amp;gt;:;:.;-&amp;gt;7?C7&amp;gt;&amp;gt;&amp;gt;77:!!!-:!!!:?C!!!:..;.;;;;;;;;;;;;;;;;.;;;-;;;;;.................
-:-;::;:&amp;gt;-.??$O7&amp;gt;7??!!:-;;;-&amp;gt;!OC&amp;gt;?7&amp;gt;!---;:&amp;gt;!:--&amp;gt;C&amp;gt;::;;;;;.;;;;;;;;;;;;;;;;--:!:&amp;gt;&amp;gt;!:--;;-;;;;;.....;;
7CC?CC&amp;gt;?&amp;gt;-::$!O?&amp;gt;7!&amp;gt;7&amp;gt;&amp;gt;!--;;::&amp;gt;7?&amp;gt;:--;-!!!:&amp;gt;&amp;gt;::&amp;gt;?:O7-::&amp;gt;:-&amp;gt;:--!&amp;gt;!!::!!&amp;gt;!!7&amp;gt;77?????C77&amp;gt;77&amp;gt;&amp;gt;!!!!::::!!
OCO?&amp;gt;;-?:--7O$CO&amp;gt;!&amp;gt;&amp;gt;&amp;gt;&amp;gt;!&amp;gt;::7-:-&amp;gt;!!:--;;-:C&amp;gt;7:!:-7&amp;gt;&amp;gt;-;?7?7????77777?????77?????CCCCC????C???C??7?7??77
?7;;. ;--::;$O&amp;gt;;   ;&amp;gt;&amp;gt;&amp;gt;!:;..;-!!:--;;;;!::!!;.   .&amp;gt;!77?C?7777777?C??????CCC??C??CC?CC?CCC??C???7?C77
7------:::7-;;.      :?!:&amp;gt;&amp;gt;;-. ;--;;;;;-:7!...!!!!;;7&amp;gt;777&amp;gt;! ; !.77????7??????C????C77?77777&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;7777
-  -::-. !!   .7 ? ;  :;&amp;gt;&amp;gt;&amp;gt;;- : ;;-;;;;;-!..&amp;gt;&amp;gt;!----!:7&amp;gt;77 !;  !. !????77?&amp;gt;7?7777?7&amp;gt;?7?77&amp;gt;&amp;gt;7&amp;gt;&amp;gt;&amp;gt;777&amp;gt;&amp;gt;7
   :!!:. ::   .: !:  !&amp;gt;77777.-;-; --;;---.&amp;gt;&amp;gt;:-;;;..;-:?&amp;gt;  -&amp;gt;!!&amp;gt;&amp;gt;&amp;gt;!!7?7C7??777777??7???777&amp;gt;C7&amp;gt;77&amp;gt;&amp;gt;777
   ..!-!!C    ;  ?  ;77777777.-- 7!----;-7:-.    .-;. 7!:&amp;gt;7;!&amp;gt;!&amp;gt;!:--7&amp;gt;&amp;gt;77C77C??CC?&amp;gt;CCC?C?7777?7&amp;gt;7??7
;    :.;!     . ?   &amp;gt; .777. 777777. .::-7-;  .:!!!!!!!;?7&amp;gt;-::?77??!!::?77?&amp;gt;7C7&amp;gt;777!?777777?7&amp;gt;&amp;gt;7777??
!.    ;;   &amp;gt;       &amp;gt;.:;777.;:7777?7  :!:-;.;!!!!!!!!!!!?7?C777??77?77!!777&amp;gt;C7C??7&amp;gt;C7:?7&amp;gt;&amp;gt;7&amp;gt;?77??COC?
    : - :         .&amp;gt;;.7777777?????: !!!;..!!!!!!!!!!!!!:C?C??????!!;?7&amp;gt;&amp;gt;&amp;gt;C777&amp;gt;7&amp;gt;7777&amp;gt;7777?&amp;gt;C??!7CQC7
      :    ..  &amp;gt; .777777777???????- &amp;gt;.&amp;gt;7;!!!!!!!!!!!!!!!CCC??????7:-7?&amp;gt;;&amp;gt;:77OC77?7?&amp;gt;?7!77&amp;gt;??CC7?&amp;gt;?77
 ?    .  .: ! .  .7???????????&amp;gt;???; 7.!!!!!!!!!!!!!::!!!OOC???????????7777?OCC?C!??7?&amp;gt;?7COOC7?7?&amp;gt;7!7
 C    .  ! ..&amp;gt;.. ;?!;????????.:.?C7 ?.;:!!!!!::-;;;;;-;-:OOOC????????7777?C?7&amp;gt;$&amp;gt;C?7&amp;gt;&amp;gt;&amp;gt;!7:OO??&amp;gt;OCO:&amp;gt;:
.....;;  ..-....;&amp;gt;?!?????????.!&amp;gt;CC!.C;&amp;gt;:!!!!:--;;;;;-----CCO&amp;gt;CCCCC???????O$CC7O&amp;gt;O7:7&amp;gt;!CO!7&amp;gt;7-O&amp;gt;$!7??
....O-....!.&amp;gt;...;????- !..???-&amp;gt;:CO?;O-7!&amp;gt;&amp;gt;!:--;!C???CC---$$&amp;gt;&amp;gt;7OOOCC???C?$C?7&amp;gt;&amp;gt;O7&amp;gt;&amp;gt;?&amp;gt;7?!7?7-7?CCO?7C?
...;;&amp;gt;.&amp;gt;.;.7...;;&amp;gt;CC. .. .?CCC&amp;gt;7OO$:$7;7&amp;gt;&amp;gt;!:;C??C????CCO-Q$&amp;gt;Q?O$OOOOOOCCOO:O&amp;gt;?7!7:C?:?O-O7:C7?&amp;gt;C&amp;gt;??O
.;;-!Q;....;..;-:!C:.777&amp;gt;..:CCCOO$OQQ--H7&amp;gt;!CC???C?C????CQHQQ$$$Q$$Q$O7$$77&amp;gt;!7?CC7&amp;gt;!C?7?&amp;gt;?&amp;gt;!!?7&amp;gt;?&amp;gt;7?&amp;gt;
;:-!OQ;:;..;-;;H!!C!7&amp;gt;;-;&amp;gt;.;OOOO$$HH$$?HO&amp;gt;$C???!-::-:7??NNQQHQQ$QQQ$OQ&amp;gt;7C?7?O?$$C:777OOCO:!:&amp;gt;&amp;gt;C?777C
-7!?QH:;;:?;;--NH7O;?!??7.7;O$$$OQNHH$H$HCOC?:---;-:::!&amp;gt;N$NQHQHHHO$QQQC$$C&amp;gt;!-?O&amp;gt;:?7C7!??O;??!:O?&amp;gt;&amp;gt;?&amp;gt;
!7OHHQQ:-&amp;gt;?::!:&amp;gt;7C$;!?C&amp;gt;C&amp;gt;C;-$Q$OC??ONQ$$QQ7?7!!-;----!$H$NQNNNNQQQQ$7?CO!7:O$?O77??OO:?C!?&amp;gt;?&amp;gt;?7O??C
ON$$??CO&amp;gt;&amp;gt;C&amp;gt;77Q7CO$&amp;gt;--:-7??:$QQHHQHQOQ?QHHHC?O!:::::!&amp;gt;?HHQOOCOC?7Q$H$COC77O?:?O:CCCC?&amp;gt;7C7&amp;gt;?O:&amp;gt;C7&amp;gt;C?&amp;gt;
QQOO?$Q7CC?$C$C?$&amp;gt;$O&amp;gt;Q?O&amp;gt;!-&amp;gt;OHHNQ$$$HO$$QQHHQQ?7&amp;gt;777?C$QO$&amp;gt;?$$?$HOOCCO77-OOQ&amp;gt;&amp;gt;::?COCC?O??!?777:-77&amp;gt;&amp;gt;
$$?O&amp;gt;$?&amp;gt;O?!CC$77????O?&amp;gt;C!OCC&amp;gt;ONHCQOQQ$Q$OOOQ$$$H?C7?OCQ$O??COCO$7OOO!?C&amp;gt;!7C7C&amp;gt;7???&amp;gt;&amp;gt;??CO??O77C!!!&amp;gt;C&amp;gt;
OCQ?QO7CO?O?CO7?C7?CC7C$C7O$HQ7O$$$$CQ77??$&amp;gt;CQ$COCCCOC?C7??OOOO&amp;gt;7C$C77&amp;gt;C?&amp;gt;&amp;gt;&amp;gt;CC7C7&amp;gt;OC?&amp;gt;$$CC?7!:&amp;gt;7777:
?OO$7O$?OOOCO?C?&amp;gt;?!7?C77C?7HOO?QOCOOC7O?7OOQ$CQOO$CCOOOC7CO$??!&amp;gt;77?7O7!OC7?C?&amp;gt;777:CC?77C?$7O&amp;gt;:!7!C&amp;gt;!
$C?!&amp;gt;QQCQOCOOCO77:?7$7?O?&amp;gt;CH$?7OC&amp;gt;!CO$CC&amp;gt;CC??OC?COOOOCC&amp;gt;OO?CO77C!77!CC?C$7?&amp;gt;??!&amp;gt;:!?$?7CCCQ?C7&amp;gt;!77&amp;gt;::
7&amp;gt;77QO7CQOCOC77?&amp;gt;777?CO7COOO&amp;gt;77?7?&amp;gt;CC?CCCOC77OCO&amp;gt;7O$?C7&amp;gt;!OCC!7C&amp;gt;??C7&amp;gt;O7?&amp;gt;C::C7&amp;gt;?&amp;gt;!77??OCC$COO77?:&amp;gt;:!
7C?$$C?O?77&amp;gt;C??C7&amp;gt;QCCO7?7?C?7?OC??CCO$$7OCC???O&amp;gt;?!$7&amp;gt;CC7?7?7??C?OC??O?C?77?&amp;gt;7?7?&amp;gt;:!!O??O$$COO?&amp;gt;&amp;gt;7!77
?CC$?C???::7:?CC?Q&amp;gt;7C?C&amp;gt;7C7:7CCOOCCOO$CCO!?OO$CC&amp;gt;?&amp;gt;&amp;gt;77??7??OOCCCOC$?!?O7C?&amp;gt;??OC?77:&amp;gt;CC?O?CCOO?&amp;gt;7&amp;gt;!77
$OOCO?C?7&amp;gt;!7?CC7C&amp;gt;&amp;gt;?!??OC?7??OO$OQ$OQO&amp;gt;7?!C7$???C??7??7777&amp;gt;?COOCOCC7C??CC??7C$C??7!CCCC??&amp;gt;7CO?&amp;gt;&amp;gt;?7??
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;IMHO it does not look great.&lt;/p&gt;
&lt;p&gt;Let's give it a second shot with this image:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Easter Bunny with Egg hand-draw" src="images/easter_bunny_eggs2.gif"/&gt;&lt;/p&gt;
&lt;p&gt;The output:&lt;/p&gt;
&lt;pre&gt;

                                                                         :           

                                                                        M            
                                                                       M &amp;gt;           
                                                                      M  C           
                                                                    !    Q           
                                                                   M     H           
                                                                 :C      !           
                                                                M                    
                                                              -H                     
                                                             M     M  M              
                                                            M    M                   
                                                           ?    !                    
                                                         ;    M        -             
                                                             M           !           
                                                        :   ?            M           
                                  MMMMC                M   .          M  -           
                              M?        M             M  Q           !  M            
                            M.           O                              -            
                          M         M-CM.O           M  M              M             
                         M         M M                 M                             
                       .;             :             M  ;              M              
                       ;          M   M             - :              M               
                      &amp;gt;               M  7            M             Q                
                     H           M    N  M         M               H                 
                    M                    !         M                                 
                                M    &amp;gt;  &amp;gt;          Q M           H                   
                   M            ;    M  M            M          Q                    
                               M     M  .            ?         M                     
                  M            $     ;               -        M                      
                  M           ; ;      Q                     H                       
                  7           M M      M             -     O                         
                  ;                  ; M  MM&amp;gt; M      ;    M                          
                  :          M   M   M M   ? M MM        7                           
                  M         M     M    M M-     M  H   :CC.                          
                  M       M        M    MQ             M   ;M                        
                         H        M&amp;gt;                          $                      
                   M    M       M                              $                     
                    M  Q      M                 O                                    
                     . H     M              MM MM               M                    
                      M     M       M       MM  M-                                   
                           !         M      -MMM        M        Q                   
             C?;                   MM  N     MMMH       :$      MM                   
         M77    ?MMM      M           ;O C    MM    ;CM         MM                   
      .M   M. M:MMM. M7   QM             $ M  !   M7   QMCCM     M                   
     C  ?MM?.  M    M  M   !     &amp;gt;.    CM  .M O  M  H  ;M        .                   
    M    M  M?. M .M   MM;Q         .       - C M:    -           ;                  
       MMHM M  &amp;gt;M M  &amp;gt;MMM MM        M Q       N                 M    ;-              
   M   Q.    M   M  Q:  M MO        M   -     M      ?          HM  M                
        M MMMHM M   M   !M                    M     M           OH     -             
  M   MMMM M   M   MMQ M.  M              .  :     M               O      ?          
  M   ;H    M  M  M .MN                    7 NMMMM!               M       M          
  M    M M$MMMM  M   N?  ;  M               M   M              M :                   
  M  MMM.:N  O  C!   M    : Q              M    M              M         $           
  M  H    M  M  MH  M    HM7&amp;gt;7          -&amp;gt;M     MQ            M           N          
  M   M MMMMQ  M MM?   &amp;gt;M  : O        M;          M                       ?          
    ?MMM!   M  H   M    M :M  M      M             M         M            M          
    M    M N  M   M     M O    M                            M           !M           
   M$ MMMMMM  7   ?   M:  O    MM   ;                     ;!      MM;                
   M M M   ; M-M M    M MM.    $  :M               M    -M      M                    
    CM &amp;gt;  M  M   M    M M         M              MMMMMO      .N                     .
    M   M M  -  M   MN  MM MM MM M               &amp;gt;    H     M                        
     MMMMMM H   M   M MM  M  N  M                    MM    H                         
      M   O M?M C   - MM        N                     !   MM  M;                     
      OM  - M M    MM&amp;gt;          M                     M   Q     ;     HM             
       MM 7 M  ?   M C         MM        M&amp;gt;CM7  :$    M  M      !    N !            .
        H M M   MM  $&amp;gt;       C          MQ  H $M                 M   ;M              
         OM M OM MMMM.M     O    O      M    M  :   O&amp;gt;           &amp;gt;  M .              
           M 7MQ  MM M           !     !         M   M            ;  M M             
            $M    - :H     M      M   MM         &amp;gt;M               MM MMM   M:        
              NQM  MMM              M M          ;MM              MC MM M?  MN       
                MMMMNCM   :                                       M   MMM   MM.      
                 MM&amp;gt; MM   Q                         M             M   MM    M .      
             &amp;gt;N.NM N   MM ?        ;                M             M    M   M  Q ;MM  
               H7C M  O   M                         M             M     ;$.          
                           7                        :             M                  
                           M     M                                M                  
                                                   M              M                  
                            M   7                 MM           -M M                . 
     .                       M  M    M !          ;.       H&amp;gt;    MM                  
                                M   M   M;       M        M      ;                  .
                              ! !   M            CM M    &amp;gt;      O                    
       .                       M    !           M  M M   ;        ?                  
                              MMN    M         H    H      MNNM   M &amp;gt;M               
 .                             ;M&amp;gt;    ?   M          :           : M$                
             .               ;$MMM     .M.    !                  . :MO               
                          MMMMMM  M          .         .:       M    NMM:M;          
                         :         M       M             M    :$                     
                                     M7:$M                MMMM                       
                                                                              .      

                                            OM.                                      
                                          7M !                                       
                                      CMMMM M                                        
                                       ; MM M 7.MMM.                                 
                              .                                            .         


&lt;/pre&gt;
&lt;h2&gt;MotionDesignStudio script&lt;/h2&gt;
&lt;p&gt;There is also another &lt;a href="https://gist.github.com/motiondesignstudio/9374326"&gt;ascii movie image ver 1 py&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://gist.githubusercontent.com/MotionDesignStudio/9374326/raw/aa57ed9aa385ee6f0be6835be820c8ee95bb3e06/readme.txt"&gt;Readme&lt;/a&gt; is very convenient to know how to use it.&lt;/p&gt;
&lt;h3&gt;Fixing issues with script&lt;/h3&gt;
&lt;p&gt;Well... I tried to use the script itself, but unfortunatelly after a bit of digging I've found it lacks proper information about package used and has some issues.&lt;/p&gt;
&lt;p&gt;First of all I had few TabsError (inconsistent use of tabs and spaces in identation).&lt;/p&gt;
&lt;p&gt;So I went to vim and used vim command  &lt;code&gt;:retab&lt;/code&gt;. Saved file.&lt;/p&gt;
&lt;p&gt;Then I needed to fix dependencies problem.&lt;/p&gt;
&lt;p&gt;So I figure out why not create project out of it to have all the relevant files in one place.&lt;/p&gt;
&lt;p&gt;As the result &lt;a href="https://github.com/anselmos/ascii_movie_image_ver1"&gt;here is the link to project at github&lt;/a&gt;. It contains Pipfile and Pipfile.lock - for easier usage with pipenv.&lt;/p&gt;
&lt;h3&gt;Usage&lt;/h3&gt;
&lt;p&gt;I suggest you to get the version from my github project since it has fixed some issues.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git clone https://github.com/anselmos/ascii_movie_image_ver1.git
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ascii_movie_image_ver1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pipenv install --python &lt;span class="m"&gt;3&lt;/span&gt;.6
pipenv shell
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using on pipenv shell:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;python ascii_movie_image_ver_1.py image.img &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Results of using:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Easter Bunny converted" src="images/easter_bunny_eggs2_convert.png"/&gt;&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="ascii_easter_bunny_from_picture.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://happyeasterbasket.com/easter-bunny-images-pictures-clipart-drawing/"&gt;Scary^ Easter Bunny Images &amp;amp; Pictures, Clipart, Cartoon Drawing | Happy Easter 2018 Images, Quotes, Wishes, Messages, Bunny Basket Pics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/motiondesignstudio/9374326"&gt;Python ASCII Video And ASCII Image Creator · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! 
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;</content><category term="python"></category><category term="ascii"></category></entry><entry><title>Debugging https problem on pelican_link_to_title plugin</title><link href="http://witkowskibartosz.com/blog/debugging_https_problem_on_pelican_link_to_title_plugin.html" rel="alternate"></link><published>2018-03-31T22:20:00+02:00</published><updated>2018-03-31T22:20:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-31:/blog/debugging_https_problem_on_pelican_link_to_title_plugin.html</id><summary type="html">&lt;p&gt;Yesterday I've found a problem with pelican_link_to_title plugin that is related to https link. Let's debug what is the problem and how to fix it.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Yesterday I've added into my usual &lt;code&gt;&amp;lt;ahref&amp;gt; &amp;lt;/ahref&amp;gt;&lt;/code&gt; html tag https link that failed. I was surprised, but since it was not my main focus then I decided to give it a shot today. Let's check out what is wrong with plugin or what is wrong with the page I used.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="debugging_https_problem_on_pelican_link_to_title_plugin.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;The failed https page link&lt;/h2&gt;
&lt;p&gt;The link to the page was actually the Travis-Ci page:
&lt;code&gt;&amp;lt;ahref&amp;gt;https://travis-ci.org/beyondgrep/ack2&amp;lt;/ahref&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It will fail with this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;plugins/pelican_link_to_title/pelican_link_to_title.py&lt;span class="s2"&gt;", line 34, in read_page&lt;/span&gt;
&lt;span class="s2"&gt;    r = urllib.urlopen(url_page).read()&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/urllib.py&lt;span class="s2"&gt;", line 87, in urlopen&lt;/span&gt;
&lt;span class="s2"&gt;    return opener.open(url)&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/urllib.py&lt;span class="s2"&gt;", line 208, in open&lt;/span&gt;
&lt;span class="s2"&gt;    return getattr(self, name)(url)&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/urllib.py&lt;span class="s2"&gt;", line 437, in open_https&lt;/span&gt;
&lt;span class="s2"&gt;    h.endheaders(data)&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/httplib.py&lt;span class="s2"&gt;", line 1013, in endheaders&lt;/span&gt;
&lt;span class="s2"&gt;    self._send_output(message_body)&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/httplib.py&lt;span class="s2"&gt;", line 864, in _send_output&lt;/span&gt;
&lt;span class="s2"&gt;    self.send(msg)&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/httplib.py&lt;span class="s2"&gt;", line 826, in send&lt;/span&gt;
&lt;span class="s2"&gt;    self.connect()&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/httplib.py&lt;span class="s2"&gt;", line 1220, in connect&lt;/span&gt;
&lt;span class="s2"&gt;    self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/ssl.py&lt;span class="s2"&gt;", line 487, in wrap_socket&lt;/span&gt;
&lt;span class="s2"&gt;    ciphers=ciphers)&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/ssl.py&lt;span class="s2"&gt;", line 243, in __init__&lt;/span&gt;
&lt;span class="s2"&gt;    self.do_handshake()&lt;/span&gt;
&lt;span class="s2"&gt;File "&lt;/span&gt;/usr/lib/python2.7/ssl.py&lt;span class="s2"&gt;", line 405, in do_handshake&lt;/span&gt;
&lt;span class="s2"&gt;    self._sslobj.do_handshake()&lt;/span&gt;
&lt;span class="s2"&gt;CRITICAL: IOError: [Errno socket error] [Errno 1] _ssl.c:510: error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first thing I've found that may be relevant is to change urllib library into &lt;code&gt;requests&lt;/code&gt; - as it is shown &lt;a href="https://github.com/pytorch/pytorch/issues/3193"&gt;in this issue of pytorch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let's check out if it will help.&lt;/p&gt;
&lt;h2&gt;Replacing urllib into requests.&lt;/h2&gt;
&lt;p&gt;After replacing urllib with requests (adding import and changing gathering data from page) pelican_link_to_title looks like this now:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class="sd"&gt;""" This is a main script for pelican_link_to_title """&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pelican&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;link_to_title_plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;"Link_to_Title plugin "&lt;/span&gt;
    &lt;span class="n"&gt;article_ahreftag&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;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ahref_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ahref'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ahref_tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;article_ahreftag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ahref_tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soup&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;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soup&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;article_ahreftag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&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;tag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;p_tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"http://"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"https://"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"utf-8"&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;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&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;redis&lt;/span&gt;
    &lt;span class="n"&gt;redconn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redconn&lt;/span&gt;&lt;span class="o"&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;url_page&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;found&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&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;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"html.parser"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;redconn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&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;title&lt;/span&gt;
    &lt;span class="k"&gt;else&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;found&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;""" Registers Plugin """&lt;/span&gt;
    &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link_to_title_plugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After a bit of tweaking my pipenv environment I got it finally working.&lt;/p&gt;
&lt;p&gt;Firstly I installed only &lt;code&gt;requests&lt;/code&gt; with &lt;code&gt;pipenv install requests&lt;/code&gt;, but I had an issue :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;local/lib/python2.7/site-packages/urllib3/util/ssl_.py:339: SNIMissingWarning: An HTTPS request has been made, but the SNI &lt;span class="o"&gt;(&lt;/span&gt;Subject Name Indication&lt;span class="o"&gt;)&lt;/span&gt; extension to TLS is not available on this platform. This may cause the server to present an incorrect TLS certificate, which can cause validation failures. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings                  
    SNIMissingWarning


local/lib/python2.7/site-packages/urllib3/util/ssl_.py:137: InsecurePlatformWarning: A &lt;span class="nb"&gt;true&lt;/span&gt; SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
    InsecurePlatformWarning

CRITICAL: SSLError: HTTPSConnectionPool&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'travis-ci.org'&lt;/span&gt;, &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;: Max retries exceeded with url: /beyondgrep/ack2 &lt;span class="o"&gt;(&lt;/span&gt;Caused by SSLError&lt;span class="o"&gt;(&lt;/span&gt;SSLError&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;, &lt;span class="s1"&gt;'_ssl.c:510: error:14077438:SS$ routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;,&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've found that installing the security addon will fix the above problem - &lt;code&gt;pipenv install requests[security]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Check out latest &lt;a href="https://github.com/anselmos/pelican-link-to-title/blob/master/pelican_link_to_title.py"&gt;master of the pelican_link_to_title plugin that contains this fix and redis-optimization&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="debugging_https_problem_on_pelican_link_to_title_plugin.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://docs.python-requests.org/en/master/user/quickstart/#response-content"&gt;Quickstart — Requests 2.18.4 documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/29134512/insecureplatformwarning-a-true-sslcontext-object-is-not-available-this-prevent"&gt;python - InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pytorch/pytorch/issues/3193"&gt;urllib &amp;amp; urllib2 may fail ssl handshaking under a variety of circumstances · Issue #3193 · pytorch/pytorch · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="pelican"></category><category term="pelican_engine"></category><category term="pelican-plugin"></category><category term="pelican_link_to_title"></category><category term="https"></category><category term="ssl"></category></entry><entry><title>How to use ack2 searching tool for code</title><link href="http://witkowskibartosz.com/blog/how_to_use_ack2_searching_tool_for_code.html" rel="alternate"></link><published>2018-03-30T23:55:00+02:00</published><updated>2018-03-30T23:55:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-30:/blog/how_to_use_ack2_searching_tool_for_code.html</id><summary type="html">&lt;p&gt;Lately I've found this tool called ack2 that is a searching tool. Let's explore how we can use it.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://github.com/beyondgrep/ack2"&gt;Ack2&lt;/a&gt; is a greplike tool. Accordingly to documentation it's primary purpose is for searching large amount of content data like source-code of projects.&lt;/p&gt;
&lt;p&gt;There is a great &lt;a href="https://beyondgrep.com/feature-comparison/"&gt;comparison chart on ack2 authors site&lt;/a&gt; that I recommend to check!&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="how_to_use_ack2_searching_tool_for_code.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Docker for building ack2&lt;/h2&gt;
&lt;p&gt;So as I'm a docker-fan-boy as usually I decided to check if this tool will work, but not on my host machine, but using docker first with a &lt;code&gt;ubuntu:trusty&lt;/code&gt; docker-image.&lt;/p&gt;
&lt;p&gt;I've created a Dockerfile like that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;FROM alpine:3.6
RUN apk add --update
RUN apk add --update perl &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/cache/apk/*
RUN apk add --update wget &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/cache/apk/*
RUN apk add --update tar &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/cache/apk/*
RUN apk add --update curl &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/cache/apk/*
RUN apk add --update make &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/cache/apk/*
WORKDIR /app
RUN curl -o ack2.tar.gz https://codeload.github.com/beyondgrep/ack2/tar.gz/2.23_02
RUN tar -zxvf ack2.tar.gz
WORKDIR /app/ack2-2.23_02
RUN perl Makefile.PL
RUN make
RUN &lt;span class="nv"&gt;PERL_MM_USE_DEFAULT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; perl -MCPAN -e &lt;span class="s1"&gt;'install File::Next'&lt;/span&gt;
RUN make &lt;span class="nb"&gt;test&lt;/span&gt;
RUN make ack-standalone
RUN cp ack-standalone /bin/ack2
CMD &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ack2"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Run with &lt;code&gt;docker build -t anselmos/ack2:2.23_02 -f Docker.alpine.latest .&lt;/code&gt; and checked for building to be done.&lt;/p&gt;
&lt;h2&gt;Ack on Docker alpine&lt;/h2&gt;
&lt;p&gt;There is an alpine version of ack but only on &lt;code&gt;edge&lt;/code&gt; version and the ack version is 2.18.
I used this Dockerfile to check it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;FROM alpine:edge
RUN apk update
RUN apk add ack
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With &lt;code&gt;docker build -t anselmos/ack2 -f Dockerfile_alpine .&lt;/code&gt;
And then &lt;code&gt;docker run -it anselmos/ack2:alpine&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;There is also a much more simpler way that is described &lt;a href="https://beyondgrep.com/install/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For ubuntu you run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get install -y ack-grep 
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And you can create a soft link for calling &lt;code&gt;ack&lt;/code&gt; not &lt;code&gt;ack-grep&lt;/code&gt; with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo dpkg-divert --local --divert /usr/bin/ack --rename --add /usr/bin/ack-grep
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For Ubuntu:Trusty it's 2.12 version.&lt;/p&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;To use ack check this &lt;a href="https://beyondgrep.com/documentation/"&gt;documentation - contains all the reference&lt;/a&gt; - also I encourage you to check &lt;code&gt;ack2 --help&lt;/code&gt; to see what type of flags there is.&lt;/p&gt;
&lt;p&gt;The output from ack2 is a bit different from grep, and it's more readable than on grep.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;ack2 &lt;span class="s2"&gt;"perl"&lt;/span&gt; *.md
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And it will search for "perl" in all .md extension files.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="how_to_use_ack2_searching_tool_for_code.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/beyondgrep/ack2/blob/dev/DESIGN.md"&gt;ack2/DESIGN.md at dev · beyondgrep/ack2 · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/beyondgrep/ack2/blob/dev/DEVELOPERS.md"&gt;ack2/DEVELOPERS.md at dev · beyondgrep/ack2 · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/beyondgrep/ack2/releases"&gt;Releases · beyondgrep/ack2 · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/898782/how-do-i-tell-cpan-to-install-all-dependencies"&gt;perl - How do I tell CPAN to install all dependencies? - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.livejournal.com/doc/server/lj.install.perl_setup.modules.html"&gt;2. Installing Perl Modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://twiki.org/cgi-bin/view/TWiki/HowToInstallCpanModules"&gt; HowToInstallCpanModules &amp;lt; TWiki &amp;lt; TWiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/avast/docker-alpine-perl/blob/master/Dockerfile"&gt;docker-alpine-perl/Dockerfile at master · avast/docker-alpine-perl · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pkgs.alpinelinux.org/package/edge/main/x86/ack"&gt;Alpine Linux packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://travis-ci.org/beyondgrep/ack2"&gt;Travis-Ci Ack2&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! 
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;</content><category term="ack2"></category><category term="grep"></category><category term="search-tool"></category></entry><entry><title>Regexp vs clean python code performance check</title><link href="http://witkowskibartosz.com/blog/regexp_vs_clean_python_code_performance_check.html" rel="alternate"></link><published>2018-03-29T00:30:00+02:00</published><updated>2018-03-29T00:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-29:/blog/regexp_vs_clean_python_code_performance_check.html</id><summary type="html">&lt;p&gt;Lately It's been pointed to my attention that regexp are usually slower than pythonic checkers - Let's check out what will outperform.&lt;/p&gt;</summary><content type="html">&lt;p&gt;There are &lt;a href="https://docs.python.org/3/library/re.html"&gt;re&lt;/a&gt; library that gives opportunity to use regexp. With them you can make some of the string-checks that using clean-pythonic way would be a bit more complex.&lt;/p&gt;
&lt;p&gt;Let's check out if this is really a kind of bottleneck that can underperform in some edge-cases!&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="regexp_vs_clean_python_code_performance_check.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Regexp example.&lt;/h2&gt;
&lt;p&gt;Let's say that we have a string that we know should contain max 16 regular text letters.&lt;/p&gt;
&lt;p&gt;With Regexp we could check if the string matches our expectations using this code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="n"&gt;string1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Test&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;regexp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;^[a-zA-Z0-9]{16}$&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;regexp&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="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The printing will return "None" - meaning that variable &lt;code&gt;string1&lt;/code&gt; is not matching string1.&lt;/p&gt;
&lt;h2&gt;Performance regexp&lt;/h2&gt;
&lt;p&gt;Let's now check how to find performance of it.&lt;/p&gt;
&lt;p&gt;First we need to change our script into function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="n"&gt;string1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Test&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;regexp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;^[a-zA-Z0-9]{16}$&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;regexp&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;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&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="n"&gt;check_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now the &lt;a href="https://docs.python.org/2/library/timeit.html"&gt;timeit&lt;/a&gt; library comes into play.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(&amp;#39;&amp;#39;.join(str(n) for n in range(8)))&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It will check timing of the function.&lt;/p&gt;
&lt;p&gt;Let's check performance between the clean-pythonic way and the regexp way:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;timeit&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt;
&lt;span class="n"&gt;string1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Test&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;regexp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;^[a-zA-Z0-9]{16}$&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;regexp&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;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&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;check_python&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&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="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="n"&gt;alphabet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ascii_letters&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;digits&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;string_variable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;alphabet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(&amp;#39;&amp;#39;.join(str(n) for n in range(8)))&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_python(&amp;#39;&amp;#39;.join(str(n) for n in range(8)))&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_python&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&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="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(&amp;#39;&amp;#39;.join(str(n) for n in range(16)))&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_python(&amp;#39;&amp;#39;.join(str(n) for n in range(16)))&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_python&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&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="mi"&gt;16&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(&amp;#39;&amp;#39;.join(str(n) for n in range(32)))&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_python(&amp;#39;&amp;#39;.join(str(n) for n in range(32)))&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_python&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&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="mi"&gt;32&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(&amp;#39;&amp;#39;.join(str(n) for n in range(64)))&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_python(&amp;#39;&amp;#39;.join(str(n) for n in range(64)))&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_python&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&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="mi"&gt;64&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And we see that the results are outperforming regexp with clean-pythonic function. It's not like there's huge difference, but check yourself on this results:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;.5771335330209695 &lt;span class="m"&gt;0&lt;/span&gt;.38084229797823355
&lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;.818426341022132 &lt;span class="m"&gt;0&lt;/span&gt;.6164886929909699
&lt;span class="m"&gt;32&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;.226193142007105 &lt;span class="m"&gt;1&lt;/span&gt;.0479984590201639
&lt;span class="m"&gt;64&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;.1883155060058925 &lt;span class="m"&gt;1&lt;/span&gt;.9493357640167233
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It was only on some digits. Let's check now how it will perform on string with digits:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;timeit&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt;
&lt;span class="n"&gt;string1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;YetAnotherStr123&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# has 16 chars&lt;/span&gt;
&lt;span class="n"&gt;string2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;YetAnotherStr123&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;# has 32 chars&lt;/span&gt;
&lt;span class="n"&gt;string3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;YetAnotherStr123&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="c1"&gt;# has 64 chars&lt;/span&gt;
&lt;span class="n"&gt;string4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;YetAnoth*rStr123&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# has 15 chars and one special&lt;/span&gt;
&lt;span class="n"&gt;string5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;YetAnotherStr12*&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# has 15 chars and one special&lt;/span&gt;
&lt;span class="n"&gt;regexp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;^[a-zA-Z0-9]{16}$&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;regexp&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;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&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;check_python&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&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="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_variable&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="n"&gt;alphabet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ascii_letters&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;digits&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;string_variable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;alphabet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(string1)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp, string1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_python(string1)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_python, string1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&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="n"&gt;time_perform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(string2)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp, string2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_python(string2)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_python, string2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&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="n"&gt;time_perform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(string3)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp, string3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_python(string3)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_python, string3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&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="n"&gt;time_perform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(string4)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp, string4&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_python(string4)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_python, string4&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&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="n"&gt;time_perform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_regexp(string5)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_regexp, string5&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;time_perform2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;check_python(string5)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;from __main__ import check_python, string5&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100000&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="n"&gt;time_perform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_perform2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Well... now we can see what type of problems our clean-pythonic code can have with the results as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.1520436129940208 &lt;span class="m"&gt;0&lt;/span&gt;.14696863299468532
&lt;span class="m"&gt;0&lt;/span&gt;.12985941700753756 &lt;span class="m"&gt;0&lt;/span&gt;.0332289119833149
&lt;span class="m"&gt;0&lt;/span&gt;.13141735998215154 &lt;span class="m"&gt;0&lt;/span&gt;.03479363300721161
&lt;span class="m"&gt;0&lt;/span&gt;.1242920590157155 &lt;span class="m"&gt;0&lt;/span&gt;.1090795070049353
&lt;span class="m"&gt;0&lt;/span&gt;.12702590200933628 &lt;span class="m"&gt;0&lt;/span&gt;.14172734299791045
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It looks like in the string5 version pythonic code underperforms.&lt;/p&gt;
&lt;p&gt;For now I don't see any valid solution that could outperform this problem.&lt;/p&gt;
&lt;p&gt;I will come back to this if I find any valid solution.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="regexp_vs_clean_python_code_performance_check.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="regexp"></category><category term="re"></category><category term="performance"></category><category term="debugging"></category><category term="timeit"></category></entry><entry><title>Python typing support for type hints - type aliases and NewType</title><link href="http://witkowskibartosz.com/blog/python_typing_support_for_type_hints_type_aliases_and_newtype.html" rel="alternate"></link><published>2018-03-28T21:40:00+02:00</published><updated>2018-03-28T21:40:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-28:/blog/python_typing_support_for_type_hints_type_aliases_and_newtype.html</id><summary type="html">&lt;p&gt;Did you know that from python 3.5 there is support for type hints? Check out what type aliases and NewType are.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://docs.python.org/3/library/typing.html"&gt;Type Hints/Typing&lt;/a&gt; were introduced at &lt;a href="https://www.python.org/dev/peps/pep-0484/"&gt;#PEP-484&lt;/a&gt; and described in more detail at &lt;a href="https://www.python.org/dev/peps/pep-0483/"&gt;#PEP-483&lt;/a&gt;. They look very familiar to &lt;a href="https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html"&gt;Java Collections&lt;/a&gt;. Nevertheless they are a types that can be extended at your own purpose.&lt;/p&gt;
&lt;p&gt;Documentation about &lt;a href="https://docs.python.org/3/library/typing.html"&gt;typings&lt;/a&gt; is really straight-forward. I recommend you to check it out.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="python_typing_support_for_type_hints_type_aliases_and_newtype.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;NewType&lt;/h2&gt;
&lt;p&gt;You have types in python. Within them you can create a new types by making an inheritance.&lt;/p&gt;
&lt;p&gt;I.e. to make new type from int you would normally do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NewIntType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But using typing you can do this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NewType&lt;/span&gt;
&lt;span class="n"&gt;NewIntType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NewType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NewIntType'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NewIntInheritance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sumUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NewIntInheritance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NewIntInheritance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;NewIntInheritance&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;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sumUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewIntInheritance&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="n"&gt;NewIntInheritance&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="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NewType&lt;/span&gt;

&lt;span class="n"&gt;NewIntTyping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NewType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NewIntTyping'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&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;sumUpTyping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NewIntTyping&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NewIntTyping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;NewIntTyping&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;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sumUpTyping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewIntTyping&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="n"&gt;NewIntTyping&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;/pre&gt;&lt;/div&gt;
&lt;p&gt;They will basically do the same. There is a difference. When you create a new type with inheritance, that you can use &lt;code&gt;isinstance&lt;/code&gt; with it.&lt;/p&gt;
&lt;p&gt;This code shows the difference:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;NewIntTyping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NewType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NewIntTyping'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&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;checkDifferenceInheritance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NewIntInheritance&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="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewIntInheritance&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;checkDifferenceTyping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NewIntTyping&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="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewIntTyping&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;checkDifferenceInheritance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewIntInheritance&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="n"&gt;checkDifferenceTyping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewIntTyping&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;/pre&gt;&lt;/div&gt;
&lt;p&gt;It will output with this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="n"&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="s2"&gt;"test1.py"&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;38&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;checkDifferenceTyping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewIntTyping&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="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"test1.py"&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;35&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;checkDifferenceTyping&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewIntTyping&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="ne"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So using typing - you should avoid &lt;code&gt;isinstance&lt;/code&gt; or even &lt;code&gt;issubclass&lt;/code&gt; - as mentioned in &lt;a href="https://docs.python.org/3/library/typing.html#typing.TypeVar"&gt;TypeVar section&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Type Aliasing&lt;/h2&gt;
&lt;p&gt;There is also aliasing of types within typing. You can create aliases from other types as documentation at &lt;a href="https://docs.python.org/3/library/typing.html#type-aliases"&gt;type aliases says&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;

&lt;span class="n"&gt;ListOfFloats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;ListOfFloats&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Where is this usefull ? Let's say you want to annotate your function to return List of numeric type of data.&lt;/p&gt;
&lt;p&gt;You can do that with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'T'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&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;sort_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elements&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="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="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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="n"&gt;sort_list&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="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Adding to this decorator that we have introduced at &lt;a href="python_function_annotations.html"&gt;this article&lt;/a&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator_annotation_parameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_wrapped&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;wrapper&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;annotations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_wrapped&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__annotations__&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_wrapped&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;returned_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'return'&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;kwarg&lt;/span&gt; &lt;span class="ow"&gt;in&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;kwarg_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="o"&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;kwarg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&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;kwarg&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;kwarg_type&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;returned_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;returned_type&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can create a checker that will check if the output value consists of Float-Lists and matches annotation output type.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="python_typing_support_for_type_hints_type_aliases_and_newtype.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.python.org/dev/peps/pep-0483/"&gt;PEP 483 -- The Theory of Type Hints | Python.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.python.org/dev/peps/pep-0484/"&gt;PEP 484 -- Type Hints | Python.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/python/typing"&gt;GitHub - python/typing: Work related to PEP 484: typing.py (released via PyPI) and issue tracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1549801/what-are-the-differences-between-type-and-isinstance"&gt;python - What are the differences between type() and isinstance()? - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/python/cpython/blob/3.6/Lib/typing.py"&gt;cpython/typing.py at 3.6 · python/cpython · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.coglib.com/~icordasc/blog/2015/04/type-hints-in-python-35.html"&gt;Type Hints in Python 3.5 - cat /dev/brain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dgkim5360.github.io/blog/python/2017/07/duck-typing-vs-goose-typing-pythonic-interfaces/"&gt;Duck Typing vs. Goose Typing, Pythonic Interfaces :: tl;dr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jasonmbaker.wordpress.com/2008/12/11/duck-typing-vs-interfaces/"&gt;The best tool for the job: Duck typing vs Interfaces « Jason in a Nutshell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://robots.thoughtbot.com/reusable-oo-composition-vs-inheritance"&gt;Composition vs Inheritance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/44097280/duck-typing-vs-class-based-inheritance"&gt;python - Duck typing Vs class based Inheritance - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="typing"></category><category term="type"></category><category term="hints"></category><category term="python-v3"></category></entry><entry><title>Debugging tmuxp focus problem</title><link href="http://witkowskibartosz.com/blog/debugging_tmuxp_focus_problem.html" rel="alternate"></link><published>2018-03-27T22:35:00+02:00</published><updated>2018-03-27T22:35:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-27:/blog/debugging_tmuxp_focus_problem.html</id><summary type="html">&lt;p&gt;Today I'm going to debug the 'focus' problem on tmuxp. Check out my experience with fixing the problem.&lt;/p&gt;</summary><content type="html">&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="debugging_tmuxp_focus_problem.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;The &lt;code&gt;focus&lt;/code&gt; problem.&lt;/h2&gt;
&lt;p&gt;So there is an issue &lt;a href="https://github.com/tmux-python/tmuxp/issues/326"&gt;#326 of tmuxp repository&lt;/a&gt; that I also found using tmuxp. 
It's about using &lt;code&gt;focus&lt;/code&gt; attribute that does not work.&lt;/p&gt;
&lt;h2&gt;Debugging&lt;/h2&gt;
&lt;p&gt;So first of all I have started installed tmuxp with pipsi with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipsi install tmuxp
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then I have found that pipsi actually creates virtualenv to run scripts.&lt;/p&gt;
&lt;p&gt;So I've found where actually &lt;code&gt;tmuxp&lt;/code&gt; is located with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;which tmuxp
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That outputed with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;~/.local/bin/tmuxp
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And found location of the script that should be similar to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;~/.local/venvs/tmuxp/lib/python2.7/site-packages/tmuxp
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So first I tried to debug how the Tmuxp works internally and looked for &lt;code&gt;focus&lt;/code&gt; in code.&lt;/p&gt;
&lt;p&gt;I've finally found the &lt;code&gt;tmuxp load&lt;/code&gt; uses code with this stack trace :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;at cli.py &lt;code&gt;command_load&lt;/code&gt; invokes:&lt;/li&gt;
&lt;li&gt;at cli.py &lt;code&gt;load_workspace&lt;/code&gt; then invokes builder class:&lt;/li&gt;
&lt;li&gt;at cli.py &lt;code&gt;builder.build&lt;/code&gt; from workspacebuilder: - at workspacebuilder.py&lt;/li&gt;
&lt;li&gt;and in cli.py after &lt;code&gt;builder.build()&lt;/code&gt; - invoking &lt;code&gt;set_layout_hook(builder.session, 'client-attached')&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After tampering and making printing and tracing down the problem I've found that making &lt;code&gt;sys.exit()&lt;/code&gt; after &lt;code&gt;builder.build()&lt;/code&gt; creates tmux session that properly works with focusing.&lt;/p&gt;
&lt;p&gt;So after that I narrowed down problem and found that commenting &lt;code&gt;set_layout_hook&lt;/code&gt; at cli.py fixes problem.&lt;/p&gt;
&lt;p&gt;I have created a &lt;a href="https://github.com/tmux-python/tmuxp/pull/371"&gt;#371 PR&lt;/a&gt; and requested merging to branch. Let's check out what the maintainer has to say about my &lt;code&gt;fix&lt;/code&gt; which frankly is more of a hack.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="debugging_tmuxp_focus_problem.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="tmuxp"></category><category term="tmux"></category><category term="issue"></category><category term="debug"></category></entry><entry><title>Command_T for fuzzy search in vim</title><link href="http://witkowskibartosz.com/blog/command_t_for_fuzzy_search_in_vim.html" rel="alternate"></link><published>2018-03-26T19:50:00+02:00</published><updated>2018-03-26T19:50:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-26:/blog/command_t_for_fuzzy_search_in_vim.html</id><summary type="html">&lt;p&gt;Is there any type of searcher for vim that could work similarly to Pycharm fuzzy searching? Command_T plugin is the answer - check out my review on that!&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://github.com/wincent/command-t"&gt;Command T&lt;/a&gt; is a Vim Plugin that is Ruby based. It enables to make a fuzzy search for files and in files.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="command_t_for_fuzzy_search_in_vim.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;To install Command_T you need to have ruby addons in vim.&lt;/p&gt;
&lt;p&gt;Check out if you have ruby-support in vim with vim command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;ruby&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you are so lucky as I am and you have following output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;E319: Sorry, the &lt;span class="nb"&gt;command&lt;/span&gt; is not available in this version
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Than you have to add ruby-support to your vim or install vim with pre-existing ruby support.&lt;/p&gt;
&lt;h3&gt;Installing Vim with Ruby support&lt;/h3&gt;
&lt;p&gt;If you use Ubuntu system, you can install vim with ruby support with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get install -y vim-nox&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For other, I'd suggest to build vim with commands &lt;a href="https://stackoverflow.com/a/3851435"&gt;shown in this stackoverflow answer&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git clone https://github.com/vim/vim vim
&lt;span class="nb"&gt;cd&lt;/span&gt; vim
./configure --enable-rubyinterp
make
sudo make install
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Installing vim-plugin.&lt;/h3&gt;
&lt;p&gt;After enabling ruby support in vim, you need to add this to your vimrc using Vundle :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Plugin &lt;span class="s1"&gt;'wincent/command-t'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;To use you can invoke it with &lt;code&gt;&amp;lt;Leader&amp;gt;t&lt;/code&gt; - so the &lt;code&gt;\t&lt;/code&gt; standard vim combination.&lt;/p&gt;
&lt;p&gt;Well ... My first usage outputed with this beautiful error:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;command-t.vim could not load the C extension.
Please see INSTALLATION and TROUBLE-SHOOTING in the help.
Vim Ruby version: &lt;span class="m"&gt;1&lt;/span&gt;.9.3-p484
Expected version: &lt;span class="o"&gt;[&lt;/span&gt;unknown&lt;span class="o"&gt;]&lt;/span&gt;-p&lt;span class="o"&gt;[&lt;/span&gt;unknown&lt;span class="o"&gt;]&lt;/span&gt;
For more information type:    :help command-t
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What it means? it means that we need C extension for the plugin to work properly.&lt;/p&gt;
&lt;p&gt;The documentation &lt;a href="https://github.com/wincent/command-t/blob/master/doc/command-t.txt#L313"&gt;with this installation guide&lt;/a&gt; gives information that we should go to vim-plugin folder:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.vim/bundle/command-t/ruby/command-t/ext/command-t
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And compile extension with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;ruby extconf.rb 
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But my system does not have all ruby-extensions and building tools, so it failed with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Unable to require &lt;span class="s2"&gt;"mkmf"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; you may need to install Ruby development tools
&lt;span class="o"&gt;(&lt;/span&gt;depending on your system, a &lt;span class="s2"&gt;"ruby-dev"&lt;/span&gt;/&lt;span class="s2"&gt;"ruby-devel"&lt;/span&gt; package or similar&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;span class="o"&gt;[&lt;/span&gt;exiting&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let's install them:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get install -y ruby-dev
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now checking again compilation goes with this effect:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;ruby extconf.rb 
checking &lt;span class="k"&gt;for&lt;/span&gt; float.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; ruby.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; stdlib.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; string.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; fcntl.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; stdint.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; sys/errno.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; sys/socket.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; ruby/st.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; st.h... yes
checking &lt;span class="k"&gt;for&lt;/span&gt; pthread_create&lt;span class="o"&gt;()&lt;/span&gt; in -lpthread... yes
creating Makefile
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let's &lt;code&gt;make&lt;/code&gt; this.:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;make
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Outputs with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;compiling heap.c
compiling ext.c
compiling matcher.c
compiling match.c
compiling watchman.c
linking shared-object ext.so
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So it means we are good to go ?&lt;/p&gt;
&lt;p&gt;Checking... Yeah!! It works.&lt;/p&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="command_t_for_fuzzy_search_in_vim.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get install -y vim-nox&lt;span class="p"&gt;;&lt;/span&gt;
sudo apt-get install -y ruby-dev&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;VimRC:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Plugin &lt;span class="s1"&gt;'wincent/command-t'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Building plugin:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.vim/bundle/command-t/ruby/command-t/ext/command-t
ruby extconf.rb 
make
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="command_t_for_fuzzy_search_in_vim.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="command_t_for_fuzzy_search_in_vim.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/3794895/installing-vim-with-ruby-support-ruby"&gt;Installing vim with ruby support (+ruby) - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wincent/command-t"&gt;GitHub - wincent/command-t: Fast file navigation for VIM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="vim"></category><category term="command_t"></category><category term="fuzzy_search"></category><category term="vim-plugin"></category></entry><entry><title>How to use NERDTree</title><link href="http://witkowskibartosz.com/blog/how_to_use_nerdtree.html" rel="alternate"></link><published>2018-03-25T21:30:00+02:00</published><updated>2018-03-25T21:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-25:/blog/how_to_use_nerdtree.html</id><summary type="html">&lt;p&gt;Let's check out how can we improve our experience with file exploration at vim using NerdTree.&lt;/p&gt;</summary><content type="html">&lt;p&gt;The &lt;a href="https://github.com/scrooloose/nerdtree"&gt;NerdTree&lt;/a&gt; is a vim plugin that enables us to explore files within vim.&lt;/p&gt;
&lt;h1&gt;Installation&lt;/h1&gt;
&lt;p&gt;To install NERDTree you can use Vundle with adding this to your .vimrc:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Plugin &lt;span class="s1"&gt;'scrooloose/nerdtree'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Usage&lt;/h1&gt;
&lt;p&gt;All you need to do is either use vim command &lt;code&gt;:NERDTree&lt;/code&gt; or map vim-command with Ctrl+n (or other combination):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;nmap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; :NERDTreeToggle&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To learn some of the NERDTree key-combinations check the "?" sign at NERDTree, here is what you will find:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="s2"&gt;" NERDTree (5.0.0) quickhelp~&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;============================&lt;/span&gt;
&lt;span class="s2"&gt;" File node mappings~&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; double-click,
&lt;span class="s2"&gt;" &amp;lt;CR&amp;gt;,&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; o: open in current window
&lt;span class="s2"&gt;" t: open in new tab&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; T: open in new tab silently
&lt;span class="s2"&gt;" middle-click,&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; i: open split
&lt;span class="s2"&gt;" gi: preview split&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; s: open vsplit
&lt;span class="s2"&gt;" gs: preview vsplit&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="s2"&gt;" ----------------------------&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; Directory node mappings~
&lt;span class="s2"&gt;" double-click,&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; o: open &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; close node
&lt;span class="s2"&gt;" O: recursively open node&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; t: open in new tab
&lt;span class="s2"&gt;" T: open in new tab silently&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; x: close parent of node
&lt;span class="s2"&gt;" X: close all child nodes of&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt;    current node recursively
&lt;span class="s2"&gt;" middle-click,&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; e: explore selected dir
&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; ----------------------------
&lt;span class="s2"&gt;" Bookmark table mappings~&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; double-click,
&lt;span class="s2"&gt;" o: open bookmark&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; t: open in new tab
&lt;span class="s2"&gt;" T: open in new tab silently&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; D: delete bookmark
&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; ----------------------------
&lt;span class="s2"&gt;" Tree navigation mappings~&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; P: go to root
&lt;span class="s2"&gt;" p: go to parent&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; K: go to first child
&lt;span class="s2"&gt;" J: go to last child&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; &amp;lt;C-j&amp;gt;: go to next sibling
&lt;span class="s2"&gt;" &amp;lt;C-k&amp;gt;: go to prev sibling&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="s2"&gt;" ----------------------------&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; Filesystem mappings~
&lt;span class="s2"&gt;" C: change tree root to the&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt;    selected dir
&lt;span class="s2"&gt;" u: move tree root up a dir&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; U: move tree root up a dir
&lt;span class="s2"&gt;"    but leave old root open&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; r: refresh cursor dir
&lt;span class="s2"&gt;" R: refresh current root&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; m: Show menu
&lt;span class="s2"&gt;" cd:change the CWD to the&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt;    selected dir
&lt;span class="s2"&gt;" CD:change tree root to CWD&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="s2"&gt;" ----------------------------&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; Tree filtering mappings~
&lt;span class="s2"&gt;" I: hidden files (off)&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; f: file filters &lt;span class="o"&gt;(&lt;/span&gt;on&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;" F: files (on)&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; B: bookmarks &lt;span class="o"&gt;(&lt;/span&gt;off&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; ----------------------------
&lt;span class="s2"&gt;" Custom mappings~&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="s2"&gt;" ----------------------------&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; Other mappings~
&lt;span class="s2"&gt;" q: Close the NERDTree window&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; A: Zoom &lt;span class="o"&gt;(&lt;/span&gt;maximize-minimize&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"    the NERDTree window&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt; ?: toggle &lt;span class="nb"&gt;help&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/scrooloose/nerdtree"&gt;GitHub - scrooloose/nerdtree: A tree explorer plugin for vim.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! 
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;</content><category term="vim"></category><category term="nerdtree"></category></entry><entry><title>Automating Tmux sessions with tmuxp</title><link href="http://witkowskibartosz.com/blog/automating_tmux_sessions_with_tmuxp.html" rel="alternate"></link><published>2018-03-24T22:05:00+01:00</published><updated>2018-03-24T22:05:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-24:/blog/automating_tmux_sessions_with_tmuxp.html</id><summary type="html">&lt;p&gt;Today I decided to finally use one of tmux session-managers - tmuxp. Check out how to automate your tmux process with this session manager.&lt;/p&gt;</summary><content type="html">&lt;p&gt;It's more convenient to have all of this little details that you normally do day-to-day already pre-scripted - especially if you use it on a computer that you shutdown in a day-to-day fashion.&lt;/p&gt;
&lt;p&gt;That's why I decided to improve my day-to-day blogging experience with tmux and use &lt;a href="https://github.com/tmux-python/tmuxp"&gt;Tmuxp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/tmux-python/tmuxp"&gt;Tmuxp&lt;/a&gt; is a &lt;a href="https://github.com/tmux/tmux"&gt;tmux&lt;/a&gt; session manager created with python. It uses tmuxinator and teamocil style as it says in README docs.&lt;/p&gt;
&lt;p&gt;I'm amused how much features it contains!&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="automating_tmux_sessions_with_tmuxp.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Installation of Tmuxp&lt;/h2&gt;
&lt;p&gt;As my personal preference I use &lt;a href="https://github.com/mitsuhiko/pipsi"&gt;pipsi&lt;/a&gt; to install some of the script-alike stuff - just like a tmuxp:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipsi install tmuxp
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can also install tmuxp with pip (in a virtualenv if you prefer, or not, up to you):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install tmuxp
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Usage of Tmuxp&lt;/h2&gt;
&lt;p&gt;Once you will create your first configuration, you can load it as a tmux session with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;tmuxp load yourtmuxconfig.yaml &lt;span class="c1"&gt;# or yourtmuxconfig.json&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;For the example below, it will create 4 panes that are tiled - meanig as a 4 equaly defined boxes.&lt;/p&gt;
&lt;p&gt;BTW - did you know that if you have already one session with the same name as the one you are loading, tmuxp will ask you if you want to attach to that session?&lt;/p&gt;
&lt;p&gt;That's very convenient! So instead of making &lt;code&gt;tmux attach -t nameofsession&lt;/code&gt; you can actually use the &lt;code&gt;tmux load yourconfig.json&lt;/code&gt; and it will attach after answering &lt;code&gt;y&lt;/code&gt; to that created session.&lt;/p&gt;
&lt;h2&gt;Yaml and Json config files&lt;/h2&gt;
&lt;p&gt;So in Tmuxp you can actually use two type of files - yaml and json.&lt;/p&gt;
&lt;p&gt;Simple example of that:&lt;/p&gt;
&lt;p&gt;YAML:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;session_name&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;4-pane-split&lt;/span&gt;
&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
&lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;window_name&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;dev window&lt;/span&gt;
  &lt;span class="l l-Scalar l-Scalar-Plain"&gt;layout&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;tiled&lt;/span&gt;
  &lt;span class="l l-Scalar l-Scalar-Plain"&gt;shell_command_before&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;cd ~/&lt;/span&gt;
  &lt;span class="l l-Scalar l-Scalar-Plain"&gt;panes&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;shell_command&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
        &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;cd /var/log&lt;/span&gt;
        &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;ls -al | grep \.log&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;echo hello&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;echo hello&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;echo hello&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;JSON:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;windows&amp;quot;&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="nt"&gt;&amp;quot;panes&amp;quot;&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="nt"&gt;&amp;quot;shell_command&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;cd /var/log&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="s2"&gt;&amp;quot;ls -al | grep \\.log&amp;quot;&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt; 
            &lt;span class="s2"&gt;&amp;quot;echo hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;echo hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;echo hello&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;quot;shell_command_before&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;cd ~/&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;quot;layout&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;tiled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;quot;window_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;dev window&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;quot;session_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;4-pane-split&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So comparing those two - it feels like YAML is easier to use and less coding needed to have a working solution. But with my vim and python experience I find it less handy. It's probably because I have predefined strangly tab to always insert as 4 spaces no matter what type of file I'm editing (python requirements). Yeah I will fix that someday, but for now it makes my experience with YAML files less pleasant so I'd better be off with JSON as a personal preference.&lt;/p&gt;
&lt;h2&gt;Configuration&lt;/h2&gt;
&lt;p&gt;Tmuxp configuration consists of sessions and windows and panes.&lt;/p&gt;
&lt;h3&gt;Sessions and windows&lt;/h3&gt;
&lt;p&gt;Your sessions are at the bottom.&lt;/p&gt;
&lt;p&gt;Creating new session with one pane and only session name using JSON file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;windows&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;session_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;4-pane-split&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Multiple Windows&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;windows&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;panes&amp;quot;&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="nt"&gt;&amp;quot;panes&amp;quot;&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;span class="nt"&gt;&amp;quot;session_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2-pane-split&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Multiple Windows with focus specified&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;windows&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;panes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;echo &amp;#39;first pane&amp;#39;&amp;quot;&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="nt"&gt;&amp;quot;panes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;echo &amp;#39;second pane&amp;#39;&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;focus&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;panes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;echo &amp;#39;third pane&amp;#39;&amp;quot;&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="nt"&gt;&amp;quot;session_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;focus-pane&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Configuration options that you can use&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;shell_command_before&lt;/code&gt; - this is used before making call on each of the pane's scripts.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;window_name&lt;/code&gt; - this is a name for each of the windows that are within this session.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;suppress_history&lt;/code&gt; - to override default comamnd suppression.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;window_index&lt;/code&gt; - if you want to change the default sorting and placement of windows at your session&lt;/li&gt;
&lt;li&gt;&lt;code&gt;start_directory&lt;/code&gt; - you can globally use this variable as well as locally for specific pane scripts and nesting one to another as you can see in my configuration&lt;/li&gt;
&lt;li&gt;&lt;code&gt;focus&lt;/code&gt; - option to make one of the windows and panes to be focused after loading config - unfortunatelly it did not worked for me and as &lt;a href="https://github.com/tmux-python/tmuxp/issues/326"&gt;listed in this issue, i'm not the only one having this bug&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;options&lt;/code&gt; and &lt;code&gt;global_options&lt;/code&gt;- this contains changing settings (per window or globally) for:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;automatic-rename&lt;/code&gt; - you can set if you want your panes and windows to autotically change name or not&lt;/li&gt;
&lt;li&gt;&lt;code&gt;default-shell&lt;/code&gt; - you can set your default shell that will be run on panes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;default-command&lt;/code&gt; - you can set your default command on panes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main-pane-height&lt;/code&gt; - you can set height of pane.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is probably a lot more but that should be enough to make some sophisticated tmux session configuration for tmuxp.&lt;/p&gt;
&lt;p&gt;Check out more at the &lt;a href="https://tmuxp.git-pull.com/en/latest/examples.html"&gt;example section in documentation of tmuxp&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;My personal usage for creating this blog&lt;/h2&gt;
&lt;p&gt;For now I decided create tmuxp config like that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;start_directory&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;~/projects/anselmos_blog/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;windows&amp;quot;&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="nt"&gt;&amp;quot;window_index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;window_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;start_directory&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;./data/content/articles&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;panes&amp;quot;&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="nt"&gt;&amp;quot;shell_command&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                       &lt;span class="s2"&gt;&amp;quot;vim .&amp;quot;&lt;/span&gt;
                    &lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;quot;focus&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;focus&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;window_index&amp;quot;&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="nt"&gt;&amp;quot;window_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;dev&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;start_directory&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;./data&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;shell_command_before&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;cd pelican-plugins/pelican_link_to_title/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;sh runredis.sh&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;cd -&amp;quot;&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;panes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;pipenv run make devserver&amp;quot;&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="nt"&gt;&amp;quot;window_index&amp;quot;&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="nt"&gt;&amp;quot;window_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;publish&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;shell_command_before&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;cd ~/projects/anselmos_blog/&amp;quot;&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;panes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;echo &amp;#39;make publish_ftp&amp;#39;&amp;quot;&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="nt"&gt;&amp;quot;window_index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;window_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;social&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;shell_command_before&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;cd ~/projects/day_to_day_automation/blog/&amp;quot;&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;panes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;echo &amp;#39;pipenv run python get_post_summary.py ~/projects/anselmos_blog/data/content/articles/&amp;#39;&amp;quot;&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="nt"&gt;&amp;quot;session_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;blog&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This creates 4 panes:
- one with vim opened at articles directory
- second with pelican starting development-ready server that automatically detects changes in .md files.
- third with echoing make publish_ftp for my convenience to have it already there.
- last one that is for re-using the &lt;a href="how-to-use-pyperclip.md"&gt;get_post_summary.py as seen in this article&lt;/a&gt;&lt;/p&gt;
&lt;div id="asciinema"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="automating_tmux_sessions_with_tmuxp.html#asciinema"&gt; Asciinema &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;link rel="stylesheet" type="text/css" href="css/asciinema-player2.css" /&gt;&lt;/p&gt;
&lt;p&gt;4 pane split example:
&lt;asciinema-player src="asciinema/tmuxp_example.cast"&gt;&lt;/asciinema-player&gt;&lt;/p&gt;
&lt;p&gt;2 empty panes (check it in a fullscreen to see bottom pane with tmux name of panes):
&lt;asciinema-player src="asciinema/tmuxp_example2.cast"&gt;&lt;/asciinema-player&gt;&lt;/p&gt;
&lt;p&gt;3 empty panes with focus on the middle one (check it in a fullscreen to see bottom pane with tmux name of panes):
&lt;asciinema-player src="asciinema/tmuxp_example3.cast"&gt;&lt;/asciinema-player&gt;&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="automating_tmux_sessions_with_tmuxp.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="automating_tmux_sessions_with_tmuxp.html#asciinema"&gt;Asciinema&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! 
&lt;script src="scripts/asciinema-player2.js"&gt;&lt;/script&gt;&lt;/p&gt;</content><category term="tmux"></category><category term="tmuxp"></category><category term="tmux-sessions"></category><category term="tmux-automation"></category><category term="tmux-pane"></category><category term="pipsi"></category></entry><entry><title>Python Django Framework examples of decorators</title><link href="http://witkowskibartosz.com/blog/python_django_framework_examples_of_decorators.html" rel="alternate"></link><published>2018-03-23T18:55:00+01:00</published><updated>2018-03-23T18:55:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-23:/blog/python_django_framework_examples_of_decorators.html</id><summary type="html">&lt;p&gt;To improve learning of decorators I've decided to find real-life examples of decorators in django framework. Check out my review on that!&lt;/p&gt;</summary><content type="html">&lt;p&gt;To improve learning of decorators I've decided to find real-life examples of decorators in django framework.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="python_django_framework_examples_of_decorators.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;To be more precise in our adventure through decorators I decided to look for the most used python frameworks/libraries and find decorators that may be useful.&lt;/p&gt;
&lt;p&gt;In &lt;a href=""&gt;Django&lt;/a&gt; documentation you can find &lt;a href="https://docs.djangoproject.com/en/2.0/topics/http/decorators/#module-django.views.decorators.http"&gt;View Decorators&lt;/a&gt; which explains view decorators. In the &lt;a href="https://github.com/django/django"&gt;source-code of django&lt;/a&gt; you can find those decorator packages/modules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/contrib/auth/decorators.py"&gt;&lt;code&gt;django/contrib/auth/decorators.py&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/contrib/auth/decorators.py#L10"&gt;&lt;code&gt;users_passes_test&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/contrib/auth/decorators.py#L38"&gt;&lt;code&gt;login_required&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/contrib/auth/decorators.py#L53"&gt;&lt;code&gt;permission_required&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/utils/decorators.py"&gt;&lt;code&gt;django/django/utils/decorators.py&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/utils/decorators.py#L15"&gt;&lt;code&gt;method_decorator&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/utils/decorators.py#L91"&gt;&lt;code&gt;decorator_from_middleware_with_args&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/utils/decorators.py#L107"&gt;&lt;code&gt;decorator_from_middleware&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/utils/decorators.py#L126"&gt;&lt;code&gt;make_middleware_decorator&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/tree/stable/2.0.x/django/views/decorators"&gt;&lt;code&gt;django/views/decorators/&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/views/decorators/http.py#L20"&gt;&lt;code&gt;require_http_methods&lt;/code&gt;&lt;/a&gt; is a http-method decorator that uses &lt;a href="https://docs.python.org/3/library/functools.html#functools.wraps"&gt;@wraps&lt;/a&gt; - from which we learn that using &lt;code&gt;@wraps&lt;/code&gt; at decorator inner-function prevents problem with passing &lt;code&gt;__docs__&lt;/code&gt;  and &lt;code&gt;__name__&lt;/code&gt; of decorated function.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/django/django/blob/stable/2.0.x/django/views/decorators/http.py#L45"&gt;&lt;code&gt;require_GET&lt;/code&gt;&lt;/a&gt; is a derivation of &lt;code&gt;require_http_methods&lt;/code&gt; which includes only &lt;code&gt;GET&lt;/code&gt; method as a parameter to that function. - also it changes &lt;code&gt;__doc__&lt;/code&gt; of the function to have different docs than in &lt;code&gt;require_http_methods&lt;/code&gt; - for more readability.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="python_django_framework_examples_of_decorators.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/django/django"&gt;GitHub - django/django: The Web framework for perfectionists with deadlines.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/2.0/topics/http/decorators/#module-django.views.decorators.http"&gt;View decorators | Django documentation | Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vinta/awesome-python"&gt;GitHub - vinta/awesome-python: A curated list of awesome Python frameworks, libraries, software and resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/uralbash/awesome-pyramid"&gt;GitHub - uralbash/awesome-pyramid: A curated list of awesome Pyramid apps, projects and resources.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3.6/library/functools.html"&gt;10.2. functools — Higher-order functions and operations on callable objects — Python 3.6.5rc1 documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/functools.html#functools.update_wrapper"&gt;10.2. functools — Higher-order functions and operations on callable objects — Python 3.6.5rc1 documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="decorator"></category><category term="django"></category></entry><entry><title>Python Function Annotations</title><link href="http://witkowskibartosz.com/blog/python_function_annotations.html" rel="alternate"></link><published>2018-03-22T09:20:00+01:00</published><updated>2018-03-22T09:20:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-22:/blog/python_function_annotations.html</id><summary type="html">&lt;p&gt;Python core community decided to create annotations from 3.0 version. Check out what are they all about and how to use them.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Within &lt;a href="https://www.python.org/dev/peps/pep-3107/"&gt;PEP 3107&lt;/a&gt; you can find the original PEP&lt;a href="https://www.python.org/dev/peps/"&gt;(Python Enhancement Proposals)&lt;/a&gt; for annotations of funcion parameters and return values.&lt;/p&gt;
&lt;p&gt;This proposal that has been accepted is unfortunatelly only for Python3 and ongoing releases. Python2 out of the box backward compatibility is not possible.&lt;/p&gt;
&lt;p&gt;Yet you can create some backward compatibility for those annotations if you need to.&lt;/p&gt;
&lt;p&gt;Check out what this annotations are all about!&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="python_function_annotations.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h1&gt;Annotations&lt;/h1&gt;
&lt;p&gt;In other languages you have types. You expressly define your variable types, function return types and parameters types.&lt;/p&gt;
&lt;p&gt;In Python 2 you could not do that (it would raise with SyntaxError) and frankly speaking you did not expect to do that.&lt;/p&gt;
&lt;p&gt;In Python 3 you can use annotations to simulate defining function and variable types.&lt;/p&gt;
&lt;p&gt;Here is example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greeting&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'Hello '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So basically you have created a function that in python2 would look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greeting&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;return&lt;/span&gt; &lt;span class="s1"&gt;'Hello '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But annotations gives you opportunity to check what type of output and parameter types you have within this function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__annotations__&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unfortunatelly or fortunatelly it does not do anything else - So if you make annotations but you do not follow it - it will not raise it.&lt;/p&gt;
&lt;p&gt;We can change that with decorator that will check that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator_annotation_for_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_wrapped&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;wrapper&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;annotations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_wrapped&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__annotations__&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_wrapped&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;returned_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'return'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;returned_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;returned_type&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Example of usage for this decorator:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nd"&gt;@decorator_annotation_for_return&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greetings&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"Hello "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greetings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Anselmos"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# This will fail:&lt;/span&gt;
&lt;span class="nd"&gt;@decorator_annotation_for_return&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greetings_failing&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;greetings_failing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can also create a parameter types checker with decorators, but in order for it to work properly you would need to use &lt;code&gt;**kwargs&lt;/code&gt; - which means you need to expressively name arguments for function.&lt;/p&gt;
&lt;p&gt;Check out example of that decorator:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator_annotation_parameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_wrapped&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;wrapper&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;annotations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_wrapped&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__annotations__&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_wrapped&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;returned_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'return'&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;kwarg&lt;/span&gt; &lt;span class="ow"&gt;in&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;kwarg_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="o"&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;kwarg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&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;kwarg&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;kwarg_type&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;returned_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;returned_type&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@decorator_annotation_parameters&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greetings_parameter&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&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;name&lt;/span&gt;


&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greetings_parameter&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It may need some tweaking to have better readiness but it works.&lt;/p&gt;
&lt;p&gt;Also check out the suggested in pep &lt;a href="https://www.python.org/dev/peps/pep-3107/#use-cases"&gt;Use Cases&lt;/a&gt;.&lt;/p&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="python_function_annotations.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;annotation_parameter_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;annotation_parameter_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator_annotation_parameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_wrapped&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;wrapper&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;annotations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_wrapped&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__annotations__&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_wrapped&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;returned_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'return'&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;kwarg&lt;/span&gt; &lt;span class="ow"&gt;in&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;kwarg_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="o"&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;kwarg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&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;kwarg&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;kwarg_type&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;returned_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;returned_type&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="python_function_annotations.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="python_function_annotations.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.python.org/dev/peps/pep-3107/"&gt;PEP 3107 -- Function Annotations | Python.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.python.org/dev/peps/pep-0526/"&gt;PEP 526 -- Syntax for Variable Annotations | Python.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/PythonCharmers/python-future"&gt;GitHub - PythonCharmers/python-future: Easy, clean, reliable Python 2/3 compatibility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.python.org/dev/peps/pep-0484/"&gt;PEP 484 -- Type Hints | Python.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="python-v3"></category><category term="python-annotations"></category></entry><entry><title>Creating RSS Feed links in pelican theme</title><link href="http://witkowskibartosz.com/blog/creating-rss-feed-links-in-pelican-theme.html" rel="alternate"></link><published>2018-03-21T08:57:00+01:00</published><updated>2018-03-21T08:57:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-21:/blog/creating-rss-feed-links-in-pelican-theme.html</id><summary type="html">&lt;p&gt;Today I realized that my rss feeds are not clearly visible at the site. Let's add them at the menu in pelican-bootstrap3 theme.&lt;/p&gt;</summary><content type="html">&lt;p&gt;There are at least 2 options that I know how to add RSS link to pelican-bootstrap3 theme.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="creating-rss-feed-links-in-pelican-theme.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Adding RSS&lt;/h2&gt;
&lt;p&gt;First things first - if you have not yet setup your RSS at pelican with pelican-bootstrap3, you can with this in your configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;AUTHOR_FEED_ATOM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# here you can put something like 'feeds/%s.author.xml'&lt;/span&gt;
&lt;span class="n"&gt;AUTHOR_FEED_RSS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# here you can put something like 'feeds/%s.author.xml'&lt;/span&gt;
&lt;span class="n"&gt;FEED_ALL_ATOM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'feeds/all.atom.xml'&lt;/span&gt;
&lt;span class="n"&gt;TAG_FEED_ATOM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'feeds/&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;.tag.atom.xml'&lt;/span&gt;
&lt;span class="n"&gt;CATEGORY_FEED_ATOM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'feeds/&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;.atom.xml'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;RSS at the top menu of side.&lt;/h2&gt;
&lt;p&gt;You obviously can add RSS link on the top menu.&lt;/p&gt;
&lt;p&gt;To do that add to your &lt;code&gt;pelicanconf.py&lt;/code&gt; or &lt;code&gt;publishconf.py&lt;/code&gt; in MENUITEMS list item like that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;MENUITEMS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'RSS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"feeds/all.atom.xml"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;RSS in the blogroll link&lt;/h2&gt;
&lt;p&gt;In the "blogroll" links:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;LINKS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'RSS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"feeds/all.atom.xml"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Tweaking top-menu theme of pelican-bootstrap3&lt;/h1&gt;
&lt;p&gt;As suggested in this &lt;a href="https://abyvinod.github.io/setMeup.html"&gt;pelican blog setup&lt;/a&gt; - I decided to also tweak my top-menu theme items with icons.&lt;/p&gt;
&lt;p&gt;To do this I've changed &lt;code&gt;MENUITEMS&lt;/code&gt; generation at &lt;code&gt;template/base.html&lt;/code&gt; with this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;{% for title, link, icon in MENUITEMS %}
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"{{ link }}"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"fa {{icon}} fa-lg"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;{{ title }}&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
{% endfor %}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The MENUITEMS now looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;MENUITEMS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'RSS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"feeds/all.atom.xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'fa-rss'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So from now on I can add one of &lt;a href="https://fontawesome.com/icons?d=gallery&amp;amp;m=free"&gt;FontAwesome icons&lt;/a&gt; into my menu-items with ease.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="creating-rss-feed-links-in-pelican-theme.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/getpelican/pelican-themes/tree/master/pelican-bootstrap3"&gt;pelican-themes/pelican-bootstrap3 at master · getpelican/pelican-themes · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://querbalken.net/howto-activate-feeding-for-pelican-blog-en.html"&gt;Querbalken, Andreas Hüwel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://abyvinod.github.io/setMeup.html"&gt;Blogging using Pelican + Conda + GitHub Pages - Notes on the margin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/conda/conda"&gt;GitHub - conda/conda: OS-agnostic, system-level binary package manager and ecosystem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.support.wordpress.com/blogroll/"&gt;
		Links Menu (Blogroll) — Support — WordPress.com
	&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fontawesome.com/icons?d=gallery&amp;amp;m=free"&gt;Icons | Font Awesome&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! 
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;</content><category term="pelican"></category><category term="pelican-theme"></category><category term="tweaking-theme"></category></entry><entry><title>Accelerating pelican plugin execution</title><link href="http://witkowskibartosz.com/blog/accelerating-pelican-plugin-execution.html" rel="alternate"></link><published>2018-03-20T23:30:00+01:00</published><updated>2018-03-20T23:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-20:/blog/accelerating-pelican-plugin-execution.html</id><summary type="html">&lt;p&gt;After a bit of research I've found one plugin that led me to make a change in pelican_link_to_title plugin. Check out if my assumption is right and it will accelerate pelican-plugin execution.&lt;/p&gt;</summary><content type="html">&lt;p&gt;In &lt;a href="debugging-slowness-of-pelican-link-to-title-plugin.html"&gt;previous post&lt;/a&gt; I have made some quick fix with redis that makes re-loading links a bit faster.&lt;/p&gt;
&lt;p&gt;While I was searching for some plugins that I could use in my blog, I've found &lt;a href="https://github.com/classner/better_code_samples/blob/8ae86dcddb4f65d0e6b5f1afe84b6afdb4297668/better_code_samples.py"&gt;this plugin source code&lt;/a&gt; which uses &lt;code&gt;content_object_init&lt;/code&gt; signal. Let's check if using this will make our plugin even faster.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="accelerating-pelican-plugin-execution.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;To be precise and have reliable performance checks let's first change our debugging project and add more articles with links to it.&lt;/p&gt;
&lt;p&gt;Source code of debugging plugin for performance can be found &lt;a href="https://github.com/anselmos/pelican-link-to-title/tree/optimization_content_object_init"&gt;at this branch&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Comparison&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Without plugin&lt;/p&gt;
&lt;p&gt;Took 0.14 second.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;With previous plugin (redis-aware)&lt;/p&gt;
&lt;p&gt;Took 0.17-0.20 second.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;With &lt;code&gt;content_object_init&lt;/code&gt; change.&lt;/p&gt;
&lt;p&gt;First time:&lt;/p&gt;
&lt;p&gt;Took ~10 second.&lt;/p&gt;
&lt;p&gt;Second time(and next):&lt;/p&gt;
&lt;p&gt;Took ~0.20 second.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Source Code of changed plugin&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class="sd"&gt;""" This is a main script for pelican_link_to_title """&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pelican&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;urllib&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;link_to_title_plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;"Link_to_Title plugin "&lt;/span&gt;
    &lt;span class="n"&gt;article_ahreftag&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;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ahref_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ahref'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ahref_tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;article_ahreftag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ahref_tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soup&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;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soup&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;article_ahreftag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&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;tag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;p_tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"http://"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"https://"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"utf-8"&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;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&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;redis&lt;/span&gt;
    &lt;span class="n"&gt;redconn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redconn&lt;/span&gt;&lt;span class="o"&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;url_page&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;found&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"html.parser"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;redconn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&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;title&lt;/span&gt;
    &lt;span class="k"&gt;else&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;found&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;content_object_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"html5lib"&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;ctbl&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ahref'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctbl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"http://"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"https://"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;ctbl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;ctbl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;pass&lt;/span&gt;
            &lt;span class="n"&gt;ctbl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;# If beautiful soup appended html tags.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;html&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;14&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;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;""" Registers Plugin """&lt;/span&gt;
    &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content_object_init&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_object_init&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# signals.article_generator_finalized.connect(link_to_title_plugin)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Effects&lt;/h2&gt;
&lt;p&gt;Well as I see the efects are not so much different.&lt;/p&gt;
&lt;p&gt;I will need to check if updating urllib into something with parallelism will make it better.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="accelerating-pelican-plugin-execution.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/7191337/python-better-network-api-than-urllib"&gt;Python Better network API than urllib - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/Python/comments/1tvdrj/something_faster_than_urllib2open/"&gt;Something faster than urllib2.open()? : Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/3490173/how-can-i-speed-up-fetching-pages-with-urllib2-in-python"&gt;time - How can I speed up fetching pages with urllib2 in python? - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/2018026/what-are-the-differences-between-the-urllib-urllib2-and-requests-module"&gt;python - What are the differences between the urllib, urllib2, and requests module? - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="pelican"></category><category term="pelican_engine"></category><category term="pelican-plugin"></category><category term="pelican_link_to_title"></category><category term="redis"></category></entry><entry><title>Debugging slowness of pelican-link-to-title plugin</title><link href="http://witkowskibartosz.com/blog/debugging-slowness-of-pelican-link-to-title-plugin.html" rel="alternate"></link><published>2018-03-19T22:20:00+01:00</published><updated>2018-03-19T22:20:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-19:/blog/debugging-slowness-of-pelican-link-to-title-plugin.html</id><summary type="html">&lt;p&gt;Lately after using my pelican-link-to-title plugin I've found it slows down recreating html files. Let's debug what can be wrong with the plugin.&lt;/p&gt;</summary><content type="html">&lt;p&gt;In the &lt;a href="making-pelican-link-to-title-plugin.html"&gt;Making pelican-link-to-title plugin article&lt;/a&gt; I've created a neat script that uses &lt;code&gt;&amp;lt;ahref&amp;gt;link&amp;lt;/ahref&amp;gt;&lt;/code&gt; and transforms this to &lt;code&gt;&amp;lt;a href="link"&amp;gt;TITLE OF LINK&amp;lt;/a&amp;gt;&lt;/code&gt;. Today I'm going to analyze what I've done wrong while creating this plugin. Check out.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="updating-pelican-link-to-title-plugin.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Slowness of plugin&lt;/h2&gt;
&lt;p&gt;How can you analyze slowness of plugin? &lt;/p&gt;
&lt;p&gt;First let's test how much time it will take to generate html content without plugin:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git clone --recursive-modules https://github.com/anselmos/debug_pelican_plugins &lt;span class="c1"&gt;# or --recursive if you have git &amp;lt; 2.13&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; debug_pelican_plugins
pipenv shell
make html
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The last command shows how much time it took to generate pages.&lt;/p&gt;
&lt;p&gt;To be able to check performance of plugin I need to add a bit more than only one link.&lt;/p&gt;
&lt;p&gt;Let's create a content that will have at least 5 different page links.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Title: first
Date: 2018-03-19 20:30
Status: published
Author: Witkowski Bartosz
Slug: first
# first

# some topic for first


&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;http://bbc.com/&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;https://stackoverflow.com/&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;https://github.com/&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;http://abc.go.com/&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;https://www.quora.com&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;https://www.thegoodwebguide.co.uk/lifestyle/website-reviews/best-sites-news-information/best-alternative-news-sites/13301&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;http://wakatime.com/&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;http://twitter.com/&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;https://www.facebook.com/AnselmosBlog/&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ahref&amp;gt;&lt;/span&gt;https://tomato-timer.com/&lt;span class="nt"&gt;&amp;lt;/ahref&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And now let's find out how much time it takes to generate content for this article without plugin, and with plugin:&lt;/p&gt;
&lt;p&gt;without:    ~ 0.15 s.
with:       ~ 10-12 s ...&lt;/p&gt;
&lt;p&gt;And it's after a bit of optimizations with looping.&lt;/p&gt;
&lt;p&gt;The biggest bottleneck is the urllib and obtaining page-source with it. There is solution with httplib2 which I'm going to cover in next episode.&lt;/p&gt;
&lt;p&gt;This time let's focus on making a type of caching for this requests.&lt;/p&gt;
&lt;p&gt;Let's create a redis cache with link-title elements.&lt;/p&gt;
&lt;h1&gt;Redis&lt;/h1&gt;
&lt;p&gt;&lt;a href=""&gt;Redis&lt;/a&gt; is a key-value pair database server (no-sql). It's fast and reliable. Let's make a query with it in our plugin:&lt;/p&gt;
&lt;h2&gt;Starting redis from Docker&lt;/h2&gt;
&lt;p&gt;To start Redis you can install it on system. I prefer use docker instead:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run --name pelican-redis -v &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/redis:/data -d redis redis-server --appendonly yes
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;and the plugin looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; This is a main script for pelican_link_to_title &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pelican&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;urllib&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;link_to_title_plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Link_to_Title plugin &amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;article_ahreftag&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;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;html.parser&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ahref_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ahref&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ahref_tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;article_ahreftag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ahref_tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soup&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;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soup&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;article_ahreftag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&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;tag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;p_tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;http://&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;href&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;utf-8&amp;quot;&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;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&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;redis&lt;/span&gt;
    &lt;span class="n"&gt;redconn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redconn&lt;/span&gt;&lt;span class="o"&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;url_page&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;found&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;html.parser&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;redconn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&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;title&lt;/span&gt;
    &lt;span class="k"&gt;else&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;found&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Registers Plugin &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link_to_title_plugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This makes rendering again at the ~0.15 s. :) &lt;/p&gt;
&lt;p&gt;This has limitations - first time when links are obtained by urllib it will take ~10-12 seconds.&lt;/p&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! 
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;</content><category term="pelican"></category><category term="pelican_engine"></category><category term="pelican-plugin"></category><category term="pelican_link_to_title"></category><category term="redis"></category></entry><entry><title>Gitgutter Vim plugin</title><link href="http://witkowskibartosz.com/blog/gitgutter-vim-plugin.html" rel="alternate"></link><published>2018-03-18T07:30:00+01:00</published><updated>2018-03-18T07:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-18:/blog/gitgutter-vim-plugin.html</id><summary type="html">&lt;p&gt;I've stumbled upon gitgutter vim plugin that I found a more convenient to use within vim than git-diff. Check out how to use it.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://github.com/airblade/vim-gitgutter"&gt;GitGutter&lt;/a&gt; plugin lets you manage your file changes within git-repository with vim by adding signs at the left side to the line numbers.&lt;/p&gt;
&lt;p&gt;Also, you can :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Move between git-hunks (changes chunks)&lt;/li&gt;
&lt;li&gt;Undo your git-hunks&lt;/li&gt;
&lt;li&gt;See all hunks in a vim-split.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="gitgutter-vim-plugin.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;To install &lt;a href="https://github.com/airblade/vim-gitgutter"&gt;gitgutter&lt;/a&gt;, I'd suggest using Vundle with adding this to your &lt;code&gt;.vimrc&lt;/code&gt; config file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Plugin &lt;span class="s1"&gt;'airblade/vim-gitgutter'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then install usually with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;vim +PluginInstall +qall
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For more information about installation, check out &lt;a href="https://github.com/airblade/vim-gitgutter#installation"&gt;installation guide provided by the author of the plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;To use this plugin all you need to do is first a add file to your git repository and then start making changes in it. &lt;/p&gt;
&lt;p&gt;Please be adviced that Vim has an &lt;code&gt;updatetime&lt;/code&gt; flag that I suggest you tweak from 4000ms to (as I checked) around 250ms. 
Changing to 250ms is a bit better and less clunky compared to what author suggests with 100ms.&lt;/p&gt;
&lt;p&gt;To make that change, add this to your vim-config &lt;code&gt;.vimrc&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;updatetime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;250&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Turning gitgutter off&lt;/h2&gt;
&lt;p&gt;If you don't like how gitgutter works you may uninstall this plugin or if it's only for some of the files you can disable this plugin with vim-command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;:GitGutterDisable
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Turning gitgutter on&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;:GitGutterEnable
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;GitGutter toggle on/off&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;:GitGutterToggle
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Jumping to next change/chunk&lt;/h2&gt;
&lt;p&gt;Use &lt;code&gt;]c&lt;/code&gt; for next and &lt;code&gt;[c&lt;/code&gt; for previous.&lt;/p&gt;
&lt;p&gt;To customise key-mapping, use this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;nmap &lt;span class="o"&gt;]&lt;/span&gt;h &amp;lt;Plug&amp;gt;GitGutterNextHunk
nmap &lt;span class="o"&gt;[&lt;/span&gt;h &amp;lt;Plug&amp;gt;GitGutterPrevHunk
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Undoing your hunks&lt;/h2&gt;
&lt;p&gt;You can undo hanks with &lt;code&gt;&amp;lt;Leader&amp;gt;hu&lt;/code&gt; or re-map key-combination with this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;nmap &amp;lt;Leader&amp;gt;hu &amp;lt;Plug&amp;gt;GitGutterUndoHunk
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Preview hunk&lt;/h2&gt;
&lt;p&gt;You can preview hunk with &lt;code&gt;&amp;lt;Leader&amp;gt;hp&lt;/code&gt; or re-map key-combination with this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;nmap &amp;lt;Leader&amp;gt;hv &amp;lt;Plug&amp;gt;GitGutterPreviewHunk
&lt;/pre&gt;&lt;/div&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="gitgutter-vim-plugin.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;GitGutter Vim-Commands and KeyCombinations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Disable: &lt;code&gt;:GitGutterDisable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Enable: &lt;code&gt;:GitGutterEnable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Toggle: &lt;code&gt;:GitGutterToggle&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;NextHunk: &lt;code&gt;]h&lt;/code&gt; ( re-mapped from &lt;code&gt;]c&lt;/code&gt; )&lt;/li&gt;
&lt;li&gt;PrevHunk: &lt;code&gt;[h&lt;/code&gt; ( re-mapped from &lt;code&gt;[c&lt;/code&gt; )&lt;/li&gt;
&lt;li&gt;UndoHunk: &lt;code&gt;&amp;lt;Leader&amp;gt;hu&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;PreviewHunk: &lt;code&gt;&amp;lt;Leader&amp;gt;hv&lt;/code&gt; ( re-mapped from &lt;code&gt;&amp;lt;Leader&amp;gt;hp&lt;/code&gt; )&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="gitgutter-vim-plugin.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="gitgutter-vim-plugin.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/airblade/vim-gitgutter"&gt;GitHub - airblade/vim-gitgutter: A Vim plugin which shows a git diff in the gutter (sign column) and stages/undoes hunks.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1764263/what-is-the-leader-in-a-vimrc-file"&gt;vim - What is the &amp;lt;leader&amp;gt; in a .vimrc file? - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="vim"></category><category term="vim-plugins"></category><category term="vim-gitgutter"></category></entry><entry><title>How to use pyperclip</title><link href="http://witkowskibartosz.com/blog/how-to-use-pyperclip.html" rel="alternate"></link><published>2018-03-17T00:00:00+01:00</published><updated>2018-03-17T00:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-17:/blog/how-to-use-pyperclip.html</id><summary type="html">&lt;p&gt;Lately I've found python library called pyperclip - it enables to copy from and to clipboard. Check out how to use it!&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://github.com/asweigart/pyperclip"&gt;Pyperclip&lt;/a&gt; is a python module that enables managing our system clipboard. It is a cross-platform module.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="how-to-use-pyperclip.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Installation of pyperclip&lt;/h2&gt;
&lt;h3&gt;System Dependency&lt;/h3&gt;
&lt;p&gt;On Windows you don't need to install any additional software.&lt;/p&gt;
&lt;p&gt;On Linux you need to install either &lt;code&gt;xclip&lt;/code&gt; or &lt;code&gt;xsel&lt;/code&gt;, but the recommended is &lt;code&gt;xclip&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get install xclip
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;p&gt;Python module can be installed with simple pip command :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install pyperclip
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or via pipenv :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv install pyperclip
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Using pyperclip&lt;/h2&gt;
&lt;p&gt;That's pretty easy, commands are :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pyperclip.copy&lt;/code&gt; - for making a copy of data to clipboard (as a parameter)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pyperclip.paste&lt;/code&gt; - for pasting from clipboard data in python.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Examples of usage&lt;/h2&gt;
&lt;p&gt;I'm going to use pyperclip as a system for copying summaries from blog-posts.&lt;/p&gt;
&lt;p&gt;Check out this script that I'm going to use to make my day-to-day easier and more automated:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pyperclip&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;argparse&lt;/span&gt;
&lt;span class="n"&gt;YOUR_DOMAIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://witkowskibartosz.com/blog/"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_file_markdown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;SLUG_TAG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Slug: "&lt;/span&gt;
    &lt;span class="n"&gt;SUMMARY_TAG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Summary: "&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="n"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_file_markdown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;filemarkdown&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;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filemarkdown&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;SLUG_TAG&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SLUG_TAG&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;SUMMARY_TAG&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SUMMARY_TAG&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;summary&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;make_social_text_and_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;" : "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;YOUR_DOMAIN&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;".html"&lt;/span&gt;
    &lt;span class="n"&gt;pyperclip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Arguments of this script'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'markdownfile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metavar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'N'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'+'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;markdownfile&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;make_social_text_and_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This basically reads md file, looks for SLUG and SUMMARY and makes a social text that is being copied to clipboard.&lt;/p&gt;
&lt;p&gt;To use this script, you need to add path to md file as argument to python script like that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;pipenv&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;get_post_summary&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="n"&gt;your_path_to_md_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="how-to-use-pyperclip.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Simulates CTRL+C (copy):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;pyperclip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'some text that goes to clipboard'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Simulates CTRL+V (paste):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;pyperclip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="how-to-use-pyperclip.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="how-to-use-pyperclip.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/asweigart/pyperclip"&gt;GitHub - asweigart/pyperclip: Python module for cross-platform clipboard functions.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3.3/library/argparse.html"&gt;16.4. argparse — Parser for command-line options, arguments and sub-commands — Python 3.3.7 documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="pyperclip"></category><category term="copy-paste"></category></entry><entry><title>Using markings and vim-signature plugin</title><link href="http://witkowskibartosz.com/blog/using-markings-and-vim-signature-plugin.html" rel="alternate"></link><published>2018-03-16T08:00:00+01:00</published><updated>2018-03-16T08:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-16:/blog/using-markings-and-vim-signature-plugin.html</id><summary type="html">&lt;p&gt;Lately I've found one plugin in my vimrc file that I didn't recall. I searched it and found it's the one for making left-side signatures to which you can jump. Check out how to use it!&lt;/p&gt;</summary><content type="html">&lt;p&gt;You can look at the project-page of this plugin to see it in action &lt;a href="https://github.com/kshenoy/vim-signature"&gt;github-repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This plugin allows to see markings of file at the left bar before line-numbers.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="using-markings-and-vim-signature-plugin.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Usages of vim markings and vim-signature&lt;/h2&gt;
&lt;p&gt;Vim Marks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can jump right to the place where you left writing your code/blog-post/whatever.&lt;/li&gt;
&lt;li&gt;You can sign a place that is important in project you are working on to remember about something in there (as opposite to #FIXME/ #TODO which lefts data in code)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vim Signature plugin&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allows to see where the markings are set instead of making call to &lt;code&gt;:marks&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;How to install plugin&lt;/h2&gt;
&lt;p&gt;Usually with Vundle add this to your vimrc file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Plugin &lt;span class="s1"&gt;'kshenoy/vim-signature'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Between those vim-config lines:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;call vundle#begin&lt;span class="o"&gt;()&lt;/span&gt;

call vundle#end&lt;span class="o"&gt;()&lt;/span&gt;            &lt;span class="s2"&gt;" required&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you need to install your plugin with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;vim +InstallPlugin +qall
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And re-bash to new shell with installed vim-plugin.&lt;/p&gt;
&lt;h2&gt;Using Markings and Vim-Signature plugin&lt;/h2&gt;
&lt;p&gt;Vim Signature will display all markings at the left side.&lt;/p&gt;
&lt;p&gt;To use markings you should follow &lt;a href="http://vim.wikia.com/wiki/Using_marks"&gt;this awesome guide&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Making new mark: Press &lt;code&gt;m&lt;/code&gt; and some letter like &lt;code&gt;a&lt;/code&gt; so : press: &lt;code&gt;ma&lt;/code&gt; on the line that you want to place an &lt;code&gt;a&lt;/code&gt; marking.&lt;/li&gt;
&lt;li&gt;Jumping to the &lt;code&gt;a&lt;/code&gt; mark with keys: &lt;code&gt;\&lt;/code&gt;a`&lt;/li&gt;
&lt;li&gt;Listing all markings with vim-command: &lt;code&gt;:marks&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href="using-markings-and-vim-signature-plugin.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Posting here some of the marking command combinations from &lt;a href="http://vim.wikia.com/wiki/Using_marks"&gt;Vim.Wikia.com&lt;/a&gt; as a reference:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Command         Description
ma              set mark a at current cursor location
'a              jump to line of mark a (first non-blank character in line)
`a              jump to position (line and column) of mark a
d'a             delete from current line to line of mark a
d`a             delete from current cursor position to position of mark a
c'a             change text from current line to line of mark a
y`a             yank text to unnamed buffer from cursor to position of mark a
:marks          list all the current marks
:marks aB       list marks a, B



]'              jump to next line with a lowercase mark
['              jump to previous line with a lowercase mark
]`              jump to next lowercase mark
[`              jump to previous lowercase mark

The above commands take a count. For example, 5]` jumps to the fifth mark after the cursor. 

Command         Description
`.              jump to position where last change occurred in current buffer
`"              jump to position where last exited current buffer
`0              jump to position in last file edited (when exited Vim)
`1              like `0 but the previous file (also `2 etc)
''              jump back (to line in current buffer where jumped from)
``              jump back (to position in current buffer where jumped from)
`[ or `]        jump to beginning/end of previously changed or yanked text
`&amp;lt; or `&amp;gt;        jump to beginning/end of last visual selection 


:delmarks a     delete mark a
:delmarks a-d   delete marks a, b, c, d
:delmarks abxy  delete marks a, b, x, y
:delmarks aA    delete marks a, A
:delmarks!      delete all lowercase marks for the current buffer (a-z) 
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="using-markings-and-vim-signature-plugin.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="using-markings-and-vim-signature-plugin.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kshenoy/vim-signature"&gt;GitHub - kshenoy/vim-signature: Plugin to toggle, display and navigate marks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://vim.wikia.com/wiki/Using_marks"&gt;Using marks | Vim Tips Wiki | FANDOM powered by Wikia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't - up to you.&lt;/p&gt;
&lt;p&gt;Any suggestions what I should blog about? Post me a comment in the box below or poke me at &lt;a href="https://twitter.com/anselmos88"&gt;Twitter: @anselmos88&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="vim"></category><category term="vim-plugin"></category><category term="vim-signature"></category><category term="vim-marks"></category></entry><entry><title>How to remove old Git branches</title><link href="http://witkowskibartosz.com/blog/how-to-remove-old-git-branches.html" rel="alternate"></link><published>2018-03-15T20:30:00+01:00</published><updated>2018-03-15T20:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-15:/blog/how-to-remove-old-git-branches.html</id><summary type="html">&lt;p&gt;It's third time in this week when I need to remove stale remote branch so I decided to make a quick article about it - check out how to remove old git branches.&lt;/p&gt;</summary><content type="html">&lt;p&gt;It's common to need to remove old git branches. It's almost a day to day task that the most of developers do.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="how-to-remove-old-git-branches.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Before you start removing your branches you should checkout to master with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git checkout origin/master
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Removing a local branch&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git branch -D name-of-branch
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Removing a branch on remote&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;BEAWARE&lt;/strong&gt; This will make a request to git server to remove branch on remote! &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git push origin :name-of-branch-to-remove-on-git-server
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Removing local branches stale on remote&lt;/h2&gt;
&lt;h3&gt;With fetching&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git fetch -p
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Only removing&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git remote origin prune
&lt;/pre&gt;&lt;/div&gt;


&lt;div id="snippets"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="how-to-remove-old-git-branches.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git fetch -p
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git remote origin prune
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;BONUS&lt;/h1&gt;
&lt;p&gt;After some digging I've found there is a better git-command that can be used to prune  - and it's &lt;code&gt;git-prune&lt;/code&gt; - unfortunatelly it's available from &lt;code&gt;2.16.0&lt;/code&gt; version, and as I've found out with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git --version
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I was using a &lt;code&gt;1.9.1&lt;/code&gt; version :/ &lt;/p&gt;
&lt;p&gt;Let's change that:&lt;/p&gt;
&lt;h2&gt;Update git to latest version&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo add-apt-repository -y ppa:git-core/ppa
sudo apt-get update
sudo apt-get install -y git
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now for Ubuntu 14.04 I have a &lt;code&gt;2.16.2&lt;/code&gt; version.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="how-to-remove-old-git-branches.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="how-to-remove-old-git-branches.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/"&gt;Git Housekeeping Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://unix.stackexchange.com/questions/33617/how-can-i-update-to-a-newer-version-of-git-using-apt-get"&gt;How can I update to a newer version of git using apt-get&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/docs/git-prune"&gt;Git-Prune git-command reference &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://launchpad.net/~git-core/+archive/ubuntu/ppa"&gt;Git stable releases on Ubuntu PPA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! 
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;</content><category term="git"></category><category term="git-branches"></category><category term="git-prune"></category><category term="git-origin"></category></entry><entry><title>Selenium Firefox profile for Automation</title><link href="http://witkowskibartosz.com/blog/selenium-firefox-profile-for-automation.html" rel="alternate"></link><published>2018-03-14T18:30:00+01:00</published><updated>2018-03-14T18:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-14:/blog/selenium-firefox-profile-for-automation.html</id><summary type="html">&lt;p&gt;Selenium with Firefox can be a great tool to make some automations. To make them even better let's find out how to use firefox profile!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Did you know that you can actually use Firefox Profile in your Selenium automation? It's even quite simple as you will figure out in this article.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="selenium-firefox-profile-for-automation.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Creating a new Firefox Profile&lt;/h2&gt;
&lt;p&gt;Some command lines for firefox are described at &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options"&gt;this link&lt;/a&gt;, but not all of them are available at linux. I checked available commands with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;firefox --help
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To create your profile:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;firefox -P newprofile
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It will popup with a ProfileManager that is not available at normal Firefox run. You can create in this window new profile.&lt;/p&gt;
&lt;p&gt;I did so and It displayed a window with path to profile (which btw you can change) - it looks similar to this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;~/.mozilla/firefox/YOURUNIQUENAME.NAMEYOUENTERED
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You cannot copy this path while creating profile, but when you go to path with profiles:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;~/.mozilla/firefox/
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You should see it.&lt;/p&gt;
&lt;p&gt;We can do some changes on our profile with starting the same command &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;firefox -P newprofile
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;then clicking on "Start Firefox" while selecting profile that we want.&lt;/p&gt;
&lt;h2&gt;Starting Selenium with firefox profile:&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="n"&gt;profile_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/home/anselmos/.mozilla/firefox/your_profile_path_directory_enter_here&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirefoxProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Firefox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;From now you can use a working profiled Selenium Firefox.&lt;/p&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="selenium-firefox-profile-for-automation.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="n"&gt;profile_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/home/anselmos/.mozilla/firefox/your_profile_path_directory_enter_here&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirefoxProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Firefox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="selenium-firefox-profile-for-automation.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="selenium-firefox-profile-for-automation.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options"&gt;Mozilla Developer Command line options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/15954682/setting-selenium-to-use-custom-profile-but-it-keeps-opening-with-default"&gt;python -Setting selenium to use custom profile, but it keeps opening with default&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! 
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;</content><category term="python"></category><category term="selenium"></category><category term="automation"></category><category term="firefox-profile"></category><category term="firefox"></category></entry><entry><title>Automation for Procrastination</title><link href="http://witkowskibartosz.com/blog/automation_for_procrastination.html" rel="alternate"></link><published>2018-03-13T21:05:00+01:00</published><updated>2018-03-13T21:05:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-13:/blog/automation_for_procrastination.html</id><summary type="html">&lt;p&gt;How automation can help us win with procrastination? Let's find out how selenium and some web-apps can help us.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="InvisibleBread-Procrastinator" src="images/invisiblebread_procrastinator.png"&gt;&lt;/p&gt;
&lt;p&gt;Today at 6 am I've found out that I'm procrastinating for about 1 hour. When I realized that I decided to stop and check my &lt;a href="https://nozbe.com/?a=anselmos"&gt;Nozbe account&lt;/a&gt; with tasks that I could use for blog-topic. You know based on the article name what topic I've found.&lt;/p&gt;
&lt;p&gt;You may ask - how you want to use automation in fight with procrastination?&lt;/p&gt;
&lt;p&gt;I've found out that using &lt;a href="https://en.wikipedia.org/wiki/Pomodoro_Technique"&gt;Pomodoro Technique&lt;/a&gt; and special for each of us music gives me more focus than I could ever thought. That's why I'm going to make an automation that will start both of this elements at my browser to get more focused right-away.&lt;/p&gt;
&lt;p&gt;I'll use one of the Pomodoro Technique timers and Spotify playlist to play music.&lt;/p&gt;
&lt;p&gt;Without further ado, check out this selenium automation I will create!&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="automation_for_procrastination.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Selenium for Spotify web-player.&lt;/h2&gt;
&lt;p&gt;First you need to have a spotify playlist that you personally like to listen to get more focused. I have some of my preferred playlists, one of them is &lt;a href="https://open.spotify.com/album/56QpDqnTzXqMn3Jjxv73lz"&gt;Blue Stahli- Antisleep vol1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let's create an automation which for now will open this link :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;page_objects&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PageObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.common.by&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;By&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.support.ui&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;WebDriverWait&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.support&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;expected_conditions&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;EC&lt;/span&gt;

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

    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Spotify Playlist Page for Selenium Page Object Pattern&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;album_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://open.spotify.com/album/&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;playlist_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://open.spotify.com/playlist/&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;login_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://spotify.com/login/&amp;quot;&lt;/span&gt;

    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;input[id=&amp;quot;login-username&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;input[id=&amp;quot;login-password&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;login_btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;button[id=&amp;quot;g-recaptcha-button&amp;quot;]&amp;#39;&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;open_playlist&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;playlist_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;playlist_uri&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;playlist_id&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;open_album&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;album_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;album_uri&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;album_id&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;login&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;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login_uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login_btn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Using it with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Firefox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;spotify_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SpotifyPlaylist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;heregoesyourusername&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;heregoesyourpassword&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;spotify_page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;spotify_page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open_album&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;56QpDqnTzXqMn3Jjxv73lz&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It will automatically login and go to album.&lt;/p&gt;
&lt;p&gt;Taking into accunt that Spotify is not DRM Free, it needs to have &lt;code&gt;Play DRM&lt;/code&gt; settings.&lt;/p&gt;
&lt;p&gt;We will cover this in tomorrow topic how to do that because solution is not simplest as it seems.&lt;/p&gt;
&lt;p&gt;For now lets move to our second page that we need to make less Procrastination.&lt;/p&gt;
&lt;h2&gt;Pomodoro APP&lt;/h2&gt;
&lt;p&gt;I have found that using some pomodoro-technique timer makes me a lot more productive. Let's make a script that will automatically start a pomodoro timer - because that's what I'm currently doing manually.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;page_objects&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PageObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.common.by&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;By&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.support.ui&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;WebDriverWait&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.support&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;expected_conditions&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;EC&lt;/span&gt;

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

    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Spotify Playlist Page for Selenium Page Object Pattern&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;main_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://tomato-timer.com/&amp;quot;&lt;/span&gt;

    &lt;span class="n"&gt;timer_start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;button[id=&amp;quot;timer_start&amp;quot;]&amp;#39;&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;start_pomodoro&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main_uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timer_start&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now we need to mix them together. Unfortunatelly I've found that making a new tab in browser has some strange issues. To overcome it you can use a javascript code.&lt;/p&gt;
&lt;p&gt;The script looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;window.open(&amp;quot;https://google.com/&amp;quot;, &amp;quot;_blank&amp;quot;);&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The final script is available at &lt;a href="https://github.com/anselmos/day_to_day_automation/tree/master/procrastination/pomodoro_spotify"&gt;Day-to-Day Automation github repo directory&lt;/a&gt;&lt;/p&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="automation_for_procrastination.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Script for creating new tab at firefox selenium driver:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;window.open(&amp;quot;https://google.com/&amp;quot;, &amp;quot;_blank&amp;quot;);&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="automation_for_procrastination.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="automation_for_procrastination.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/lrhache/7686903"&gt;Python Selenium Open new tab/focus tab/close tab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/44369565/enabled-play-drm-using-selenium-in-pythonhttps://stackoverflow.com/questions/44369565/enabled-play-drm-using-selenium-in-python"&gt;Enabled 'Play DRM' using selenium in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://selenium-python.readthedocs.io/waits.html"&gt;Selenium Waits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.mozilla.org/en-US/kb/profile-manager-create-and-remove-firefox-profiles"&gt;Firefox Profile manager &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="selenium"></category><category term="automation"></category><category term="pomodoro"></category><category term="focus-music"></category><category term="day-to-day-automation"></category></entry><entry><title>Python decorators vs inheritance</title><link href="http://witkowskibartosz.com/blog/python_decorators_vs_inheritance.html" rel="alternate"></link><published>2018-03-12T05:40:00+01:00</published><updated>2018-03-12T05:40:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-12:/blog/python_decorators_vs_inheritance.html</id><summary type="html">&lt;p&gt;Python decorators can have a lot of similarities with class-inheritance. Check out my review on this topic.&lt;/p&gt;</summary><content type="html">&lt;p&gt;In previous article &lt;a href="python_class_based_decorator_for_classes.html"&gt;about class-based decorators for classes&lt;/a&gt; I gave you example how one can create decorator.&lt;/p&gt;
&lt;p&gt;Those decorators have similarities to inheritance between classes.&lt;/p&gt;
&lt;p&gt;I will review pros and cons for class-inheritance and decorator(function/class based).&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="python_decorators_vs_inheritance.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Decorator example:&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;timeit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;default_timer&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimingDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;klas&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;klas&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org_calculation1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calculation1&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calculation1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calculation1&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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;arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__call__&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;calculation1&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="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org_calculation1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&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;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&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="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@TimingDecorator&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClassTest&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;calculation1&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;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&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;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;
        &lt;span class="c1"&gt;# i&amp;#39;m adding a sleep - as a test case if counter works.&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;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&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;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFancyClassTest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calculation1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;215&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;you can make an extension for class-methods without inheritance&lt;/li&gt;
&lt;li&gt;you could mix inheritance with decorators&lt;/li&gt;
&lt;li&gt;you still have the same class-object.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;all methods needs to be initialized and re-assigned at init&lt;/li&gt;
&lt;li&gt;for each method you need to create another method in decorator (not flexible enough)&lt;/li&gt;
&lt;li&gt;decorator is limited to this class methods - can not be reused at different class with different methods.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Function decorator example:&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;counter_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_name&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;wrapper&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;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;output_of_function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_name&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;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&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="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&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;output_of_function&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClassTest&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

    &lt;span class="nd"&gt;@counter_print&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculation1&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;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&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;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;
        &lt;span class="c1"&gt;# i&amp;#39;m adding a sleep - as a test case if counter works.&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;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&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;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFancyClassTest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calculation1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;215&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;you still have the same class-object&lt;/li&gt;
&lt;li&gt;you could can mix inheritance with decorators&lt;/li&gt;
&lt;li&gt;you don't need to re-create assignment for predefined class-methods&lt;/li&gt;
&lt;li&gt;your decorator is not limited to only this specific class. It is re-usable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Not advice to use this solution if you have a lot of code to make. It can get messy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Inheritance example&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClassTest&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;calculation1&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;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&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;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;
        &lt;span class="c1"&gt;# i&amp;#39;m adding a sleep - as a test case if counter works.&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;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&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;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimerMyFancyClassTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyFancyClassTest&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;calculation1&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="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calculation1&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;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&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="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&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;output&lt;/span&gt;



&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimerMyFancyClassTest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calculation1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;215&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;your extended class does the same as decorator (prints timing for method)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You need to create code that extends main code&lt;/li&gt;
&lt;li&gt;It is not re-usable/adoptable to other class-methods&lt;/li&gt;
&lt;li&gt;you endup with different object and comparison is a bit more complex&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;MIX (inheritance at decorators class)&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;timeit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;default_timer&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MetaClassDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; A meta class decorator that forces creating methods from decorator-appended class.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;klas&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;klas&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;klass_method&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_klas_methods&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;self.org_&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;klass_method&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; = self.klas.&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;klass_method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;self.klas.&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;klass_method&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; = self.&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;klass_method&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;get_klas_methods&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot; based on https://stackoverflow.com/a/34452 &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;all_methods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;method_name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;method_name&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;!=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__&amp;quot;&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;all_methods&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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;arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FancyTestDecor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MetaClassDecorator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; This decorator forces 2 methods - fancy_method and test1 &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fancy_method&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="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org_fancy_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&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;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&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="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&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;test1&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="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org_test1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&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;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&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="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@FancyTestDecor&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClassTest&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;fancy_method&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fancy print from fancy method&amp;quot;&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;test1&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Ttest11&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFancyClassTest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fancy_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;you re-use pre-existing architecture for decorator.&lt;/li&gt;
&lt;li&gt;you create only class with methods (reusing meta-decorator-class)&lt;/li&gt;
&lt;li&gt;you can create a more complex solutions as decorators for classes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;All methods from &lt;code&gt;MyFancyClassTest&lt;/code&gt; if any found, needs to be added and re-assigned to fields, because of &lt;code&gt;exec&lt;/code&gt; for all methods that does not start with "__" &lt;a href="https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references"&gt;private functions/methods - check docs for 2.7 python.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;You create a non-reusable code just as in class-based decorator (unless you find other class that will have only those methods) (unless you find solution to replace the &lt;code&gt;exec&lt;/code&gt; problem and re-assign methods without manually changing them at &lt;code&gt;__init__&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="python_decorators_vs_inheritance.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MetaClassDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; A meta class decorator that forces creating methods from decorator-appended class.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;klas&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;klas&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;klass_method&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_klas_methods&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;self.org_&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;klass_method&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; = self.klas.&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;klass_method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;self.klas.&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;klass_method&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; = self.&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;klass_method&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;get_klas_methods&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot; based on https://stackoverflow.com/a/34452 &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;all_methods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;method_name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;method_name&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;!=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__&amp;quot;&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;all_methods&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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;arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FancyTestDecor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MetaClassDecorator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; This decorator counts timing of fancy_method method &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fancy_method&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="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org_fancy_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&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;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timer&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="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="python_decorators_vs_inheritance.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="python_decorators_vs_inheritance.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/29336616/eval-scope-in-python-2-vs-3"&gt;Eval scope in python2 vs python3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/functions.html#eval"&gt;Build-in Functions - python 3.6.4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/34439/finding-what-methods-a-python-object-has"&gt;Introspection - Finding what methods a Python object has&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/2/library/timeit.html"&gt;TimeIt - Measure execution time of small code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/7370801/measure-time-elapsed-in-python"&gt;performance - Measure time elapsed in Python?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="decorator"></category><category term="class-decorator"></category><category term="class-based-decorator"></category></entry><entry><title>Python class based decorator for classes</title><link href="http://witkowskibartosz.com/blog/python_class_based_decorator_for_classes.html" rel="alternate"></link><published>2018-03-11T10:45:00+01:00</published><updated>2018-03-11T10:45:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-11:/blog/python_class_based_decorator_for_classes.html</id><summary type="html">&lt;p&gt;Python decorators for classes can be class-based. Check out how to create one!&lt;/p&gt;</summary><content type="html">&lt;p&gt;As I've shown you in &lt;a href="/python_decorators_with_parameters.html"&gt;previous episode about parameterizing decorators&lt;/a&gt; you can create a class-based decorator.&lt;/p&gt;
&lt;p&gt;This time let's create a derivation class-based decorator that is intended for classes.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="python_class_based_decorator_for_classes.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;First, we create our class that will use decorator.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClassTest&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;fancy_method&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fancy print from fancy method&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The decorator itself with class:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DecoratorForClasses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;klas&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;klas&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org_fancy_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fancy_method&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fancy_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fancy_method&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;init&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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;arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&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="s2"&gt;&amp;quot;call&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__call__&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;fancy_method&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;before pancy method (at decorator)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org_fancy_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&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="s2"&gt;&amp;quot;after pancy method (at decorator)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@DecoratorForClasses&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClassTest&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;fancy_method&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fancy print from fancy method&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFancyClassTest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fancy_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;After analizing this, I see a lot of similarities with python-inherintance in it.&lt;/p&gt;
&lt;p&gt;Yet since decorator does not have any other inheritance, but instead can "extend" capabilities of classes, it is still useful.&lt;/p&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="python_class_based_decorator_for_classes.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DecoratorForClasses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;klas&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;klas&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org_method1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method1&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method1&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method1&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;method1_decorator&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org_method1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;klas&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;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;


&lt;span class="nd"&gt;@DecoratorForClasses&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClassTest&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;method1&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fancy print from fancy method&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFancyClassTest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-Promotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="python_class_based_decorator_for_classes.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="python_class_based_decorator_for_classes.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://python-3-patterns-idioms-test.readthedocs.io/en/latest/PythonDecorators.html"&gt;Decorators - Python3 Patterns, Recipes and idioms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.phyast.pitt.edu/~micheles/python/documentation.html#class-decorators-and-decorator-factories-deprecated"&gt;The decorator module (old version)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.python.org/moin/PythonDecoratorLibrary#Class_method_decorator_using_instance"&gt;Python Decorator Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@vadimpushtaev/decorator-inside-python-class-1e74d23107f6"&gt;Decorator inside Python class - Vadim Pushtaev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/11731136/python-class-method-decorator-with-self-arguments"&gt;Python class method decorator with self arguments?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.codementor.io/sheena/advanced-use-python-decorators-class-function-du107nxsv"&gt;Advanced Uses of Python Decorators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="decorator"></category><category term="class-decorator"></category><category term="class-based-decorator"></category></entry><entry><title>Python decorators with parameters</title><link href="http://witkowskibartosz.com/blog/python_decorators_with_parameters.html" rel="alternate"></link><published>2018-03-10T16:30:00+01:00</published><updated>2018-03-10T16:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-10:/blog/python_decorators_with_parameters.html</id><summary type="html">&lt;p&gt;You can create a python decorator with parameters. Check out my short review on that.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Python Decorators have the ability to be parameterized.&lt;/p&gt;
&lt;p&gt;The main reason is to have more ability to change some behaviour of &lt;a href="python_decorators_for_function.html"&gt;function&lt;/a&gt;/&lt;a href="python_decorators_for_classes.html"&gt;class&lt;/a&gt; in a more elegant &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY&lt;/a&gt; way.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="python_decorators_with_parameters.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;You can create your own decorator that will be a class. &lt;/p&gt;
&lt;p&gt;This time we will use that, to make our code a bit more simplier and readable.&lt;/p&gt;
&lt;p&gt;This example is a more/less based on this &lt;a href="https://stackoverflow.com/a/5929178"&gt;stackoverflow answer&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BeforeAfterDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;before_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;after_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;which_return&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;before_func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;before_func&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after_func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;after_func&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;which_return&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;which_return&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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;original_func&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;wrappee&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;output_before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;before_func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;original_func&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;output_after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after_func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;which_return&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&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;output_before&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;which_return&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&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;output_after&lt;/span&gt;
            &lt;span class="k"&gt;else&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;output&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrappee&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;before_function&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="s2"&gt;&amp;quot;this is a more complex function that will be invoked before function&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;before&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;after_function&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="s2"&gt;&amp;quot;this is a more complex function that will be invoked after function&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;after&amp;quot;&lt;/span&gt;

&lt;span class="nd"&gt;@BeforeAfterDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;before_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;after_function&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_all_return_before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&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="s1"&gt;&amp;#39;in bar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;method&amp;quot;&lt;/span&gt;

&lt;span class="nd"&gt;@BeforeAfterDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;before_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;after_function&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_all_return_after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&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="s1"&gt;&amp;#39;in bar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;method&amp;quot;&lt;/span&gt;

&lt;span class="nd"&gt;@BeforeAfterDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;before_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;after_function&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;make_all_return_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&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="s1"&gt;&amp;#39;in bar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;method&amp;quot;&lt;/span&gt;


&lt;span class="n"&gt;first_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_all_return_before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;z&amp;#39;&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="s2"&gt;&amp;quot;function ended with return: &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;second_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_all_return_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;z&amp;#39;&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="s2"&gt;&amp;quot;function ended with return: &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second_output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;third_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_all_return_after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;z&amp;#39;&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="s2"&gt;&amp;quot;function ended with return: &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;third_output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As you can see in script above, this decorator (&lt;code&gt;BeforeAfterDecorator&lt;/code&gt;) has ability to take other functions that will be invoked before decorated function and after.
Also it has third parameter that decides which output will be taken.&lt;/p&gt;
&lt;p&gt;Where you could use that?&lt;/p&gt;
&lt;p&gt;For example at the &lt;a href="http://www.fabfile.org/"&gt;Fabric&lt;/a&gt; which can be used for deployment process. Check out my posts about &lt;a href="tag/fabric.html"&gt;using fabric&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the &lt;a href="https://stackoverflow.com/a/26151604"&gt;stackoverflow answer&lt;/a&gt; you can find alternative solution to make meta-decorator that uses triple-nest function. I suggest you to check it.&lt;/p&gt;
&lt;p&gt;This decorator looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parametrized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dec&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;layer&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;repl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&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;dec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&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;return&lt;/span&gt; &lt;span class="n"&gt;repl&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;layer&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;div id="snippets"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="python_decorators_with_parameters.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ParameterizedDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;your_decorator_parameter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;your_decorator_parameter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;your_decorator_parameter&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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;original_func&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;wrappee&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;your_decorator_parameter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;original_func&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;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrappee&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Autopromotion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="python_decorators_with_parameters.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="python_decorators_with_parameters.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Related links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/5929107/decorators-with-parameters"&gt;StackOverFlow - python - Decorators with Parameters?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.artima.com/weblogs/viewpost.jsp?thread=240808#function-decorators"&gt;Decorators I: Introduction to python decorators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="decorator"></category><category term="decorators-with-parameters"></category><category term="decorator-class-based"></category></entry><entry><title>Python decorators for Classes</title><link href="http://witkowskibartosz.com/blog/python_decorators_for_classes.html" rel="alternate"></link><published>2018-03-09T07:55:00+01:00</published><updated>2018-03-09T07:55:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-09:/blog/python_decorators_for_classes.html</id><summary type="html">&lt;p&gt;Classes in Python can have their own decorators. Check out how to make own!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Classes in Python can be extended by inheritance. In Python 3 ability to make a class-decorator was added per &lt;a href="https://www.python.org/dev/peps/pep-3129/"&gt;PEP request&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Check out that you can make a type of inheritance from decorator to add something to method &lt;a href="https://github.com/agiliq/Django-parsley/blob/master/parsley/decorators.py"&gt;like in this example&lt;/a&gt;&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="python_decorators_for_classes.html#tothepoint"&gt; To The Point &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;How to make your own class decorator? First you need a class definition so let's create one :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You were calling sir?!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now we can create our class decorator:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fancy_class_decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;old_init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_init&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="n"&gt;old_init&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;here goes your additional code to init!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_init&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And using decorator :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nd"&gt;@fancy_class_decorator&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You were calling sir?!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;While I was researching topic I've found that making a class-only fields that are not initialized within constructor can lead to a bad results.&lt;/p&gt;
&lt;p&gt;Check out this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fancy_class_decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;old_init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_init&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onevar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fancy_decorator_before&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fancy_decorator_before&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;old_init&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onevar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fancy_decorator_after&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fancy_decorator_after&amp;quot;&lt;/span&gt;

    &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_init&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;

&lt;span class="nd"&gt;@fancy_class_decorator&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;onevar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;onevar&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onevar&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="s2"&gt;&amp;quot;before&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;before&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="s2"&gt;&amp;quot;after&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And then This:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fancy_class_decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;old_init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_init&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onevar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fancy_decorator_before&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fancy_decorator_before&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;old_init&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onevar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fancy_decorator_after&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fancy_decorator_after&amp;quot;&lt;/span&gt;

    &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_init&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;

&lt;span class="nd"&gt;@fancy_class_decorator&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onevar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;onevar&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onevar&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="s2"&gt;&amp;quot;before&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;before&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="s2"&gt;&amp;quot;after&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fancy_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fancy_object&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;First example presents situation where you create a class-based fields which are not initialized within constructor of class.&lt;/p&gt;
&lt;p&gt;Because we are making a decorator-inheritance over constructor, it automatically changes fields data.&lt;/p&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;

&lt;h1&gt;&lt;a href="python_decorators_for_classes.html#snippets"&gt; Snippets &lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Replace &lt;code&gt;old_method&lt;/code&gt; with method you want to make decorator-inheritance on.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;class_decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;old_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_method&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="n"&gt;old_method&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="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;old_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_method&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Auto-promotion:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="python_decorators_for_classes.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="python_decorators_for_classes.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Found related to post:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.python.org/dev/peps/pep-3129/"&gt;PEP 3129 - Class decorators &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.python.org/dev/peps/pep-0318"&gt;PEP 318 - Decorators for functions and methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/python/peps"&gt;PEPs Github Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://krzysztofzuraw.com/blog/2016/python-class-decorators.html"&gt;Krzysztof Żuraw Blog about Python class decorators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jfine-python-classes.readthedocs.io/en/latest/decorators.html"&gt;Jonathan Fine tutorial on decorators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/681953/python-class-decorator"&gt;Python class decorator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/agiliq/Django-parsley/blob/master/parsley/decorators.py#L105"&gt;Django-parsley decorators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Not related, but also time-worth:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Pilcrow"&gt;Pilcrow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="decorator"></category><category term="class-decorator"></category></entry><entry><title>Python decorators for function</title><link href="http://witkowskibartosz.com/blog/python_decorators_for_function.html" rel="alternate"></link><published>2018-03-08T08:15:00+01:00</published><updated>2018-03-08T08:15:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-08:/blog/python_decorators_for_function.html</id><summary type="html">&lt;p&gt;What are python decorators? How can you create your own function decorator? Check out!&lt;/p&gt;</summary><content type="html">&lt;script src="scripts/asciinema-player2.js"&gt;&lt;/script&gt;

&lt;p&gt;What are python decorators? How can you create your own function decorator? Check out!&lt;/p&gt;
&lt;h1&gt;What are python decorators&lt;/h1&gt;
&lt;p&gt;Python decorators are a wrappers around the function/method/class that can do actions before/after some function/method/class is invoked.&lt;/p&gt;
&lt;p&gt;To make that happen, you re-use function as a parameter. Basically you create a private function that contains other function as a parameter. Sounds like not a trivial thing? Don't be scared, it's pretty simple.&lt;/p&gt;
&lt;p&gt;As a reference think about a profiler that can measure how much time your function took. With wrapper it's easy-peasy.&lt;/p&gt;
&lt;div id="tothepoint"&gt;&lt;/div&gt;

&lt;h1&gt;To The Point&lt;/h1&gt;
&lt;p&gt;To create your first &lt;code&gt;decorator&lt;/code&gt;, first you create a function wrapper:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&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;return&lt;/span&gt; &lt;span class="n"&gt;function_that_you_take_as_argument&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;But wait, what is the &lt;code&gt;function_that_you_take_as_argument&lt;/code&gt; ? It's exactly what it says - a function that is taken with decorator as argument.&lt;/p&gt;
&lt;p&gt;To make a working decorator you also need to make an outer-function around it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_that_you_take_as_argument&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;wrapper&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;return&lt;/span&gt; &lt;span class="n"&gt;function_that_you_take_as_argument&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;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@decorator_name&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;function_that_you_take_as_argument&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="s2"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This decorator does nothing at this time. But if you add output to variable and make statements before and after like that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_that_you_take_as_argument&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;wrapper&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;before:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;function_that_you_take_as_argument&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="s2"&gt;&amp;quot;after:&amp;quot;&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;output&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@decorator_name&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;your_function_this_name_is_different_then_in_wrapper_argument&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="s2"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then your function call with decorator will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;first print &lt;code&gt;before:&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;make function - print &lt;code&gt;test&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;print &lt;code&gt;after&lt;/code&gt; -when function has done it's executement.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="snippets"&gt;&lt;/div&gt;

&lt;h1&gt;Snippets&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_wrapped&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;wrapper&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;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_wrapped&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;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;div id="asciinema"&gt;&lt;/div&gt;

&lt;h1&gt;Asciinema&lt;/h1&gt;
&lt;p&gt;&lt;link rel="stylesheet" type="text/css" href="css/asciinema-player2.css" /&gt;
&lt;asciinema-player src="asciinema/python_decorators_for_function.json"&gt;&lt;/asciinema-player&gt;&lt;/p&gt;
&lt;h2&gt;Example from asciinema&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#! /usr/bin/env python&lt;/span&gt;
&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class="c1"&gt;# vim:fenc=utf-8&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Copyright © 2018 [Anselmos](github.com/anselmos) &amp;lt;anselmos@users.noreply.github.com&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Distributed under terms of the MIT license.&lt;/span&gt;

&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Decorators example&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Here you put your function &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;before invoking function&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;output_of_function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_name&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;after invoking function&amp;quot;&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;output_of_function&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@decorator_name&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;your_function_that_will_use_decorator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;TODO: Docstring for your_function_that_will_use_decorator.&lt;/span&gt;
&lt;span class="sd"&gt;    :returns: TODO&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Test&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;your_function_that_will_use_decorator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;h2&gt;Autopromotion:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="python_decorators_for_function.html#tothepoint"&gt;ToThePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="python_decorators_for_function.html#snippets"&gt;Snippets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="python_decorators_for_function.html#asciinema"&gt;Asciinema&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Found while research of the topic&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lord63/awesome-python-decorator#built-in-python-decorator"&gt;List of Python build-in Decorators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="decorator"></category><category term="function-decorator"></category></entry><entry><title>Pipenv run vs Pipenv shell</title><link href="http://witkowskibartosz.com/blog/pipenv_run_vs_pipenv_shell.html" rel="alternate"></link><published>2018-03-07T07:25:00+01:00</published><updated>2018-03-07T07:25:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-07:/blog/pipenv_run_vs_pipenv_shell.html</id><summary type="html">&lt;p&gt;Pipenv has a run and shell, but which one should I use ? That's the same question I've asked myself yesterday. Check out my brief summary about this!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Pipenv has a run and shell, but which one should I use ? That's the same question I've asked myself yesterday. Check out my brief summary about this!&lt;/p&gt;
&lt;h1&gt;Pipenv shell&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;Pipenv shell&lt;/code&gt;&lt;/em&gt; is used mainly as a &lt;code&gt;run it now, and leave&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It will create an active environemnt almost the same way as with &lt;code&gt;source env/bin/activate&lt;/code&gt;, but it will also do it within a new shell. That way you cannot use previous commands from history.&lt;/p&gt;
&lt;p&gt;There is even a &lt;a href="https://github.com/pypa/pipenv/issues/876"&gt;bug about that&lt;/a&gt; but the conclusion is that it's not pipenv issue, rather &lt;a href="https://github.com/berdario/pew/issues/165"&gt;pew problem with sub-shell&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As it's using a sub-shell, it may not be advised to use it within your deployment/management.&lt;/p&gt;
&lt;p&gt;For example if you want to make a &lt;code&gt;Dockerfile&lt;/code&gt; with Pipenv, you should not use &lt;code&gt;pipenv shell&lt;/code&gt; because it will not be activated for the next &lt;code&gt;RUN&lt;/code&gt; command or any other command that you may put with &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; signs.&lt;/p&gt;
&lt;p&gt;You could use some type of sub-processing but that's far beyond easy and clean - so as using &lt;code&gt;pipenv --venv&lt;/code&gt; that gives you opportunity to reuse underlying virtualenv (by giving you place where is the v-env that you can activate manually).&lt;/p&gt;
&lt;h1&gt;Pipenv run&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;Pipenv run&lt;/code&gt; is the main purpose for running next python commands. It will automatically activate environment for that command and execute anything you will put to it.&lt;/p&gt;
&lt;p&gt;For example to run some specific python file that uses dependency you will:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv run python main.py
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That will activate env and run &lt;code&gt;python main.py&lt;/code&gt; in the env.&lt;/p&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;As posted by Dan Ryan(techalchemy) &lt;a href="https://github.com/pypa/pipenv/issues/944#issuecomment-338360714"&gt;in this issue comment&lt;/a&gt; - you can should use &lt;code&gt;pipenv run&lt;/code&gt; for 'heavy lifting' and &lt;code&gt;pipenv shell&lt;/code&gt; for day-to-day convenience of dev tasks.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/pipenv/issues/944"&gt;Pipenv - Activate a pipenv environment without creating a new shell? #944&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/pipenv/issues/297"&gt;Pipenv - pipenv shell loses history #297&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/pipenv/issues/876"&gt;Pipenv - up/down arrow history doesn't work on pipenv shell on windows #876&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/virtualenv/issues/355"&gt;Virtualenv - site.py not compatible with python 2.7 #355&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/berdario/pew/issues/150"&gt;Pew - Tab completion under pew? #150 &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/berdario/pew/issues/166"&gt;Pew - Arrow keys don't work in pew shell on Windows #166 &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/berdario/pew/issues/165"&gt;Pew - up/down arrow history doesn't work on pipenv shell on windows #165&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="pipenv"></category><category term="pipfile"></category></entry><entry><title>Locking Pipfile with Pipenv</title><link href="http://witkowskibartosz.com/blog/locking-pipfile-with-pipenv.html" rel="alternate"></link><published>2018-03-06T23:08:00+01:00</published><updated>2018-03-06T23:08:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-06:/blog/locking-pipfile-with-pipenv.html</id><summary type="html">&lt;p&gt;Today I've got a problem with pipenv - Locking your Pipfile with pipenv. Check out how easy it is!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I've got a problem with pipenv - Locking your Pipfile with pipenv. Check out how easy it is!&lt;/p&gt;
&lt;p&gt;In the &lt;a href="how-to-use-pipenv.html"&gt;previous article about pipfile&lt;/a&gt; I've presented some key commands how to use this powerful yet effortless python management tool.&lt;/p&gt;
&lt;p&gt;This time let's dive a bit further!&lt;/p&gt;
&lt;h1&gt;The case with problem.&lt;/h1&gt;
&lt;p&gt;Pipenv is a great tool, but in some cases it may fail in one or another way.&lt;/p&gt;
&lt;p&gt;Today I had a bit of failure of this tool. But it was not pipenv fault. It was a more Pip and System dependencies problem.&lt;/p&gt;
&lt;p&gt;To the point - I installed psycopg2 with Pipenv but forgot that it needs postgres-dev package at the system. It failed.&lt;/p&gt;
&lt;p&gt;While it failed, Pipenv made a call and did not create Pipfile.lock - a lock file.&lt;/p&gt;
&lt;p&gt;So immediatelly after I've realized what just happend, I've created a &lt;a href="https://hub.docker.com/r/anselmos/pipenv/tags/"&gt;docker image&lt;/a&gt; ( Ha!) with a pipenv(1.0) and postgresql system dependency(2.0).&lt;/p&gt;
&lt;p&gt;Then I've found that I could easily make it with &lt;code&gt;pipenv lock&lt;/code&gt; which was incredible.&lt;/p&gt;
&lt;h1&gt;Pipenv locking&lt;/h1&gt;
&lt;p&gt;Pipfile.lock will be generated whenever you make :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pipenv install --dev&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pipenv install [package-name]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pipenv uninstall [package-name]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One of the times when your Pipfile.lock may not be updated is - when the Pipfile has been changed, i.e. when you made some git - merging process and changed versions of packages in Pipfile.&lt;/p&gt;
&lt;p&gt;Then you may need to refresh your Pipfile.lock because that changes are not reflected in &lt;code&gt;Pipfile.lock&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To do that you will use &lt;code&gt;pipenv lock&lt;/code&gt; - isn't it easy ?.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hub.docker.com/r/anselmos/pipenv"&gt;Anselmos/Pipenv docker image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/pipenv"&gt;Pipenv github repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="python"></category><category term="pipenv"></category><category term="pipfile"></category></entry><entry><title>Your coding timer with Wakatime</title><link href="http://witkowskibartosz.com/blog/your-coding-timer-with-wakatime.html" rel="alternate"></link><published>2018-03-05T19:07:00+01:00</published><updated>2018-03-05T19:07:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-05:/blog/your-coding-timer-with-wakatime.html</id><summary type="html">&lt;p&gt;Have you ever wonder how much time you spend on your IDE and focused work like programming/writing code? Today I'm going to check if wakatime is solution to find that!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Have you ever wonder how much time you spend on your IDE and focused work like programming/writing code? Today I'm going to check if wakatime is solution to find that!&lt;/p&gt;
&lt;h1&gt;Wakatime&lt;/h1&gt;
&lt;p&gt;A &lt;a href="https://wakatime.com"&gt;Wakatime&lt;/a&gt; is a time-management tool. It automates process of gathering how much time you have spend on coding and typing text within your editor.&lt;/p&gt;
&lt;p&gt;Today I've decided finally to check if this is a great tool or not.&lt;/p&gt;
&lt;h1&gt;Plugins&lt;/h1&gt;
&lt;p&gt;This time management tool has a &lt;a href="https://wakatime.com/editors"&gt;list of editor integrations&lt;/a&gt; that works.&lt;/p&gt;
&lt;p&gt;That's why I've decided to use it - because in that list there are two tools without which I don't see my programmers day - 
&lt;a href="https://wakatime.com/vim"&gt;vim&lt;/a&gt; and &lt;a href="https://wakatime.com/pycharm"&gt;pycharm&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let's check out how to integrate them!&lt;/p&gt;
&lt;h1&gt;Creating your account on Wakatime.&lt;/h1&gt;
&lt;p&gt;First you need to create your account on Wakatime. It will be needed for having API-KEY pasted into config.&lt;/p&gt;
&lt;h1&gt;Vim plugin&lt;/h1&gt;
&lt;p&gt;As usually you will use Vundle to install plugin.&lt;/p&gt;
&lt;p&gt;Add this to your .vimrc file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Plugin &lt;span class="s1"&gt;&amp;#39;wakatime/vim-wakatime&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;vim +PluginInstall +qall
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Plugin should automatically be installed.&lt;/p&gt;
&lt;p&gt;After installation and re-accessing your shell and vim, you should be asked for API-KEY. Paste the one you have been granted at &lt;a href="https://wakatime.com/settings/api-key"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This key will be saved in your config file at :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;~/.wakatime.cfg
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Pycharm Plugin&lt;/h1&gt;
&lt;p&gt;In Pycharm, as usually, go to Settings and Plugins, find plugin via "Browse Repositories" and install.&lt;/p&gt;
&lt;p&gt;After installation, you should restart your Pycharm, if you are not asked for API-KEY - no worries.&lt;/p&gt;
&lt;p&gt;You can change it at 'Tools' -&amp;gt; 'WakaTime Settings' and "API Key".&lt;/p&gt;
&lt;p&gt;Copy the key from &lt;code&gt;~/.wakatime.cfg&lt;/code&gt; file and you should be ready to go.&lt;/p&gt;
&lt;h1&gt;Statistics!&lt;/h1&gt;
&lt;p&gt;After a while of coding I've found that it gathers huge amount of data which then is presented to user at &lt;a href="images/waka_time_dashboard.png"&gt;Dashboard which you can check at this image&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are also a &lt;a href="https://wakatime.com/leaders"&gt;"LeaderBoards"&lt;/a&gt; where you can start a competition to code a bit more.&lt;/p&gt;
&lt;h1&gt;Excluding files&lt;/h1&gt;
&lt;p&gt;What if i don't want to have some files/project to be visible at Waka? &lt;/p&gt;
&lt;p&gt;Check out how to setup it with config file &lt;a href="https://wakatime.com/faq#exclude-paths"&gt;at faq&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wakatime.com"&gt;WakaTime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wakatime.com/editors/"&gt;WakaTime Editors Supported&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wakatime.com/developers"&gt;WakaTime API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you in the next episode! Cheers! &lt;/p&gt;</content><category term="wakatime"></category><category term="coding-timer"></category></entry><entry><title>Python snippets in Vim with Ultisnips</title><link href="http://witkowskibartosz.com/blog/python_snippets_in_vim_with_ultisnips.html" rel="alternate"></link><published>2018-03-04T18:40:00+01:00</published><updated>2018-03-04T18:40:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-04:/blog/python_snippets_in_vim_with_ultisnips.html</id><summary type="html">&lt;p&gt;Snippets in all type of editors are very usefull beings that every bloger/programmer should start using. Especially if using ViM. Check out Ultisnips solution that supports it!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Snippets in all type of editors are very usefull beings that every bloger/programmer should start using. Especially if using ViM. Check out what solution I've found that supports snippets for vim!&lt;/p&gt;
&lt;p&gt;S0-E30/E30&lt;/p&gt;
&lt;h1&gt;UltiSnips&lt;/h1&gt;
&lt;p&gt;There is a great snippets solution for Vim &lt;a href="https://github.com/SirVer/ultisnips"&gt;UltiSnips created iniatially by Holger Rapp&lt;/a&gt;, that is also recommended by &lt;a href="https://code.djangoproject.com/wiki/UsingVimWithDjango#Ultisnips.vim"&gt;Django Team at Vim Hints&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let's check out what they are all about!&lt;/p&gt;
&lt;h1&gt;Installing UltiSnips&lt;/h1&gt;
&lt;p&gt;First of all, you need to install your UltiSnips.&lt;/p&gt;
&lt;p&gt;As usually I'm recommending &lt;a href="https://github.com/VundleVim/Vundle.vim"&gt;Vundle&lt;/a&gt; that makes installing of vim-plugins much easier.&lt;/p&gt;
&lt;p&gt;Let's do it.
Add this line in your .vimrc file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot; Track the engine.&lt;/span&gt;
&lt;span class="s2"&gt;Plugin &amp;#39;SirVer/ultisnips&amp;#39;&lt;/span&gt;

&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; Snippets are separated from the engine. Add this &lt;span class="k"&gt;if&lt;/span&gt; you want them:
Plugin &lt;span class="s1"&gt;&amp;#39;honza/vim-snippets&amp;#39;&lt;/span&gt;

&lt;span class="s2"&gt;&amp;quot; Trigger configuration. Do not use &amp;lt;tab&amp;gt; if you use https://github.com/Valloric/YouCompleteMe.&lt;/span&gt;
&lt;span class="s2"&gt;let g:UltiSnipsExpandTrigger=&amp;quot;&lt;/span&gt;&amp;lt;tab&amp;gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="s2"&gt;let g:UltiSnipsJumpForwardTrigger=&amp;quot;&lt;/span&gt;&amp;lt;c-j&amp;gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="s2"&gt;let g:UltiSnipsJumpBackwardTrigger=&amp;quot;&lt;/span&gt;&amp;lt;c-k&amp;gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; If you want :UltiSnipsEdit to split your window.
&lt;span class="nb"&gt;let&lt;/span&gt; g:UltiSnipsEditSplit&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;vertical&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now as usually make installation of this plugin with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;vim +PluginInstall +qall
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;UltiSnips Templates&lt;/h1&gt;
&lt;p&gt;When you follow steps above, you will have already predefined templates from &lt;a href="https://github.com/honza/vim-snippets"&gt;&lt;code&gt;honza/vim-snippets&lt;/code&gt; repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can check those templates in your vim-bundle directory at:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;ls -al ~/.vim/bundle/vim-snippets/UltiSnips/
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I personally checked the source code for preexisting &lt;a href="https://github.com/honza/vim-snippets/blob/master/UltiSnips/python.snippets"&gt;python snippet&lt;/a&gt; to know which snippets are available.&lt;/p&gt;
&lt;h1&gt;Using UltiSnips&lt;/h1&gt;
&lt;p&gt;When we copy-pasted changes to vimrc file, there was a "UltiSnipsExpandTrigger", "UltiSnipsJumpForwardTrigger" and "UltiSnipsJumpBackwardTrigger".&lt;/p&gt;
&lt;p&gt;They are in fact a binding to which key-stroke special action should be used. It means, that using in our case a "Tab" after writing name of the snippet i.e. :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;deff&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TAB&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;will make use of preexisting &lt;code&gt;deff&lt;/code&gt; snippet and paste it to our code/text.&lt;/p&gt;
&lt;p&gt;Those snippets have special moving triggers, which applies to move forward/backward within snippet elements to be changed.&lt;/p&gt;
&lt;h1&gt;Where to go now?&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Holdger Rapp (author of UltiSnipps) YT video &lt;a href="https://www.youtube.com/watch?v=Zik6u0klD40&amp;amp;list=PLLAWlWqN1WUOJq8Ba3nLLEaXO6zpqF6Dk"&gt;UltiSnips Playlist&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=Zik6u0klD40"&gt;EP1&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=f_WQxYgK0Pk"&gt;EP2&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=hKrrOevbrxY"&gt;EP3&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=JJQYwt6Diro"&gt;EP4&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;VimCasts Videos - You can also check how to use this UltiSnips with &lt;a href="http://vimcasts.org/episodes/meet-ultisnips/"&gt;videos from vimcasts&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gitter communicator for UltiSnips - a place where community paste they problems and solves them. Check at &lt;a href="https://gitter.im/SirVer/ultisnips"&gt;SirVer/Ultisnips&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I used those videos and it helped me to learn how to use this powerful feature.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/SirVer/ultisnips"&gt;UltiSnips github repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.djangoproject.com/wiki/UsingVimWithDjango"&gt;Using Vim With Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://web.archive.org/web/20090206143136/http://py.vaults.ca/~x/python_and_vim.html"&gt;Notes on using Vim with Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://vimcasts.org/episodes/meet-ultisnips/"&gt;Meet UltiSnips at vimcasts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/19039443/vim-ultisnips-how-do-i-move-to-the-next-placeholder-or-tabstop"&gt;Vim UltiSnips How do i move to the next placeholer or tabstop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;I'd like to address a special thanks for &lt;a href="https://twitter.com/miroburn?lang=en"&gt;#miroburn&lt;/a&gt; for challenging me in making a 30-day blog-posting! It was a great experience!&lt;/p&gt;
&lt;p&gt;See you in the next episode soon! Cheers! &lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="vim"></category><category term="vim-snippets"></category><category term="vim-ultisnips"></category><category term="ultisnips"></category><category term="snippets"></category></entry><entry><title>Vim Templates are a life saver</title><link href="http://witkowskibartosz.com/blog/vim-templates-are-a-life-saver.html" rel="alternate"></link><published>2018-03-03T17:00:00+01:00</published><updated>2018-03-03T17:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-03:/blog/vim-templates-are-a-life-saver.html</id><summary type="html">&lt;p&gt;Today when my 30daychallenge almost finishes (tomorrow is the last day) I feel that I could not make it without reusing previous posts for new posts. Check out how to automate it!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today when my 30daychallenge almost finishes (tomorrow is the last day) I feel that I could not make it without reusing previous posts for new posts. Check out how to automate it!&lt;/p&gt;
&lt;p&gt;S0-E29/E30&lt;/p&gt;
&lt;h1&gt;The problem&lt;/h1&gt;
&lt;p&gt;As you may or may not find - most of my posts are currently made with a ViM editor. &lt;/p&gt;
&lt;p&gt;It can be a bit painful sometimes, especially when it goes with day-to-day blog-posting. So to be able to deliver content I was cheating a little - to be more precise - I used a &lt;a href="https://en.wikipedia.org/wiki/Copy_and_paste_programming"&gt;Copy-and-Paste&lt;/a&gt; method. That means I was making a copy of the previous post and replaced it with current content.&lt;/p&gt;
&lt;p&gt;A fun fact is that this post is also written like that. That's a bit silly, so let's change it, shall we?&lt;/p&gt;
&lt;h1&gt;Vim Templates&lt;/h1&gt;
&lt;p&gt;There is a plugin called &lt;code&gt;vim-templates&lt;/code&gt; by Adrian Perez that gives us the opportunity to make a life of a blogger and a programmer a bit easier.&lt;/p&gt;
&lt;p&gt;You can find the project on GitHub repo - &lt;a href="https://github.com/aperezdc/vim-template"&gt;Vim-Templates&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;How to install&lt;/h1&gt;
&lt;p&gt;The most comfortable way will be by using &lt;a href="https://github.com/VundleVim/Vundle.vim"&gt;Vundle Vim Plugin Manager&lt;/a&gt;. That's the one I'm using, and that's why I'll cover how to do it this way.&lt;/p&gt;
&lt;p&gt;Add Plugin to your .vimrc file where you usually place your plugins:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Plugin &lt;span class="s1"&gt;&amp;#39;aperezdc/vim-template&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And now install it with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;vim +PluginInstall +qall
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That's it. You should have your plugin installed.&lt;/p&gt;
&lt;p&gt;You should now get to new shell env to get your plugin running.&lt;/p&gt;
&lt;h1&gt;How to use it?&lt;/h1&gt;
&lt;p&gt;Start a new file in vim, and if your extension is in templates directory, then you will get automatically generated content from that template.&lt;/p&gt;
&lt;p&gt;Of course, you may not want to use automatically generated content by this plugin, then remove auto-cmd within .vimrc:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;let&lt;/span&gt; g:templates_no_autocmd &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then to use this plugin all you need to do is use the vim command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;Template *.&amp;amp;&lt;span class="k"&gt;lt&lt;/span&gt;;here&lt;span class="p"&gt;-&lt;/span&gt;goes&lt;span class="p"&gt;-&lt;/span&gt;template&lt;span class="p"&gt;-&lt;/span&gt;extension&amp;amp;gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;i.e. for blog markdown file, I would use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;Template *.md
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Or for Python file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;Template *.&lt;span class="k"&gt;py&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;BE AWARE of using :Template&lt;/h1&gt;
&lt;p&gt;Making a vim-command &lt;code&gt;:Template *.py&lt;/code&gt; in an already filled file, will append content from template to your vim-buffer at the top.&lt;/p&gt;
&lt;h1&gt;Where are the templates?&lt;/h1&gt;
&lt;p&gt;Template files are located usually within directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;ls ~/.vim/bundle/vim-template/templates/
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Out of the box you have :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;ls -l ~/.vim/bundle/vim-template/templates/ &lt;span class="p"&gt;|&lt;/span&gt; sort &lt;span class="p"&gt;|&lt;/span&gt; uniq -c &lt;span class="p"&gt;|&lt;/span&gt; wc -l
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;so about 50 file-templates.&lt;/p&gt;
&lt;h1&gt;Can I extend them?&lt;/h1&gt;
&lt;p&gt;Yes, you can extend them! Tweak them to make what you want them to do.&lt;/p&gt;
&lt;p&gt;There are some unique characters in templates that make the whole process of automation even a bit further.&lt;/p&gt;
&lt;p&gt;I.e. the python template uses something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#! /usr/bin/env python&lt;/span&gt;
&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class="c1"&gt;# vim:fenc=utf-8&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Copyright © %YEAR% %USER% &amp;amp;lt;%MAIL%&amp;amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Distributed under terms of the %LICENSE% license.&lt;/span&gt;

&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;%HERE%&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Where you find special characters like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;%YEAR% - a current year.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;%USER% - a name from your computer user. Change it within .vimrc with : &lt;code&gt;let g:username = 'yourusername'&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;%MAIL% - email is a combination of your name on the computer and a host-name. This can be change within .vimrc with : &lt;code&gt;let g:email = 'anselmos@users.noreply.github.com'&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;%LICENSE% - which by default creates a "MIT" sign. You can change this within .vimrc with : &lt;code&gt;let g:license = 'yourslicensename'&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;%HERE% - will give nothing, but ensure that vim-cursor will get placed in the place where this sign is.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;For more knowledge&lt;/h1&gt;
&lt;p&gt;You can check documentation with vim using :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;help templates.txt
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Also, check out in browser &lt;a href="https://github.com/aperezdc/vim-template/blob/master/doc/template.txt"&gt;documentation of this plugin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I will surely check it whenever I will need to change something with the template.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/aperezdc/vim-template"&gt;Vim-Template Plugin github repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/aperezdc/vim-template/blob/master/doc/template.txt"&gt;Vim-Template docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/VundleVim/Vundle.vim"&gt;Vundle Plugin Manager github repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vi.stackexchange.com/questions/613/how-do-i-install-a-plugin-in-vim-vi"&gt;How do I Install a plugin in Vim/Vi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="vim"></category><category term="vim-templates"></category></entry><entry><title>Callable in python - do you even use it?</title><link href="http://witkowskibartosz.com/blog/callable-in-python-do-you-even-use-it.html" rel="alternate"></link><published>2018-03-02T23:00:00+01:00</published><updated>2018-03-02T23:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-02:/blog/callable-in-python-do-you-even-use-it.html</id><summary type="html">&lt;p&gt;Today let's find out what is the purpose of the &lt;code&gt;callable&lt;/code&gt; function and in which versions of python it does not work.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today let's find out what is the purpose of the &lt;code&gt;callable&lt;/code&gt; function and in which versions of python it does not work.&lt;/p&gt;
&lt;p&gt;S0-E28/E30 :)&lt;/p&gt;
&lt;h1&gt;Callable&lt;/h1&gt;
&lt;p&gt;A callable is a function that checks other methods/functions/classes to find out if that particular element has a &lt;code&gt;__call__&lt;/code&gt; implemented.&lt;/p&gt;
&lt;p&gt;Since variables like int or boolean will not have that, making :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;callable&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;/pre&gt;&lt;/div&gt;


&lt;p&gt;or &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Will output a "False". Meaning that those elements are &lt;code&gt;not callable&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;But let's check if an object will return true.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ASimpleClass&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="n"&gt;element1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ASimpleClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nb"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;No. It does not - why? because it's an Object, not a Callable.&lt;/p&gt;
&lt;p&gt;Now Let's find out if a class will be a callable:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="nb"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And sure thing, it does.&lt;/p&gt;
&lt;p&gt;Also for functions it is valid:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;function1&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Is there a situation where you would not recommand callable?&lt;/h1&gt;
&lt;p&gt;Yes. In fact, &lt;code&gt;callable&lt;/code&gt; was removed between 3.0 to 3.2. In 3.2 + it was brought back.&lt;/p&gt;
&lt;p&gt;So I would check if we are using 3.0 to 3.2 python. If yes, then I would not use callable. I would then check with code like that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgement&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/111234/what-is-a-callable-in-python"&gt;What is a callable in python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/functions.html#callable"&gt;Callable at 3.6.4 python docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.programiz.com/python-programming/methods/built-in/callable"&gt;Python callable()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3.1/whatsnew/3.0.html#builtins"&gt;What's new in Python 3.0 - Python 3.1.5 documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="python"></category><category term="python-v3"></category><category term="python-v2"></category></entry><entry><title>One year blog Anniversary - Why do I still blog?</title><link href="http://witkowskibartosz.com/blog/one-year-blog-anniversary-why-do-i-still-blog.html" rel="alternate"></link><published>2018-03-01T22:30:00+01:00</published><updated>2018-03-01T22:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-03-01:/blog/one-year-blog-anniversary-why-do-i-still-blog.html</id><summary type="html">&lt;p&gt;Today is the day when this Blog has it's One Year Anniversary. Exactly One year ago I decided to start blogging. Check out why after one year I still blog.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today is the day when this Blog has it's One Year Anniversary. Exactly One year ago I decided to start blogging. Check out why after one year I still blog.&lt;/p&gt;
&lt;p&gt;S0-E27/E30 :)&lt;/p&gt;
&lt;h1&gt;What was my first article?&lt;/h1&gt;
&lt;p&gt;You can look back using page-navigator on a list of posts and find out that my first blog post was &lt;a href="how-to-create-own-blog.html"&gt;How to create own blog&lt;/a&gt; which give a lot of input on making your own Blog! Even I am really a fan of it - because of amount of knowledge I've put into that particular article. &lt;/p&gt;
&lt;h1&gt;What I've prepared for 1st year blog anniversary&lt;/h1&gt;
&lt;p&gt;I've added two plugins:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/getpelican/pelican-plugins/tree/master/series"&gt;Series&lt;/a&gt; - a great plugin that enables the creation of series of posts. Configured by blogger. In my blog, you can check one of the &lt;a href="tag/30daychallenge.html"&gt;#30dayMiroBurnChallenge posts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/getpelican/pelican-plugins/tree/master/related_posts"&gt;Related-posts&lt;/a&gt; - also a great plugin that enables making relations between posts that contains similar tags. It works automatically but can you can override its default behaviour. I have already enabled this plugin, Just go to the end of this posts and you will have five related posts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I decided finally to clean up a bit my markdown directory with posts and move files from one "bin" into individual directories i.e. &lt;code&gt;projects&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I do hope you those plugins will help you find some interesting articles.&lt;/p&gt;
&lt;p&gt;Now to the question.&lt;/p&gt;
&lt;h1&gt;Why do I still blog&lt;/h1&gt;
&lt;p&gt;I do tend to have a break from now to then. But even if I do - I come back. I believe it's because of those arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I feel achievement every time I put an article on the blog. (even if it's a straightforward tutorial) - sometimes I come-back to that post for knowledge.&lt;/li&gt;
&lt;li&gt;Each time I blog, I try to find an interesting thing that I'm currently working on or that fascinates me. That helps me to move forward with my knowledge and experience.&lt;/li&gt;
&lt;li&gt;Sharing knowledge with others! - You have a friend that's likely to have a problem that you already solved? Why not share it on your blog or a StackOverflow?&lt;/li&gt;
&lt;li&gt;Making a post about something gives you an opportunity to learn that thing better - Why ? - Because you need to undestand beforehand what are you are blogging about - and that makes a type of &lt;a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging"&gt;"Rubber duck debugging"&lt;/a&gt; process in your mind - which alternatively improves the learning process.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's about it - that's what drives my blogging experience.&lt;/p&gt;
&lt;p&gt;How about you? When do you plan to start your Blog ?&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/getpelican/pelican-plugins/tree/master/related_posts"&gt;pelican related_posts plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/getpelican/pelican-plugins/tree/master/series"&gt;pelican series plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/getpelican/pelican-themes/tree/master/pelican-bootstrap3"&gt;pelican pelican-bootstrap3 theme&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="pelican"></category><category term="pelican-plugin"></category><category term="pelican-themes"></category><category term="blog"></category><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category></entry><entry><title>Should I use has_key or in for dict at Python?</title><link href="http://witkowskibartosz.com/blog/should-i-use-has-key-or-in-for-dict-at-python.html" rel="alternate"></link><published>2018-02-28T18:30:00+01:00</published><updated>2018-02-28T18:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-28:/blog/should-i-use-has-key-or-in-for-dict-at-python.html</id><summary type="html">&lt;p&gt;Today a very brief topic about using has_key and my journey on finding that it does not work on Python3. Check out!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today a very brief topic about using has_key and my journey on finding that it does not work on Python3. Check out!&lt;/p&gt;
&lt;p&gt;S0-E26/E30 :)&lt;/p&gt;
&lt;h1&gt;Python Dictionaries&lt;/h1&gt;
&lt;p&gt;Let's say you have a dict like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;test_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;testkey&amp;quot;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;quot;testvalue&amp;quot;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;quot;TestKey2&amp;quot;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;quot;TEstkeyVal2&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And you want to know that there is a &lt;code&gt;testkey&lt;/code&gt; in this dictionary.&lt;/p&gt;
&lt;p&gt;At python2+ you could do that :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;test_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;testkey&amp;quot;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;quot;testvalue&amp;quot;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;quot;TestKey2&amp;quot;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;quot;TEstkeyVal2&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
assert test_dict.has_key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;testkey&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And the assertion would not raise.&lt;/p&gt;
&lt;p&gt;But in Python3+ you have an error:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;assert test_dict.has_key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;testkey&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
Traceback &lt;span class="o"&gt;(&lt;/span&gt;most recent call last&lt;span class="o"&gt;)&lt;/span&gt;:
  File &lt;span class="s2"&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;1&lt;/span&gt;, in &amp;lt;module&amp;gt;
  AttributeError: &lt;span class="s1"&gt;&amp;#39;dict&amp;#39;&lt;/span&gt; object has no attribute &lt;span class="s1"&gt;&amp;#39;has_key&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That's because &lt;code&gt;has_key&lt;/code&gt; has been removed from python3.&lt;/p&gt;
&lt;h1&gt;What should I do?&lt;/h1&gt;
&lt;p&gt;Instead of using &lt;code&gt;has_key&lt;/code&gt; use &lt;code&gt;in&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;testkey&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;test_dict&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Should I use dict.keys() to check then?&lt;/h1&gt;
&lt;p&gt;Short version - you should not - why ? because you may find yourself someday in a performance issue that is hard to trace.&lt;/p&gt;
&lt;p&gt;So don't make use of something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;key1&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dict1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Instead use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;key1&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dict1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/1323410/has-key-or-in/41390975#41390975"&gt;Check this stackoverflow comment about performance&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;or in this hidden code that I've copy-pasted so you don't need to go to SO:&lt;/p&gt;
&lt;p&gt;&lt;button onclick="example1Func()"&gt;Show/Hide!&lt;/button&gt;
&lt;div id="example1" style="display: none;"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ python3.5 -mtimeit -s&lt;span class="s1"&gt;&amp;#39;d=dict.fromkeys(range( 99))&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;d.has_key(12)&amp;#39;&lt;/span&gt;
Traceback &lt;span class="o"&gt;(&lt;/span&gt;most recent call last&lt;span class="o"&gt;)&lt;/span&gt;:
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;301&lt;/span&gt;, in main
        &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; t.timeit&lt;span class="o"&gt;(&lt;/span&gt;number&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;178&lt;/span&gt;, in timeit
        &lt;span class="nv"&gt;timing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.inner&lt;span class="o"&gt;(&lt;/span&gt;it, self.timer&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;&amp;lt;timeit-src&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;6&lt;/span&gt;, in inner
        d.has_key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
AttributeError: &lt;span class="s1"&gt;&amp;#39;dict&amp;#39;&lt;/span&gt; object has no attribute &lt;span class="s1"&gt;&amp;#39;has_key&amp;#39;&lt;/span&gt;

$ python2.7 -mtimeit -s&lt;span class="s1"&gt;&amp;#39;d=dict.fromkeys(range(  99))&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;d.has_key(12)&amp;#39;&lt;/span&gt;
&lt;span class="m"&gt;10000000&lt;/span&gt; loops, best of &lt;span class="m"&gt;3&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;.0872 usec per loop

$ python2.7 -mtimeit -s&lt;span class="s1"&gt;&amp;#39;d=dict.fromkeys(range(1999))&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;d.has_key(12)&amp;#39;&lt;/span&gt;
&lt;span class="m"&gt;10000000&lt;/span&gt; loops, best of &lt;span class="m"&gt;3&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;.0858 usec per loop

$ python3.5 -mtimeit -s&lt;span class="s1"&gt;&amp;#39;d=dict.fromkeys(range(  99))&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;12 in d&amp;#39;&lt;/span&gt;
&lt;span class="m"&gt;10000000&lt;/span&gt; loops, best of &lt;span class="m"&gt;3&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;.031 usec per loop

$ python3.5 -mtimeit -s&lt;span class="s1"&gt;&amp;#39;d=dict.fromkeys(range(1999))&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;12 in d&amp;#39;&lt;/span&gt;
&lt;span class="m"&gt;10000000&lt;/span&gt; loops, best of &lt;span class="m"&gt;3&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;.033 usec per loop

$ python3.5 -mtimeit -s&lt;span class="s1"&gt;&amp;#39;d=dict.fromkeys(range(  99))&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;12 in d.keys()&amp;#39;&lt;/span&gt;
&lt;span class="m"&gt;10000000&lt;/span&gt; loops, best of &lt;span class="m"&gt;3&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;.115 usec per loop

$ python3.5 -mtimeit -s&lt;span class="s1"&gt;&amp;#39;d=dict.fromkeys(range(1999))&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;12 in d.keys()&amp;#39;&lt;/span&gt;
&lt;span class="m"&gt;10000000&lt;/span&gt; loops, best of &lt;span class="m"&gt;3&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;.117 usec per loop
&lt;/pre&gt;&lt;/div&gt;


&lt;/div&gt;

&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3.1/whatsnew/3.0.html#builtins"&gt;What's New in Python3.0 - python 3.1.5 docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1323410/has-key-or-in"&gt;has_key or 'in' on stackoverflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1323410/has-key-or-in/41390975#41390975"&gt;python - has_key() or in - with performance check&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;
&lt;script type="text/javascript"&gt;
function example1Func() {
    var x = document.getElementById("example1");
    if (x.style.display === "none") {
        x.style.display = "block";
    } else {
        x.style.display = "none";
    }
}
&lt;/script&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="python"></category><category term="python-3"></category><category term="python-2"></category><category term="dict"></category><category term="has_key"></category></entry><entry><title>How to use Pipenv</title><link href="http://witkowskibartosz.com/blog/how-to-use-pipenv.html" rel="alternate"></link><published>2018-02-27T20:30:00+01:00</published><updated>2018-02-27T20:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-27:/blog/how-to-use-pipenv.html</id><summary type="html">&lt;p&gt;Have you noticed that recommendation for Managing Application Dependency at python.org has been changed? Apparently our python community should use now Pipenv. But how to? Let's check out!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Have you noticed that recommendation for Managing Application Dependency at python.org has been changed? Apparently our python community should use now Pipenv. But how to? Let's check out!&lt;/p&gt;
&lt;p&gt;S0-E25/E30 :)&lt;/p&gt;
&lt;h1&gt;Pipenv&lt;/h1&gt;
&lt;p&gt;The &lt;a href="https://pipenv.readthedocs.io/en/latest/"&gt;Pipenv&lt;/a&gt; has been created by &lt;a href="https://github.com/kennethreitz"&gt;Kenneth Reitz&lt;/a&gt; - who complained at his blog in this &lt;a href="https://www.kennethreitz.org/essays/a-better-pip-workflow"&gt;post - A better pip workflow&lt;/a&gt; - about pip workflow - and then created this tool.&lt;/p&gt;
&lt;p&gt;You can check Readme for pypenv at their &lt;a href="https://github.com/pypa/pipenv"&gt;github repository&lt;/a&gt; to find out what problems it solves :) I encourage you to do that ! &lt;/p&gt;
&lt;h1&gt;Let's get started!&lt;/h1&gt;
&lt;h2&gt;Installing Pipenv&lt;/h2&gt;
&lt;p&gt;So first things first - What do we need for Pipenv ?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pip&lt;/code&gt; - you can find out how to get pip &lt;a href="https://pip.pypa.io/en/stable/installing/"&gt;here&lt;/a&gt; - but for most of the &lt;code&gt;*nix&lt;/code&gt; users - you should already have pip packaged with your system.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install pipenv
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Adding a shell-completion!&lt;/h2&gt;
&lt;h3&gt;Bash&lt;/h3&gt;
&lt;p&gt;Put command below into your &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.bash_profile&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;pipenv --completion&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Basic usage&lt;/h1&gt;
&lt;p&gt;Let's make some day-to-day tasks with pipenv:&lt;/p&gt;
&lt;h2&gt;Create new project using python3.6&lt;/h2&gt;
&lt;p&gt;First let's make a project with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;mkdir pipenv_test_project
&lt;span class="nb"&gt;cd&lt;/span&gt; pipenv_test_project
git init .
git commit --allow-empty -m &lt;span class="s2"&gt;&amp;quot;Init&amp;quot;&lt;/span&gt;
git remote add origin git@github.com:anselmos/pipenv_test_project.git
git push origin HEAD:master
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Initialize pipenv at project&lt;/h2&gt;
&lt;p&gt;And now initialize pipenv at the &lt;code&gt;pipenv_test_project&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv --python &lt;span class="m"&gt;3&lt;/span&gt;.6
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Activating pipenv at project&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv shell
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;REMEMBER - you need to be in the root path of the project.&lt;/p&gt;
&lt;h2&gt;Install all dependences including dev:&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv install --dev
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This will create a &lt;code&gt;Pipfile.lock&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Let's install some dependency i.e. selenium&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv install selenium
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And your Pipfile and Pipfile.lock has been changed.&lt;/p&gt;
&lt;h2&gt;Installing old version of pelican and upgrading&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv install &lt;span class="nv"&gt;pelican&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.6.0
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Upgrading to latest version of pelican&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv install pelican
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Which will automatically check version and install the latest - 3.7.1 ! Yeah.&lt;/p&gt;
&lt;h2&gt;Uninstalling pelican&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pipenv uninstall pelican
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;The &lt;code&gt;pipenv_test_project&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;The project for this article is available &lt;a href="https://github.com/anselmos/pipenv_test_project"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That was an introduction to pipenv - if you need a more advanced stuff - check &lt;a href="https://pipenv.readthedocs.io/en/latest/"&gt;documentation&lt;/a&gt; or &lt;code&gt;pipenv --man&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pipenv.readthedocs.io/en/latest/"&gt;Pipenv docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/pipenv"&gt;Pipenv github repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/pipenv/issues/1453"&gt;Pipenv official for recommended tools #1453 issue on pipenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kennethreitz.org/essays/a-better-pip-workflow"&gt;A Better Pip Workflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packaging.python.org/guides/tool-recommendations/#installation-tool-recommendations"&gt;Tool Recommendations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/pip"&gt;pip - "Pip installs Python"&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="python"></category><category term="pipenv"></category><category term="dependencies"></category><category term="python-dependencies"></category><category term="depencency-management"></category><category term="requirements"></category><category term="Pipfile"></category></entry><entry><title>Making a FullScreen Screenshot with Firefox Node on Selenium Hub</title><link href="http://witkowskibartosz.com/blog/making-a-fullscreen-screenshot-with-firefox-node-on-selenium-hub.html" rel="alternate"></link><published>2018-02-26T20:00:00+01:00</published><updated>2018-02-26T20:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-26:/blog/making-a-fullscreen-screenshot-with-firefox-node-on-selenium-hub.html</id><summary type="html">&lt;p&gt;Today we are going to make a fullscreen screenshot at Selenium Hub using Firefox node. Check out how to fix the issue.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today we are going to make a fullscreen screenshot at Selenium Hub using Firefox node. Check out how to fix the issue.&lt;/p&gt;
&lt;p&gt;This article is a followup of &lt;a href="grammarly-integration-for-pelican-part3.html"&gt;Grammarly Integration&lt;/a&gt; - intended for fixing fullscreen issue - you can check there how to make a screenshot.&lt;/p&gt;
&lt;p&gt;S0-E24/E30 :)&lt;/p&gt;
&lt;h1&gt;Full Screen Screenshot within Selenium.&lt;/h1&gt;
&lt;p&gt;There is a problem with latest versions of Firefox - and from what I've heard only FF v47.0.1 works properly.&lt;/p&gt;
&lt;p&gt;So Let's check out how to make a fullscreen screenshot with this version!&lt;/p&gt;
&lt;h1&gt;Firefox Node and Selenium Hub.&lt;/h1&gt;
&lt;p&gt;After quick research of the topic I've found version of Selenium Hub and Firefox Node docker images that makes fullscreen possible.&lt;/p&gt;
&lt;h1&gt;Version of Node and Hub&lt;/h1&gt;
&lt;p&gt;Version of the hub and node in docker-images is &lt;code&gt;2.53.1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Beaware that you need to pull Hub and Node. Using Latest Hub and previous version of Firefox Node will not work.&lt;/p&gt;
&lt;h1&gt;Running Firefox Node and Hub&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker rm -f selenium-hub
docker run -d -p &lt;span class="m"&gt;4444&lt;/span&gt;:4444 --name selenium-hub selenium/hub:2.53.1
docker rm -f selenium-node-firefox
docker run -d --link selenium-hub:hub --name selenium-node-firefox -v /dev/shm:/dev/shm selenium/node-firefox:2.53.1
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/seleniumhq/selenium/issues/1141"&gt;Ability to take full page screenshot&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://arthurpemberton.com/2017/12/full-page-screenshots-with-python-and-selenium"&gt;Full page screenshots with Python and Selenium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/elcamino/5f562564ecd2fb86f559"&gt;How to take full-page screenshots with Selenium and Google Chrome in Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pypi.python.org/pypi/selenium-chrome-screenshot/0.0.1"&gt;Selenium-Chrome-Screenshot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/SeleniumHQ/docker-selenium/issues/404"&gt;How to build with FF 47.0.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rafaferreira/docker-selenium/tree/master/NodeFirefox"&gt;docker-selenium/NodeFirefox at master - rafaferreira/docker-selenium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hub.docker.com/r/selenium/node-firefox/builds/bvdpvsfarm5evuni3wppdul/"&gt;Docker-Selenium Firefox Node Hub Build for FF 47.0.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="selenium"></category><category term="selenium-hub"></category><category term="node-firefox"></category><category term="selenium-node-firefox"></category><category term="fullscreen-screenshot-selenium"></category></entry><entry><title>Making Pelican Link To Title Plugin</title><link href="http://witkowskibartosz.com/blog/making-pelican-link-to-title-plugin.html" rel="alternate"></link><published>2018-02-25T23:00:00+01:00</published><updated>2018-02-25T23:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-25:/blog/making-pelican-link-to-title-plugin.html</id><summary type="html">&lt;p&gt;Today we are going to dive into Pelican, and it's plugins :) We are going to make a plugin that will transform only a link into an HTML link with a description consisting of the page title.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today we are going to dive into Pelican, and it's plugins :) We are 
going to make a plugin that will transform only a link into an HTML link
 with a description consisting of the page title.&lt;/p&gt;
&lt;p&gt;S0-E23/E30 :)&lt;/p&gt;
&lt;h1&gt;Pelican Plugins&lt;/h1&gt;
&lt;p&gt;In this blog we have already created pelican-plugin, you can check &lt;a href="tag/pelican-plugin.html"&gt;pelican-plugin tag&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;What type of signals pelican has to offer?&lt;/h1&gt;
&lt;p&gt;Well, that's the thing, they are not first-class documented things.&lt;/p&gt;
&lt;p&gt;For making them a bit more available and easier to debug, I've created &lt;a href="https://github.com/anselmos/debug_pelican_signals"&gt;debug_pelican_signals repository at github&lt;/a&gt; that contains all signals which you can now connect to Pycharm or pdb and debug. The methods are visible &lt;a href="https://github.com/anselmos/debug_pelican_signals/blob/master/plugins/signalsdebugger/signalsdebugger.py"&gt;at signalsdebugger.py of debug_pelican_signals repo.&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Making a Pelican Link To Title&lt;/h1&gt;
&lt;p&gt;Now let's make a pelican link to title plugin that will convert all links into links with a title.&lt;/p&gt;
&lt;p&gt;The plugin will be called 'Pelican Link to Title'. Its source code is available at &lt;a href="https://github.com/anselmos/pelican-link-to-title"&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Code itself:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; This is a main script for pelican_link_to_title &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pelican&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;urllib&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;link_to_title_plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Link_to_Title plugin &amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;article_ptags&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;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;html.parser&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;p_tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ahref&amp;#39;&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;tag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;p_tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;http://&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;href&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url_page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;utf-8&amp;quot;&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;read_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;html.parser&amp;quot;&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;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Registers Plugin &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link_to_title_plugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To use the plugin, all you need to do is add into your &lt;code&gt;PLUGINS&lt;/code&gt; in pelicanconf a &lt;code&gt;pelican-link-to-title&lt;/code&gt; and put in the article something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ahref&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;witkowskibartosz&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;ahref&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;and this "ahref" will be retransformed into:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://witkowskibartosz.com/blog/&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Anselmos&lt;/span&gt; &lt;span class="n"&gt;Blog&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Which means, it goes into this page, takes the title of the page and puts into a-href string data.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://web.stanford.edu/~zlotnick/TextAsData/Web_Scraping_with_Beautiful_Soup.html"&gt;Web Scraping with Beautiful Soup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="pelican"></category><category term="pelican_engine"></category><category term="pelican-plugin"></category><category term="pelican_link_to_title"></category></entry><entry><title>Making Elasticsearch Your Blog Search Engine.</title><link href="http://witkowskibartosz.com/blog/making-elasticsearch-your-blog-search-engine.html" rel="alternate"></link><published>2018-02-24T21:35:00+01:00</published><updated>2018-02-24T21:35:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-24:/blog/making-elasticsearch-your-blog-search-engine.html</id><summary type="html">&lt;p&gt;Do you have a blog, that lacks search engine that could find in content of your article where you wrote about &lt;em&gt;this&lt;/em&gt; and &lt;em&gt;that&lt;/em&gt; ? Let's check if Elasticsearch can help with it. Check out!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Do you have a blog, that lacks search engine that could find in content of your article where you wrote about &lt;em&gt;this&lt;/em&gt; and &lt;em&gt;that&lt;/em&gt; ? Let's check if Elasticsearch can help with it. Check out!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Elastic-Logo" src="images/elastic_logo.png"&gt;&lt;/p&gt;
&lt;p&gt;S0-E22/E30 :)&lt;/p&gt;
&lt;h1&gt;Elasticsearch store your pelican posts&lt;/h1&gt;
&lt;p&gt;This blog uses Pelican engine that uses either a reStructuredText or Markdown files which then are transformed into a html with some theme.&lt;/p&gt;
&lt;p&gt;Because of that, you can't have a search engine on html files online. Fortunately you can use Elasticsearch, push your &lt;em&gt;rst&lt;/em&gt;/&lt;em&gt;md&lt;/em&gt; Files and search for specific words in it :)&lt;/p&gt;
&lt;p&gt;Let's check how to achieve this.&lt;/p&gt;
&lt;h1&gt;Making a Search within your own .md files.&lt;/h1&gt;
&lt;p&gt;If you are so lucky to have some text files, you can start off. For my prof of concept purpose we'll use &lt;a href="https://github.com/getpelican/pelican-blog.git"&gt;github repo from pelican blog&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Let's make a script that would put data from md/rst files into Elasticsearch.&lt;/p&gt;
&lt;p&gt;Ofcourse let's don't repeat, and reuse what we have learned from &lt;a href="utilizing_elasticsearch_python_client.html"&gt;yesterday's elasticsearch python client&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Listing files with extension in python&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;glob&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_files&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;fileextension&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;walk&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;*.{}&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileextension&lt;/span&gt;&lt;span class="p"&gt;)))]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Putting file context into elasticsearch&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;import_rst_files&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;all_rst_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mypath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rst&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;docs&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;rst_file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_rst_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Readfile content:&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_file_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rst_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="s2"&gt;&amp;quot;_index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;blogpost-{}&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;_type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;blogpost&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rst_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;_source&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;PelicanblogAuthors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;content&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="n"&gt;docs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;helpers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bulk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;docs&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;read_file_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Making a very trivial searching&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search_in_elastic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phrase_to_search&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;blog&amp;quot;&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;elasticsearch_dsl&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Search&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;match&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;phrase_to_search&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&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;response&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Execution&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;import_rst_files&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_in_elastic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;print_found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This will list files, read them, put into elasticsearch and then output all found blog-posts with 'blog' phrase.&lt;/p&gt;
&lt;h1&gt;Bonus&lt;/h1&gt;
&lt;p&gt;You can find the code listed above in &lt;a href="https://github.com/anselmos/elk_for_pelican"&gt;this repository&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.freecodecamp.org/elasticsearch-with-django-the-easy-way-909375bc16cb"&gt;Elasticserach with Django the easy way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/18394147/recursive-sub-folder-search-and-return-files-in-a-list-python"&gt;Recursive Sub folder search nad return files in a list python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/3207219/how-do-i-list-all-files-of-a-directory"&gt;How do i list all files of a directory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="elk"></category><category term="elasticsearch"></category><category term="blog"></category></entry><entry><title>Utilizing Elasticsearch Python Client</title><link href="http://witkowskibartosz.com/blog/utilizing_elasticsearch_python_client.html" rel="alternate"></link><published>2018-02-23T23:00:00+01:00</published><updated>2018-02-23T23:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-23:/blog/utilizing_elasticsearch_python_client.html</id><summary type="html">&lt;p&gt;Elasticsearch is a great search engine, but using JSON and curl does not fit python. Fortunatelly there are two libraries that you can use - and in today's article I'll focus on that :) Check out!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Elasticsearch is a great search engine, but using JSON and curl does not fit python. Fortunately there are two libraries that you can use - and in today's article I'll focus on that :) Check out!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Elastic-Logo" src="images/elastic_logo.png"&gt;&lt;/p&gt;
&lt;p&gt;S0-E21/E30 :)&lt;/p&gt;
&lt;h1&gt;Elasticsearch python wrappers&lt;/h1&gt;
&lt;p&gt;How to start with Python Wrapper for Elasticsearch engine? &lt;/p&gt;
&lt;p&gt;That's pretty easy. First, we need to setup our elasticsearch engine by using a &lt;code&gt;jar&lt;/code&gt; file and use java, or for Docker to handle this heavy topic - &lt;a href="how_to_start_with_elastic_elk_stack.html"&gt;which you can find in my previous post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you do that, we can start tinkering with it using two python wrappers.&lt;/p&gt;
&lt;p&gt;First one is the Official one and it's called &lt;code&gt;Low Level&lt;/code&gt; because it uses simple api that makes just requests with json data (converted from python-dicts). This one is called &lt;code&gt;Elasticsearch-py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Second one is a bit more complex but also very user-friendly and rather easy to use and learn. It uses a different approach. Reusing official library, makes use of python's &lt;code&gt;lambdas&lt;/code&gt; making a very data-flow-friendly api.&lt;/p&gt;
&lt;p&gt;Let's check them out!&lt;/p&gt;
&lt;h1&gt;Elasticsearch-py&lt;/h1&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The only one is the library itself - you can install it with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install elasticsearch
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;This is an example of data that you could put in a blog-post:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;elasticsearch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;blog_post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;date&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;A new Blog-Post Content!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;test-index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;blogpost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;blog_post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;What do you think what will be output of this script? &lt;/p&gt;
&lt;p&gt;&lt;button onclick="example1Func()"&gt;Show Me!&lt;/button&gt;&lt;/p&gt;
&lt;div id="example1" style="display: none;"&gt;
&lt;code&gt;
{u'_type': u'blogpost', u'_seq_no': 0, u'_shards': {u'successful': 1, u'failed': 0, u'total': 2}, u'_index': u'test-index', u'_version': 1, u'_primary_term': 1, u'result': u'created', u'_id': u'1'}
&lt;/code&gt;
&lt;/div&gt;

&lt;p&gt;And the Searching :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;elasticsearch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&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;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;test-index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;blogpost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;How to you think, will it output my data?&lt;/p&gt;
&lt;p&gt;&lt;button onclick="example2Func()"&gt;You already know the answer, don't you?&lt;/button&gt;
&lt;div id="example2" style="display: none;"&gt;
&lt;code&gt;
{u'_type': u'blogpost', u'_source': {u'date': u'2018-02-23', u'content': u'A new Blog-Post Content!', u'author': u'Anselmos'}, u'_index': u'test-index', u'_version': 3, u'found': True, u'_id': u'1'}
&lt;/code&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;h1&gt;Elasticsearch-dsl-py&lt;/h1&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The only one is the library itself - you can install it with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install elasticsearch-dsl
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Search Query!&lt;/h2&gt;
&lt;p&gt;This library has a more advanced features that can come in handy especially in a advanced search with filtering.&lt;/p&gt;
&lt;p&gt;To make a better use of this library, let's make a list of data for searching:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;elasticsearch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;elasticsearch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;helpers&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;blog&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;anselmos&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;elk&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;elastic&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;elasticsearch&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;elasticstack&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;elasticsearch-py&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;elasticsearch-dsl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Anselmos&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Bartosz Witkowski&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="s2"&gt;&amp;quot;_index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;blogpost-{}&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;_type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;blogpost&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;_source&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;date&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;A new Blog-Post Content!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&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="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;helpers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bulk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That's an elasticsearch-py code that makes 10 blogposts with the same content, but different tags (randomized ).&lt;/p&gt;
&lt;p&gt;Let's say, we wanted to know which tag have &lt;code&gt;blog&lt;/code&gt; and author equals &lt;code&gt;Anselmos&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;with low-level api this would be:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;elasticsearch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;query&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;bool&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;should&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;match&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;query&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;blog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}}}]}}}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;query&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;bool&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;should&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;match&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;query&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}}}]}}}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;msearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;blogpost-2018-02-23&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;blogpost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;queries&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="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And how about hour High Level ? &lt;/p&gt;
&lt;p&gt;Check-out&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;elasticsearch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;elasticsearch_dsl&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Search&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;match&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;blog&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;match&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Anselmos&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/elastic/elasticsearch-py"&gt;Official Python low-level client for Elasticsearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/elastic/elasticsearch-dsl-py"&gt;High Level Python client for Elasticsearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elasticsearch-py.readthedocs.io/en/master/api.html#elasticsearch"&gt;Elasticsearch-py API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://elasticsearch-py.readthedocs.io/en/master/helpers.html"&gt;Elasticsearch-py Helpers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://elasticsearch-dsl.readthedocs.io/en/latest/api.html"&gt;Elasticsearch-dsl API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://elasticsearch-dsl.readthedocs.io/en/latest/search_dsl.html"&gt;Elasticsearch-dsl Search DSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/kibana/current/tutorial-load-dataset.html"&gt;Loading Sample Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/kibana/current/tutorial-visualizing.html"&gt;Visualizing Your Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/guide/master/running-elasticsearch.html"&gt;Installing and Running Elasticsearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.x/query-dsl-query-string-query.html#query-string-syntax"&gt;Query String Query Syntax&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-use-kibana-dashboards-and-visualizations"&gt;How To Use Kibana Dashboards and Visualizations&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-elasticsearch-logstash-and-kibana-elk-stack-on-ubuntu-14-04"&gt;How To Install Elasticsearch, Logstash, and Kibana (ELK Stack) on Ubuntu 14.04&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/adding-logstash-filters-to-improve-centralized-logging"&gt;Adding Logstash Filters To Improve Centralized Logging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kevinmarsh.com/2014/10/23/using-jq-to-import-json-into-elasticsearch.html"&gt;Using jq to Import JSON into Elasticsearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tryolabs.com/blog/2015/02/17/python-elasticsearch-first-steps/"&gt;Python + Elasticsearch. First steps.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://labs.encoded.io/2015/01/02/analytics-with-elasticsearch-and-kibana/"&gt;Simple Analytics with Elasticsearch and Kibana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/20288770/how-to-use-bulk-api-to-store-the-keywords-in-es-by-using-python"&gt;SO-How to use Bulk API to store the keywords in ES by using Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/15014310/why-is-there-no-xrange-function-in-python3"&gt;SO-Why is there no xrange function in Python3?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/28546253/how-to-create-request-body-for-python-elasticsearch-msearch"&gt;SO-How to create request body for Python Elasticsearch mSearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=UPkqFvjN-yI"&gt;Elasticsearch in an Hour&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://flaviof.com/blog/hacks/pelican-show-hide-button.html"&gt;Adding show/hide button to pelican-bootstrap3 theme &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3schools.com/howto/howto_js_toggle_hide_show.asp"&gt;How TO - Toggle Hide and Show&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;
&lt;script type="text/javascript"&gt;
function example1Func() {
    var x = document.getElementById("example1");
    if (x.style.display === "none") {
        x.style.display = "block";
    } else {
        x.style.display = "none";
    }
}
function example2Func() {
    var x = document.getElementById("example2");
    if (x.style.display === "none") {
        x.style.display = "block";
    } else {
        x.style.display = "none";
    }
}
&lt;/script&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="elk"></category><category term="elasticsearch"></category><category term="logstash"></category><category term="kibana"></category></entry><entry><title>How to start with Elastic ELK Stack</title><link href="http://witkowskibartosz.com/blog/how_to_start_with_elastic_elk_stack.html" rel="alternate"></link><published>2018-02-22T06:50:00+01:00</published><updated>2018-02-22T06:50:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-22:/blog/how_to_start_with_elastic_elk_stack.html</id><summary type="html">&lt;p&gt;Today I'm going to present you an ELK - Elasticsearch stack solution and how to start with it :) Checkout :)&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I'm going to present you an ELK - Elasticsearch stack solution and how to start with it :) Checkout :)
&lt;img alt="Elastic-Logo" src="images/elastic_logo.png"&gt;&lt;/p&gt;
&lt;p&gt;S0-E20/E30 :)&lt;/p&gt;
&lt;h1&gt;Elasticsearch - what is it?&lt;/h1&gt;
&lt;p&gt;Elasticsearch is a tool - or rather a stack of tools called ELK which combines at least 3 apps: Elasticsearch, Logstash and Kibana.&lt;/p&gt;
&lt;p&gt;Logstash is just a propagator of data to searcher-elasticsearch which is visualised within Kibana :) That's a big shortcut of what ELK stack is.&lt;/p&gt;
&lt;p&gt;Details and information about that are widely spread all over the internet, just check firstly &lt;a href="https://www.elastic.co/elk-stack"&gt;here - at documentation&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Elasticsearch ELK Stack with docker.&lt;/h1&gt;
&lt;h2&gt;Elasticsearch&lt;/h2&gt;
&lt;p&gt;Based on tutorial there is an easy &lt;code&gt;docker-run&lt;/code&gt; command for elasticsearch:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run -p &lt;span class="m"&gt;9200&lt;/span&gt;:9200 -p &lt;span class="m"&gt;9300&lt;/span&gt;:9300 --name elasticsearch -e &lt;span class="s2"&gt;&amp;quot;discovery.type=single-node&amp;quot;&lt;/span&gt; docker.elastic.co/elasticsearch/elasticsearch:6.2.2
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Logstash&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker pull docker.elastic.co/logstash/logstash:6.2.2
docker pull docker.elastic.co/logstash/logstash-oss:6.2.2
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Without any volumens and configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run --rm -it --link elasticsearch:localhost docker.elastic.co/logstash/logstash:6.2.2
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And with only one config file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run --rm -it -v ~/settings/logstash.yml:/usr/share/logstash/config/logstash.yml docker.elastic.co/logstash/logstash:6.2.2
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Kibana&lt;/h2&gt;
&lt;p&gt;Run without configuration (just basic):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker pull docker.elastic.co/kibana/kibana:6.2.2
docker run --rm -it --link elasticsearch:localhost -p &lt;span class="m"&gt;5601&lt;/span&gt;:5601 docker.elastic.co/kibana/kibana:6.2.2
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;A Bonus!&lt;/h1&gt;
&lt;p&gt;I've decided to make a simple &lt;a href="https://github.com/anselmos/elk_starter_kit"&gt;github repo&lt;/a&gt; which intend is to use it as a starter for anyone looking into ELK first time.&lt;/p&gt;
&lt;p&gt;Enjoy it :)&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/deviantony/docker-elk"&gt;The ELK stack powered by Docker and Compose. &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/elastic/elasticsearch-docker"&gt;Official Elasticsearch Docker image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/elastic/logstash-docker"&gt;Official Logstash Docker image &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/elastic/kibana-docker"&gt;Official Kibana Docker image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html"&gt;Install Elasticsearch with Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/products/logstash"&gt;Logstash Help&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/logstash/current/introduction.html"&gt;Logstash Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/logstash/current/docker.html"&gt;Running Logstash on Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/logstash/current/docker-config.html"&gt;Configuring Logstash for Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/kibana/current/docker.html"&gt;Running Kibana on Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/beats/filebeat/6.x/filebeat-module-system.html"&gt;System module -Filebeat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="elk"></category><category term="elasticsearch"></category><category term="logstash"></category><category term="kibana"></category></entry><entry><title>How to integrate Travis with Selenium Tests using Docker</title><link href="http://witkowskibartosz.com/blog/how_to_integrate_travis_with_selenium_tests_using_docker.html" rel="alternate"></link><published>2018-02-21T17:00:00+01:00</published><updated>2018-02-21T17:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-21:/blog/how_to_integrate_travis_with_selenium_tests_using_docker.html</id><summary type="html">&lt;p&gt;Integration of Travis with Selenium - is it possible ? How would you do that ? Checkout !&lt;/p&gt;</summary><content type="html">&lt;p&gt;Integration of Travis with Selenium - is it possible? How would you do that? Checkout!&lt;/p&gt;
&lt;p&gt;S0-E19/E30 :)&lt;/p&gt;
&lt;h1&gt;Travis and Docker&lt;/h1&gt;
&lt;p&gt;If you don't already know, I'm a big fan of the docker, and how the service has impacted developers society as such that each developer can take any new fancy-pancy tool and use it without having to get bored about the configuration of new server.&lt;/p&gt;
&lt;p&gt;You may ask yourself - how is that related to Travis and Selenium ? Well... I'm going to try to use Travis and Docker Selenium image to run those tests :) &lt;/p&gt;
&lt;p&gt;But did you knew there is possibility to make use of Docker within Travis?&lt;/p&gt;
&lt;p&gt;Until yesterday I didn't know. But when I've found I've thought to myself - I have to check it!&lt;/p&gt;
&lt;p&gt;So Let's check how to begin Travis-docker integration first shall we?&lt;/p&gt;
&lt;h2&gt;Travis file.&lt;/h2&gt;
&lt;p&gt;Travis as you can check in documentation should contain few key things. First of all:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;language: python
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;a href="https://docs.travis-ci.com/user/languages/python/"&gt;Building a Python Project with Travis&lt;/a&gt; gives you a more advanced look at possibilities for Python-language project.&lt;/p&gt;
&lt;p&gt;So a simple &lt;code&gt;.travis.yml&lt;/code&gt; will look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;language: python
python:
    - &lt;span class="s2"&gt;&amp;quot;2.7&amp;quot;&lt;/span&gt;
    - &lt;span class="s2"&gt;&amp;quot;3.6&amp;quot;&lt;/span&gt;
&lt;span class="c1"&gt;# command to install dependencies&lt;/span&gt;
install:
 - pip install -r requirements.txt
&lt;span class="c1"&gt;# command to run tests&lt;/span&gt;
script:
 - pytest &lt;span class="c1"&gt;# or py.test for Python versions 3.5 and below&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And docker will need to be handled like this &lt;a href="https://docs.travis-ci.com/user/docker/"&gt;As described here&lt;/a&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;language: python
python:
    - &lt;span class="s2"&gt;&amp;quot;2.7&amp;quot;&lt;/span&gt;

services:
    - docker

before_install:
    - docker pull selenium/node-firefox:3.8.1-francium
    - docker pull selenium/hub:3.8.1-francium
    - docker run -d -p &lt;span class="m"&gt;4444&lt;/span&gt;:4444 --name selenium-hub selenium/hub:3.8.1-francium
    - docker run -d --link selenium-hub:hub --name selenium-node-firefox -v /dev/shm:/dev/shm selenium/node-firefox:3.8.1-francium

&lt;span class="c1"&gt;# command to install dependencies&lt;/span&gt;
install:
    - pip install -r requirements.txt
script:
    - python tests.py 
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Tests on Grammarly Selenium Automation Project!&lt;/h2&gt;
&lt;p&gt;So for our testing, I've used our Grammarly mini project to check if Travis will use it with Selenium-IDE and will use tests.&lt;/p&gt;
&lt;p&gt;And it DID! checkout result for &lt;a href="https://travis-ci.org/anselmos/grammarly-selenium-automation/jobs/344401329"&gt;python2.7 here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Adjustment for python3.6&lt;/h2&gt;
&lt;p&gt;I've also found that pip did not setup accurately project with &lt;code&gt;requirements.txt&lt;/code&gt; because those requirements were for python2.7.
Let's fix this by changing a bit &lt;code&gt;requirements.txt&lt;/code&gt; and check if tests on Travis will work :)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;argparse&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.2.1
&lt;span class="nv"&gt;beautifulsoup4&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.6.0
page-objects&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.1.0
&lt;span class="nv"&gt;selenium&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.9.0
wsgiref
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As you can see I've removed specific number of version for &lt;code&gt;wsgiref&lt;/code&gt; library because it's the one that &lt;a href="https://travis-ci.org/anselmos/grammarly-selenium-automation/jobs/344401330"&gt;failed this travis job&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This &lt;a href="https://github.com/anselmos/grammarly-selenium-automation/commit/f747d3db762cfd3f109e8332564b0fe579f95391"&gt;commit&lt;/a&gt; adds this fix and adds a Build-Status from Travis to README.md&lt;/p&gt;
&lt;p&gt;The results &lt;a href="https://travis-ci.org/anselmos/grammarly-selenium-automation/builds/344410156"&gt;are here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And as you can see this fix did not fix the problem :( So I've decided to &lt;a href="https://github.com/anselmos/grammarly-selenium-automation/commit/31abdb804cee282919a1d0fe0b582ce2914954af"&gt;remove a &lt;code&gt;wsgiref&lt;/code&gt; library from requirements&lt;/a&gt; and &lt;a href="https://travis-ci.org/anselmos/grammarly-selenium-automation/jobs/344412318"&gt;test again&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately as you can see, it also failed :) Because I forgot about very appealing redundant printing that was coded in python2.&lt;/p&gt;
&lt;p&gt;So I got rid of it. Now take a look at this &lt;a href="https://travis-ci.org/anselmos/grammarly-selenium-automation/builds/344413984"&gt;travis build&lt;/a&gt;. Taking into consideration that tests are not properly coded (using Python's &lt;code&gt;time.sleep&lt;/code&gt; instead of Selenium &lt;code&gt;Wait&lt;/code&gt;) sometimes This builds will fail -until I'll finally fix the problem :)&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/fabric/fabric/blob/master/.travis.yml"&gt;Travis example by Fabric&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.travis-ci.com/user/languages/python"&gt;Building a Python project -Travis Ci&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.travis-ci.com/user/docker/"&gt;Using Docker in Builds - Travis CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.travis-ci.com/user/gui-and-headless-browsers/"&gt;Gui and headless browser testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/travis-ci/worker"&gt;Travis worker on Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/travis-ci/travis.rb"&gt;Travis Ci Client CLI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="python"></category><category term="travis"></category><category term="selenium"></category><category term="unittests"></category><category term="gui-tests"></category><category term="integration"></category><category term="travis-ci"></category><category term="docker"></category><category term="docker-hub"></category><category term="selenium-docker-hub"></category><category term="selenium-hub"></category><category term="grammarly-selenium"></category><category term="grammarly-api"></category><category term="grammarly-integration"></category></entry><entry><title>Grammarly Integration for Pelican part3!</title><link href="http://witkowskibartosz.com/blog/grammarly-integration-for-pelican-part3.html" rel="alternate"></link><published>2018-02-20T22:00:00+01:00</published><updated>2018-02-20T22:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-20:/blog/grammarly-integration-for-pelican-part3.html</id><summary type="html">&lt;p&gt;Today more adventures about Grammarly and scraping data from checking-results.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today more adventures about Grammarly and scraping data from checking-results.&lt;/p&gt;
&lt;p&gt;S0-E18/E30 :)&lt;/p&gt;
&lt;h1&gt;Grammarly results scraping continues&lt;/h1&gt;
&lt;p&gt;After yesterday's article about possibility to scrape some results from Grammarly checking, let's now make a more advanced scraping :)&lt;/p&gt;
&lt;p&gt;Let's make an example with more issues, so we can experiment with BeautifulSoap and scrape more with it.&lt;/p&gt;
&lt;p&gt;I've found the "Demo document" that is presented within first usage of Grammarly, contains a lot of issues to present features of Grammarly. So let's use it :) &lt;/p&gt;
&lt;p&gt;Scraping:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tests_all_in_one&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="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Firefox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;demo_document.txt&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;demo_data_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;r+&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;demo_data_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;za2217279@mvrht.net&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyNewDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_new_document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DEMO DATA TEXT&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;demo_data_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;actual_source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page_source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_page_source&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;scraper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DocumentScraper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actual_source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;found_issues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scraper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all_issues&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;found_issues&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;
        &lt;span class="n"&gt;issues_by_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scraper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_issues_by_type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;issues_by_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_ed4374-plainTextTitle&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;issues_by_type&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_ed4374-titleReplacement&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;issues_by_type&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;issues_by_type&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_ed4374-plainTextTitle&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;issues_by_type&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_ed4374-titleReplacement&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And the source of &lt;code&gt;Document Scraper&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DocumentScraper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;html_source&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# self.html_source = html_source&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;html.parser&amp;quot;&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;get_issue_div&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="c1"&gt;# DIV with class=_adbfa1e6-editor-page-cardsCol&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;div&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;_adbfa1e6-editor-page-cardsCol&amp;#39;&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;get_all_warnings&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="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_issue_div&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_all_warnings_texts&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt;  &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_all_warnings&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;iterate_over_warnings&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;innerelement&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_all_warnings&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;innerelement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_all_issues&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="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;div&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;_ed4374-title&amp;#39;&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;return_issues_by_type&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;issues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all_issues&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;output&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;issue&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;issue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;issue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;issue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contents&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;output&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Where &lt;code&gt;demo_document.txt&lt;/code&gt; contains "Demo Document" from Grammarly.&lt;/p&gt;
&lt;p&gt;This gives you and example of how one can make our previous automation usable and transform it to something more.&lt;/p&gt;
&lt;h1&gt;Selenium Screenshots for better understanding Grammarly found issues.&lt;/h1&gt;
&lt;p&gt;Taking into account that there is no Selenium PDF generator - let's at least make a screenshot of page so we can then know where exactly those issues are:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save_screenshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;grammarly_checks.png&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_screenshot_as_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;grammarly_checks2.png&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The only problem I've found with this is that it does not make a full-page screenshot. I remember that within Java that trick worked and you could make a full-web-page screenshot (and the webbrowser).&lt;/p&gt;
&lt;p&gt;I might comeback to this :)&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/41721734/taking-screenshot-of-full-page-with-selenium-python-chromedriver"&gt;Taking a Screenshot of Full Page with Selenium Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://seleniumwithjavapython.wordpress.com/selenium-with-python/basics-of-webdriver/taking-screenshot-of-a-page/"&gt;Taking a Screenshot Of a Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/3422262/take-a-screenshot-with-selenium-webdriver"&gt;Take a screenshot with Selenium WebDriver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/37906704/taking-a-whole-page-screenshot-with-selenium-marionette-in-python"&gt;Taking a whole page screenshot with Selenium Marionette in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/fabtho/13e4a2e7cfbfde671b8fa81bbe9359fb"&gt;make a full screenshot with selenium in python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="python"></category><category term="pelican"></category><category term="python-static-sites"></category><category term="grammarly"></category><category term="grammarly-integration"></category><category term="grammarly-api"></category><category term="selenium"></category><category term="pelican-grammarly-plugin"></category></entry><entry><title>Grammarly Integration for Pelican part2!</title><link href="http://witkowskibartosz.com/blog/grammarly-integration-for-pelican-part2.html" rel="alternate"></link><published>2018-02-19T23:55:00+01:00</published><updated>2018-02-19T23:55:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-19:/blog/grammarly-integration-for-pelican-part2.html</id><summary type="html">&lt;p&gt;Today let's focus on gathering results from Grammarly document checking in our mini-automation-project :)&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today let's focus on gathering results from Grammarly document checking in our mini-automation-project :)&lt;/p&gt;
&lt;p&gt;This article is a part of &lt;a href="tag/pelican-grammarly-plugin.html"&gt;Grammarly Selenium Pelican Automation Mini project&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;S0-E17/E30 :)&lt;/p&gt;
&lt;h1&gt;Grammarly Automation Gathering Report.&lt;/h1&gt;
&lt;p&gt;So Grammarly creates an report in a PDF. But the report in PDF is just a simple PDF creation of HTML file.&lt;/p&gt;
&lt;p&gt;Why not disassemble that HTML page and get the results that we need instead of generating PDF and gathering only part of results? &lt;/p&gt;
&lt;p&gt;Let's check if our assumptions meet with reality :) &lt;/p&gt;
&lt;p&gt;So we have a text, lets for our example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;A simple
Multiline
text
That wraps
after max
2 words.
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Put this into grammarly and gather HTML output it will generate.&lt;/p&gt;
&lt;p&gt;Grammarly As I've found out will only generate pdf for premium users.&lt;/p&gt;
&lt;p&gt;So let's focus on disassembling the html.&lt;/p&gt;
&lt;p&gt;After gathering output from script:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_simple_text_gather_html&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot; This test is suppose to return html &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;za2217279@mvrht.net&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyNewDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_new_document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;text_to_put&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;A simple &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="s2"&gt;            Multiline &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="s2"&gt;            text &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="s2"&gt;            That wraps &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="s2"&gt;            after max &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="s2"&gt;            2 words. &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="s2"&gt;        &amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text_to_put&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I've found that there is an unique div called with css-class &lt;code&gt;_adbfa1e6-editor-page-cardsCol&lt;/code&gt; That does not change from document to document. Maybe that's just a feature for react-app to know where to put the result of checking ? Either way - we have output!&lt;/p&gt;
&lt;p&gt;But ... The output is not perfect. Data gathered in this way only gives a "shape" information - not exact details about where text is written in bad way - only information about specific text that is incorrect and the proposition for correct.&lt;/p&gt;
&lt;p&gt;So instead of using Selenium for sculpturing I'll use python's html extractor - Beautiful Soup.&lt;/p&gt;
&lt;p&gt;Let's make a source that will output html that then can be used within Beautiful Soup.&lt;/p&gt;
&lt;p&gt;Now the GrammarlyDocument src looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PageObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;input[type=&amp;quot;text&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;textarea&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# This button below will only be visible for grammarly premium users.&lt;/span&gt;
    &lt;span class="n"&gt;score_button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;span[class=&amp;quot;_ff9902-score&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;download_pdf_btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;div[class=&amp;quot;_d0e45e-button _d0e45e-medium&amp;quot;]&amp;#39;&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;put_title&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;title&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;put_text&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;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&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;def&lt;/span&gt; &lt;span class="nf"&gt;get_page_source&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="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And test:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_get_page_source&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;page_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;za2217279@mvrht.net&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyNewDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_new_document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;text_to_put&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;A simple &lt;/span&gt;&lt;span class="se"&gt;\n\&lt;/span&gt;
&lt;span class="s2"&gt;            Multiline &lt;/span&gt;&lt;span class="se"&gt;\n\&lt;/span&gt;
&lt;span class="s2"&gt;            text &lt;/span&gt;&lt;span class="se"&gt;\n\&lt;/span&gt;
&lt;span class="s2"&gt;            That wraps &lt;/span&gt;&lt;span class="se"&gt;\n\&lt;/span&gt;
&lt;span class="s2"&gt;            after max &lt;/span&gt;&lt;span class="se"&gt;\n\&lt;/span&gt;
&lt;span class="s2"&gt;            2 words. &lt;/span&gt;&lt;span class="se"&gt;\n\&lt;/span&gt;
&lt;span class="s2"&gt;        &amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_to_put&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;actual_source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page_source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_page_source&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;html&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;actual_source&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;/html&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;actual_source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Yeah It's very silly test, but for now is sufficient.&lt;/p&gt;
&lt;h1&gt;Reverse parse HTML&lt;/h1&gt;
&lt;p&gt;Let's start with what the &lt;a href="https://pypi.python.org/pypi/beautifulsoup4"&gt;&lt;code&gt;Beautiful Soup&lt;/code&gt;&lt;/a&gt; is.&lt;/p&gt;
&lt;p&gt;It's a python html extractor that can be usefull when you want to scrape data from html. It's used widly with web-crawlers.&lt;/p&gt;
&lt;p&gt;Now, let's make a DocumentScraper that will scrape data from html for us with at least the results data for now.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DocumentScraper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;html_source&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# self.html_source = html_source&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;html.parser&amp;quot;&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;get_issue_div&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="c1"&gt;# DIV with class=_adbfa1e6-editor-page-cardsCol&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;div&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;_adbfa1e6-editor-page-cardsCol&amp;#39;&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;get_all_warnings&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="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_issue_div&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_all_warnings_texts&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt;  &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_all_warnings&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;iterate_over_warnings&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;innerelement&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_all_warnings&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;innerelement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And the simplest test on pre-downloaded file (output from selenium):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;document_scraper&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DocumentScraper&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GrammarlyScrapingTests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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&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;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;bs_output_test1.html&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;r+&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data_scrape1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&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;test1&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="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data_scrape1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;21022&lt;/span&gt;
        &lt;span class="n"&gt;scraper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DocumentScraper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data_scrape1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Incorrect spacingwraps             after → wraps after&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scraper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_all_warnings_texts&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Part 3 !&lt;/h1&gt;
&lt;p&gt;There is going to be a part3 that will sum-up this mini-project and make this draft accessable.&lt;/p&gt;
&lt;p&gt;So stay tuned :) &lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/19957194/install-beautiful-soup-using-pip"&gt;python - install beautiful soap using pip&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.pythonforbeginners.com/files/reading-and-writing-files-in-python"&gt;reading and writing files in python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.travis-ci.com/user/gui-and-headless-browsers/"&gt;Gui and headless browser testing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="python"></category><category term="pelican"></category><category term="python-static-sites"></category><category term="grammarly"></category><category term="grammarly-integration"></category><category term="grammarly-api"></category><category term="selenium"></category><category term="pelican-grammarly-plugin"></category></entry><entry><title>Grammarly Integration for Pelican part1!</title><link href="http://witkowskibartosz.com/blog/grammarly-integration-for-pelican-part1.html" rel="alternate"></link><published>2018-02-18T16:30:00+01:00</published><updated>2018-02-18T16:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-18:/blog/grammarly-integration-for-pelican-part1.html</id><summary type="html">&lt;p&gt;There are no Grammarly applications that could deliver some type of integration with at least command-line. So let's make a selenium automation that will paste text into grammarly documents!&lt;/p&gt;</summary><content type="html">&lt;p&gt;There are no Grammarly applications that could deliver integration with at least command-line. So let's make selenium automation that will paste text into Grammarly documents!&lt;/p&gt;
&lt;p&gt;S0-E16/E30 :)&lt;/p&gt;
&lt;h1&gt;Grammarly Integration&lt;/h1&gt;
&lt;p&gt;For now [mid-February 2018] Grammarly does not give their users API that you could use in integrations with some blogging engines, but instead, you can use their &lt;a href="https://play.google.com/store/apps/details?id=com.grammarly.android.keyboard&amp;amp;hl=en"&gt;Android&lt;/a&gt;/&lt;a href="https://itunes.apple.com/us/app/grammarly-keyboard/id1158877342?mt=8"&gt;iOS&lt;/a&gt; spelling keyboard on your mobile or use Web-browser.&lt;/p&gt;
&lt;p&gt;There are integrations for &lt;a href="https://chrome.google.com/webstore/detail/grammarly-for-chrome/kbfnbcaeplbcioakkpcpgfkobkghlhen?hl=en"&gt;Chrome as a plugin&lt;/a&gt;, &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/grammarly-1/"&gt;Firefox addon&lt;/a&gt; and native in &lt;a href="https://www.grammarly.com/native"&gt;Windows and MacOS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since I'm a more into Linux - There is no real alternative than using their web-app.&lt;/p&gt;
&lt;p&gt;Yes, they are excellent and I still use them. But for now, I don't have mobile-integration for my blogging experience, as Pelican is a static-site generator and I store files on my computer. I'm planning to make some automations, and this post is one of them :)&lt;/p&gt;
&lt;p&gt;The best thing for now that I still do is manually copy-paste the actual text of blog-post and put it in Google-Keep and then use &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/grammarly-1/"&gt;Grammarly Firefox Plugin&lt;/a&gt;. That seems a bit silly and not as handy as an Automation that could do that for me.&lt;/p&gt;
&lt;h1&gt;Selenium automation for Grammarly&lt;/h1&gt;
&lt;p&gt;So I said to myself - why not create Selenium automation that will at least put actual text of blog-post into Grammarly Document?&lt;/p&gt;
&lt;h2&gt;Grammarly-Selenium-Automation project init.&lt;/h2&gt;
&lt;p&gt;First, let's create a repository on GitHub called &lt;code&gt;grammarly-selenium-automation&lt;/code&gt;.
Then Let's make git-repo with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;mkdir grammarly-selenium-automation
&lt;span class="nb"&gt;cd&lt;/span&gt; grammarly-selenium-automation
git init .
git commit --allow-empty -m &lt;span class="s2"&gt;&amp;quot;Init&amp;quot;&lt;/span&gt;
wget https://www.gitignore.io/api/vim%2Cpython -O .gitignore
git add .gitignore
git commit -m &lt;span class="s2"&gt;&amp;quot;Adds gitignore&amp;quot;&lt;/span&gt;
git remote add origin git@github.com:anselmos/grammarly-selenium-automation.git
git push -u origin master
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And now we have our repository available on &lt;a href="https://github.com/anselmos/grammarly-selenium-automation"&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now let's make actual selenium login-automation.&lt;/p&gt;
&lt;h2&gt;Grammarly Selenium login script.&lt;/h2&gt;
&lt;p&gt;For this script, I'll use one of my previous blog posts about &lt;a href="how-to-create-your-first-selenium-grid-compatible-test.html"&gt;making selenium-automation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;BTW - I've ofcourse forgot about making a virtualenv for using selenium :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; grammarly-selenium-automation &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; virtualenv .env &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; .env/bin/activate &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip install selenium &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip freeze &amp;gt; requirements.txt
git add requirements.txt
git commit -m &lt;span class="s2"&gt;&amp;quot;Adds pip requirements.txt&amp;quot;&lt;/span&gt;
git push origin HEAD:master
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And now the script:
&lt;code&gt;login.py&lt;/code&gt; script&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.common.keys&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Keys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;grammarly_page&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GrammarlyGeneralTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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&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="c1"&gt;# for dev I&amp;#39;ll use only visible browser instead of no-gui one.&lt;/span&gt;
        &lt;span class="c1"&gt;# but for production, it will use the no-gui one.&lt;/span&gt;
        &lt;span class="c1"&gt;# self.driver = webdriver.Firefox()&lt;/span&gt;
        &lt;span class="c1"&gt;# TODO uncomment it when finished coding.&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;command_executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://127.0.0.1:4444/wd/hub&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;desired_capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;browserName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;firefox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;javascriptEnabled&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&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;test_grammarly_in_title&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;page_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&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;page_login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Grammarly&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_login&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;page_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;za2217279@mvrht.net&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&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;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_url&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://app.grammarly.com/&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tearDown&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;and the &lt;code&gt;grammarly_page.py&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;page_objects&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PageObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PageObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;input[type=&amp;quot;email&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;input[type=&amp;quot;password&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;button[type=&amp;quot;submit&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://www.grammarly.com&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;signin_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/signin&amp;#39;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_login&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;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signin_uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can find it also at this repo tag: &lt;a href="https://github.com/anselmos/grammarly-selenium-automation/releases/tag/login-page-done"&gt;login-page-done&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Grammarly Selenium adds new file:&lt;/h2&gt;
&lt;p&gt;Now ! :) to the fun-part :) Let's make a new document in Grammarly and push it to the grammarly with copying data.&lt;/p&gt;
&lt;p&gt;While I was working on making new doc script, I've decided to change naming of the &lt;code&gt;login.py&lt;/code&gt; file into &lt;code&gt;tests.py&lt;/code&gt; - because I thought it will be more meaningful - since that's what it contains :) &lt;/p&gt;
&lt;p&gt;Moving on :&lt;/p&gt;
&lt;p&gt;Within &lt;code&gt;grammarly_page.py&lt;/code&gt; I've added this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GrammarlyNewDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PageObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://app.grammarly.com/&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;new_document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;div[role=&amp;quot;button&amp;quot;]&amp;#39;&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;make_new_document&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;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&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;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;input[type=&amp;quot;text&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PageElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;textarea&amp;#39;&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;put_title&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;title&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;put_text&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;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And on the &lt;code&gt;tests.py&lt;/code&gt; I've added this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_make_new_doc&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;page_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;za2217279@mvrht.net&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyNewDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_new_document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;TEST&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://app.grammarly.com/docs/&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_url&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_change_title_on_doc&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;page_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;za2217279@mvrht.net&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyNewDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_new_document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_doc&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;test_change_text_on_doc&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;page_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;za2217279@mvrht.net&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyNewDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_new_document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_doc&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;test_change_title_and_text_on_doc&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;page_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;za2217279@mvrht.net&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyNewDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_new_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_new_document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_doc&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;assert_title&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;page_doc&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;title_expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;NewTestTitle&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title_expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&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;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;actual_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actual_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&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;assert_text&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;page_doc&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;text_expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;A very bad text that are have some issues and Grammarly Should find problems with it&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;page_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&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;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;actual_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GrammarlyDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actual_doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can check the whole project in this state at tag: &lt;a href="https://github.com/anselmos/grammarly-selenium-automation/releases/tag/doc-title-and-text"&gt;doc-title-and-text&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Pelican plugin for Grammarly&lt;/h1&gt;
&lt;p&gt;That's just a POC for making Grammarly and Selenium Automation. In part2 I'll try to make integration with the pelican engine.&lt;/p&gt;
&lt;p&gt;This time I'll focus my attention on gathering as much as I can from the Grammarly document Checker. :)&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/c0nn3r/reverse_engineering_grammarly_api"&gt;C0nn3r-Reverse-engineering-grammarly-api&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/grammarly/status/388621218586578944?lang=en"&gt;Grammarly On Twitter - No API yet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tech.grammarly.com/blog/building-browser-extensions-at-scale#command-line-api"&gt;Building Browser Extensions at scale&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://english.stackexchange.com/questions/79657/is-grammarly-really-that-good"&gt;grammar - is 'Grammarly' really that good? &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://selenium-python.readthedocs.io/page-objects.html"&gt;Selenium Page Object Pattern for python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://page-objects.readthedocs.io/en/latest/"&gt;Page-Objects python lib&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Grammarly Alternatives:
- &lt;a href="https://textgears.com/"&gt;TextGears&lt;/a&gt; - this one has an API that you could use. ( and payment for amount of requests/data sent)&lt;/p&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="python"></category><category term="pelican"></category><category term="python-static-sites"></category><category term="grammarly"></category><category term="grammarly-integration"></category><category term="grammarly-api"></category><category term="selenium"></category><category term="pelican-grammarly-plugin"></category></entry><entry><title>How to upgrade python to 3.6.4</title><link href="http://witkowskibartosz.com/blog/how-to-upgrade-python-to-3.6.4.html" rel="alternate"></link><published>2018-02-17T22:25:00+01:00</published><updated>2018-02-17T22:25:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-17:/blog/how-to-upgrade-python-to-3.6.4.html</id><summary type="html">&lt;p&gt;Today I've learned my lesson - I need to upgrade my python from 3.4.3 to 3.6.4 because simplenote python-api will not work with previous versions. Checkout my experience while upgrading :)&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I've learned my lesson - I need to upgrade my python from 3.4.3 to 3.6.4 because while analysing simplenote python-api I've found that it will not work with previous versions. Checkout my experience while upgrading :)&lt;/p&gt;
&lt;p&gt;S0-E15/E30 :)&lt;/p&gt;
&lt;h1&gt;Simplenote Case&lt;/h1&gt;
&lt;p&gt;Few articles back I've wrote about simplenote and possibility to use it with vim. Unfortunatelly on my Ubuntu-Trusty (14.04) I could not.&lt;/p&gt;
&lt;p&gt;That time I've digged the problem a bit - but not as much to find out why it was not working on my machine.&lt;/p&gt;
&lt;p&gt;Today I've spend few hours on Docker and validating on which version of python It could work. Finally I've found that problem was with python and that using python 3.6.4 could solve problem with accessing simplenote!&lt;/p&gt;
&lt;h1&gt;Python upgrade to 3.6.4 from source !&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get install -y &lt;span class="se"&gt;\&lt;/span&gt;
     autotools-dev      &lt;span class="se"&gt;\&lt;/span&gt;
     blt-dev            &lt;span class="se"&gt;\&lt;/span&gt;
     bzip2              &lt;span class="se"&gt;\&lt;/span&gt;
     dpkg-dev           &lt;span class="se"&gt;\&lt;/span&gt;
     g++-multilib       &lt;span class="se"&gt;\&lt;/span&gt;
     gcc-multilib       &lt;span class="se"&gt;\&lt;/span&gt;
     libbluetooth-dev   &lt;span class="se"&gt;\&lt;/span&gt;
     libbz2-dev         &lt;span class="se"&gt;\&lt;/span&gt;
     libexpat1-dev      &lt;span class="se"&gt;\&lt;/span&gt;
     libffi-dev         &lt;span class="se"&gt;\&lt;/span&gt;
     libffi6            &lt;span class="se"&gt;\&lt;/span&gt;
     libffi6-dbg        &lt;span class="se"&gt;\&lt;/span&gt;
     libgdbm-dev        &lt;span class="se"&gt;\&lt;/span&gt;
     libgpm2            &lt;span class="se"&gt;\&lt;/span&gt;
     libncursesw5-dev   &lt;span class="se"&gt;\&lt;/span&gt;
     libreadline-dev    &lt;span class="se"&gt;\&lt;/span&gt;
     libsqlite3-dev     &lt;span class="se"&gt;\&lt;/span&gt;
     libssl-dev         &lt;span class="se"&gt;\&lt;/span&gt;
     libtinfo-dev       &lt;span class="se"&gt;\&lt;/span&gt;
     mime-support       &lt;span class="se"&gt;\&lt;/span&gt;
     net-tools          &lt;span class="se"&gt;\&lt;/span&gt;
     netbase            &lt;span class="se"&gt;\&lt;/span&gt;
     python-crypto      &lt;span class="se"&gt;\&lt;/span&gt;
     python-mox3        &lt;span class="se"&gt;\&lt;/span&gt;
     python-pil         &lt;span class="se"&gt;\&lt;/span&gt;
     python-ply         &lt;span class="se"&gt;\&lt;/span&gt;
     quilt              &lt;span class="se"&gt;\&lt;/span&gt;
     tk-dev             &lt;span class="se"&gt;\&lt;/span&gt;
     zlib1g-dev

wget https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tgz
tar -zxvf Python-3.6.4.tgz
&lt;span class="nb"&gt;cd&lt;/span&gt; Python-3.6.4/ &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./configure --prefix /usr/local/lib/python3.6.4 --enable-ipv6 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; -
&lt;span class="nb"&gt;cd&lt;/span&gt; Python-3.6.4/ &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; -
&lt;span class="nb"&gt;cd&lt;/span&gt; Python-3.6.4/ &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make altinstall
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Simplenote problems not resolved :(&lt;/h1&gt;
&lt;p&gt;Unfortunatelly it looks like upgrading to python3.6.4 is not the only thing I need to do.&lt;/p&gt;
&lt;p&gt;After the upgrade, simpenote.py still does not work on vim :/&lt;/p&gt;
&lt;p&gt;I will come back to this- but for now I'll just use docker-container with working solution of python3.6.4 with vim 7.4.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://simplenote.com/developers/"&gt;Simplenote Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/automattic/simplenote-electron"&gt;Simplenote Electron based on React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/automattic/simplenote-android"&gt;Simplenote Android client &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://simperium.com/docs/reference/http/#authorize"&gt;Simperium authorize API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hub.docker.com/r/library/python/tags/"&gt;Python Images Tags on Docker Hub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mrtazz/simplenote.py/pull/13"&gt;Python3 by sickmartian simplenote.py-PR#13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://askubuntu.com/questions/775059/vim-python-support-on-ubuntu-16-04"&gt;Vim python support on ubuntu 16.04&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mrtazz/simplenote.py/issues/21"&gt;Simplenote.py Issue #21&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vim/vim/issues/717"&gt;Pythons site module could not be loaded&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mbless.de/blog/2016/01/09/upgrade-to-python-2711-on-ubuntu-1404-lts.html"&gt;Upgrade to Python 2.7.11 on ubuntu 14.04LTS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/using/unix.html#getting-and-installing-the-latest-version-of-python"&gt;Using Python on Unix platforms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="python"></category><category term="ubuntu-trusty"></category><category term="python-v3"></category></entry><entry><title>How to deploy Docker on DockerHub with Github Push</title><link href="http://witkowskibartosz.com/blog/how-to-deploy-docker-on-hub-with-github-push.html" rel="alternate"></link><published>2018-02-16T22:00:00+01:00</published><updated>2018-02-16T22:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-16:/blog/how-to-deploy-docker-on-hub-with-github-push.html</id><summary type="html">&lt;p&gt;Did you ever wanted to deploy your own docker-image with only git-push ? Well I've got solution for you :) Check-it-out :)&lt;/p&gt;</summary><content type="html">&lt;p&gt;Did you ever wanted to deploy your own docker-image with only git-push ? Well I've got solution for you :) Check-it-out :) &lt;/p&gt;
&lt;p&gt;S0-E14/E30 :)&lt;/p&gt;
&lt;h1&gt;Project in Github&lt;/h1&gt;
&lt;p&gt;First what you need is a Github repository. Then what you need is to enable docker integration on the project with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Settings -&amp;gt; Integrations &amp;amp; services -&amp;gt; Add Service -&amp;gt; &amp;quot;Docker&amp;quot;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Docker Hub with access&lt;/h1&gt;
&lt;p&gt;When you have setup your github repository, what you need to do is go to Docker Hub and create your account if you haven't done it yet.
Then go to &lt;code&gt;Create&lt;/code&gt; -&amp;gt; &lt;code&gt;Create Automated Build&lt;/code&gt; -&amp;gt; &lt;code&gt;Link Accounts&lt;/code&gt; 
Or go to &lt;a href="https://hub.docker.com/account/authorized-services/"&gt;this site&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then you will link your github account.&lt;/p&gt;
&lt;p&gt;After this point you will be able to make automated builds for docker-images with git-pushes.&lt;/p&gt;
&lt;h1&gt;Docker image on Docker Hub with push&lt;/h1&gt;
&lt;p&gt;I've created a &lt;a href="https://github.com/anselmos/docker_discovery"&gt;github-test-repository called docker_discovery&lt;/a&gt; that is linked now with github.&lt;/p&gt;
&lt;p&gt;Dockerfile :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;FROM alpine
MAINTAINER anselmos@users.noreply.github.com
RUN apk update
RUN apk add vim
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can check my first successful build &lt;a href="https://hub.docker.com/r/anselmos/docker_discovery/builds/bszxrh3grijc6sa8bgnrvag/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/docker-hub/builds/#remote-build-triggers"&gt;Remote Build Triggers for Docker-hub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/docker-hub/github/#github-service-hooks"&gt;Github service hooks for docker-hub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stratoscale.com/blog/devops/practical-devops-use-case-github-jenkins-docker/"&gt;Practival devops use case github jenkins docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.brianchristner.io/how-to-automate-docker-builds-end-to-end/"&gt;How to Automate docker builds end to end&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="docker"></category><category term="github"></category><category term="git"></category><category term="dockerhub"></category></entry><entry><title>Update your tmux to latest version</title><link href="http://witkowskibartosz.com/blog/update-your-tmux-to-latest-version.html" rel="alternate"></link><published>2018-02-15T20:40:00+01:00</published><updated>2018-02-15T20:40:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-15:/blog/update-your-tmux-to-latest-version.html</id><summary type="html">&lt;p&gt;Today a very short tutorial on how to update tmux at *nix. Why would you update your tmux ? Checkout.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today a very short tutorial on how to update tmux at *nix. Why would you update your tmux ? Checkout.&lt;/p&gt;
&lt;p&gt;S0-E13/E30 :)&lt;/p&gt;
&lt;h1&gt;Tmux&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/tmux/tmux/wiki"&gt;Tmux&lt;/a&gt; is an terminal multiplexer and a some-how successor of &lt;a href="https://www.gnu.org/software/screen/"&gt;gnu-screen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I used to use screen, but since it didn't have such good multiplexing as tmux, I've decided to abandon it.&lt;/p&gt;
&lt;h1&gt;Why do you need latest version of tmux?&lt;/h1&gt;
&lt;p&gt;That's the problem - since I'm planning to use Ubuntu Trusty disto until 18.04 will be delivered, I need to update my packages from 14.04 manually.&lt;/p&gt;
&lt;p&gt;But why ? &lt;/p&gt;
&lt;p&gt;There's a plugin called &lt;code&gt;tmux-ressurect&lt;/code&gt; that has this fancy option to save &amp;amp; restore all tmux sessions with only &lt;code&gt;CMD + r&lt;/code&gt; and &lt;code&gt;CMD + s&lt;/code&gt;.
Unfortunatelly it needs at least 1.9 version of tmux and trusty disto went with 1.8 :( so let's upgrade to 2.6 :D &lt;/p&gt;
&lt;h1&gt;Building from source&lt;/h1&gt;
&lt;p&gt;Let's first install dependencies for building on our machine:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get -y remove tmux
sudo apt-get -y install wget tar libevent-dev libncurses-dev
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;then let's download source and unpack it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.6
wget https://github.com/tmux/tmux/releases/download/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/tmux-&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.tar.gz
tar xf tmux-&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.tar.gz
rm -f tmux-&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.tar.gz
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now let's build and install it and cleanit up:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.6
&lt;span class="nb"&gt;cd&lt;/span&gt; tmux-&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
./configure
make
sudo make install
&lt;span class="nb"&gt;cd&lt;/span&gt; -
sudo rm -rf /usr/local/src/tmux-&lt;span class="se"&gt;\*&lt;/span&gt;
sudo mv tmux-&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; /usr/local/src
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Than only thing that you SHOULD do - not to have problems with &lt;code&gt;protocol version mismatch&lt;/code&gt; is to kill old tmux server that can be still running in the background with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo killall -9 tmux
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://unix.stackexchange.com/questions/122238/protocol-version-mismatch-client-8-server-6-when-trying-to-upgrade"&gt;protocol version mismatch (client 8, server 6) when trying to upgrade&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/fikovnik/c64bd5f68701e8ce698afa58bdfb1d77"&gt;tmux 2.0 and tmux 2.3 installation steps for Ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="tmux"></category><category term="bash"></category></entry><entry><title>Grip and Vim for Note taking</title><link href="http://witkowskibartosz.com/blog/grip-and-vim-for-note-taking.html" rel="alternate"></link><published>2018-02-14T19:00:00+01:00</published><updated>2018-02-14T19:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-14:/blog/grip-and-vim-for-note-taking.html</id><summary type="html">&lt;p&gt;Grip it! There are plenty of tools to make your .markdown or .md files in a html way- but is there a vim plugin that would make it more automated and integrated ? Let's answer this question, shall we ?&lt;/p&gt;</summary><content type="html">&lt;p&gt;Grip it! There are plenty of tools to make your .markdown or .md files in a html way- but is there a vim plugin that would make it more automated and integrated ? Let's answer this question, shall we ?&lt;/p&gt;
&lt;p&gt;S0-E12/E30 :)&lt;/p&gt;
&lt;h1&gt;Vim note taking and a markdown files.&lt;/h1&gt;
&lt;p&gt;Vim is my favourite tool for making short notes. Also it works best as a IDE for python files.&lt;/p&gt;
&lt;p&gt;But how to make those markdown files available on your machine without having to use any websites or puting it online ?&lt;/p&gt;
&lt;p&gt;There's a way - besides those GUI apps that gives you that, you can actually make use of a &lt;code&gt;Grip&lt;/code&gt; markdown renderer.&lt;/p&gt;
&lt;h1&gt;Grip!&lt;/h1&gt;
&lt;p&gt;Thanks to &lt;a href="https://github.com/joeyespo"&gt;&lt;code&gt;Joe Esposito&lt;/code&gt;&lt;/a&gt; you can watch on browser how you type-in your markdown file. Each time you will save your markdown file that is connected with grip, it will automatically refresh.&lt;/p&gt;
&lt;p&gt;The project &lt;a href="https://github.com/joeyespo/grip"&gt;&lt;code&gt;Grip&lt;/code&gt;&lt;/a&gt; is something that I personally use and used even at work for short exchanging of information within markdown files. You can actually have a server that's on your machine visible within your local network. (putting aside network-alike problems).&lt;/p&gt;
&lt;p&gt;But in order to do that you have to have another script run in your system.&lt;/p&gt;
&lt;p&gt;How to use it ? &lt;/p&gt;
&lt;p&gt;First install grip with a pip (for global installation) or within your environment (first activate your virtual-env)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install grip
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Than if the file is called &lt;code&gt;README.md&lt;/code&gt; grip will automatically make use of it with command &lt;code&gt;grip&lt;/code&gt; if you are in the same directory as mentioned file.&lt;/p&gt;
&lt;p&gt;Grip actually will make a listing of files and you can access files from directory you started &lt;code&gt;grip&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;I.e. you have 2 files in your directory : &lt;code&gt;README.md&lt;/code&gt; and &lt;code&gt;a-very-important-note.md&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now what grip will do is select the &lt;code&gt;README.md&lt;/code&gt; and make a html page when you open your browser at &lt;code&gt;localhost:6419&lt;/code&gt;. Also you can go to &lt;a href="http://localhost:6419/a-very-important-node.md"&gt;localhost:6419/a-very-important-node.md&lt;/a&gt; and it will render your markdown file into html.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/joeyespo/grip#configuration"&gt;configuration section within readme of grip&lt;/a&gt; gives you even a hint of possibility to change port number on which the service will work.&lt;/p&gt;
&lt;h1&gt;Vim integrations for markdown files&lt;/h1&gt;
&lt;p&gt;Is there any type of integration with vim and markdown that you could use ? &lt;/p&gt;
&lt;h3&gt;Vim-Markdown&lt;/h3&gt;
&lt;p&gt;It's an integration for vim that reutilize power of vim to make markdown experience more vim-alike.&lt;/p&gt;
&lt;p&gt;I.e. this page is a markdown file that I'm currently writing! And I'm using Vim-Markdown that presents a TOC (Table Of Contents) on the right when I put in vim-exec mode :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;:Toc
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Also you can check all your links in md file if they link to proper site.&lt;/p&gt;
&lt;p&gt;Github project site &lt;a href="https://github.com/plasticboy/vim-markdown/"&gt;Vim-Markdown by plasticboy&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Vim-Wiki&lt;/h3&gt;
&lt;p&gt;It's a Markdown integration for making notes as a type of Wiki. You start with your &lt;code&gt;index.md&lt;/code&gt; and then you can create all your &lt;code&gt;notes&lt;/code&gt; within vim.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/vimwiki/vimwiki"&gt;Checkout github project page&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The only minus of this is that at this point you have to use a special type of syntax and a .wiki extensions.&lt;/p&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="grip"></category><category term="python"></category><category term="vim"></category><category term="vim-plugin"></category><category term="markdown"></category><category term="vim-wiki"></category></entry><entry><title>Unittests and Assert Raise</title><link href="http://witkowskibartosz.com/blog/unittests-and-assert-raise.html" rel="alternate"></link><published>2018-02-13T23:50:00+01:00</published><updated>2018-02-13T23:50:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-13:/blog/unittests-and-assert-raise.html</id><summary type="html">&lt;p&gt;Using assert raise within tests is a tricky thing - So today I'll focus on how to properly use it :)&lt;/p&gt;</summary><content type="html">&lt;p&gt;Using assert raise within tests is a tricky thing - So today I'll focus on how to properly use it :)&lt;/p&gt;
&lt;p&gt;S0-E11/E30 :)&lt;/p&gt;
&lt;h1&gt;Unittest with self.assertRaise for function tests&lt;/h1&gt;
&lt;p&gt;Let's present example for function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;raiser_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Is This function Called?&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestCase2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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;test_will_pass_self_assert_raise&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="c1"&gt;# proper usage&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raiser_function&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;test_with_self_assert_raise&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="c1"&gt;# proper usage&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;raiser_function&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;test_will_fail&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="c1"&gt;# added intentionally this line below for the test not to fail.&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="c1"&gt;# you should not call methoc/function inside of self.assertRaises, but give arguments and kwargs as self.assertRaises argument&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raiser_function&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Unittest with self.assertRaise for object method tests&lt;/h1&gt;
&lt;p&gt;Let's present example for object-method:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RaiserClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&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;methodToRaiseNotImplementedError&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="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Is This Test Called?&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestCase1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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;test_will_pass_self_assert_raise&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RaiserClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;methodToRaiseNotImplementedError&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;test_with_self_assert_raise&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="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;RaiserClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;methodToRaiseNotImplementedError&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;test_will_fail&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="c1"&gt;# added intentionally this line below for the test not to fail.&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;raiser_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RaiserClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raiser_object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;methodToRaiseNotImplementedError&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;test_will_fail2&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="c1"&gt;# added intentionally this line below for the test not to fail.&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RaiserClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;methodToRaiseNotImplementedError&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/6103825/how-to-properly-use-unit-testings-assertraises-with-nonetype-objects"&gt;How to properly use unit-testing's assertRaises() with NoneType objects?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.peterbe.com/plog/assertraises-and-inheritance"&gt;Careful with your assertRaises() and inheritance of exceptions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="python"></category><category term="unittest"></category><category term="assert"></category><category term="assert-raise"></category><category term="object-oriented-programming"></category><category term="functional-programming"></category><category term="with-assert-raise"></category></entry><entry><title>Zope Inteface and Its purpose</title><link href="http://witkowskibartosz.com/blog/zope-interface-and-its-purpose.html" rel="alternate"></link><published>2018-02-12T18:00:00+01:00</published><updated>2018-02-12T18:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-12:/blog/zope-interface-and-its-purpose.html</id><summary type="html">&lt;p&gt;This time let's focus on something different than usually - Let's check what Zope Interface is all about :)&lt;/p&gt;</summary><content type="html">&lt;p&gt;This time let's focus on something different than usually - Let's check what Zope Interface is all about :)&lt;/p&gt;
&lt;p&gt;S0-E10/E30 :)&lt;/p&gt;
&lt;h1&gt;Zope Interface&lt;/h1&gt;
&lt;p&gt;Zope Interface is a part of so called &lt;code&gt;Zope Toolkit&lt;/code&gt; - a set of libraries used within web-frameworks.&lt;/p&gt;
&lt;p&gt;This &lt;code&gt;interface&lt;/code&gt; is about making a reusable elements in system that you then re-purpose in a DRY principle.&lt;/p&gt;
&lt;h1&gt;Zope Interface usage&lt;/h1&gt;
&lt;p&gt;You may define your own interface for class. This may be good for example to know what tests needs to be created:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;zope&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;zope.interface.verify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;verifyClass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;zope.interface.verify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BrokenImplementation&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;zope.interface.tests&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;test_verify&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ITestObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interface&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;test_simplest_leading_zero&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; This test will check if LeadingZeroValidator behave as expected&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;implements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ITestObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@interface.implementer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ITestObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestObjectProperlyImplements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&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;test_simplest_leading_zero&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestIfMyTestObjectImplementsMethods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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;test_verify_fails&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="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BrokenImplementation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verifyClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ITestObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TestObject&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;test_verify_success&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;verifyClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ITestObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TestObjectProperlyImplements&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;test_using_test_method&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;testobj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TestObjectProperlyImplements&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;testobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test_simplest_leading_zero&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;NotImplementedError vs verifyClass&lt;/h1&gt;
&lt;p&gt;While I was researching the topic I've found that using anything inside of methods defined in Interface - will be disregarded.&lt;/p&gt;
&lt;p&gt;I wanted to create a more abstract Interface that would prompt about NotImplementedError - than I've found that &lt;code&gt;zope.interface.Interface&lt;/code&gt; disregards any body inside of the method.&lt;/p&gt;
&lt;p&gt;You need to create class based on this interface to be able to use NotImplementedError as in example above.&lt;/p&gt;
&lt;p&gt;Below you can check example of this mis-guided behaviour:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;zope&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;zope.interface.verify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;verifyClass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;zope.interface.verify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BrokenImplementation&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;zope.interface.tests&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;test_verify&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IHowNotCreateInterfaceWithMethodBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interface&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;method_that_should_be_implemented&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; This method needs to be implemented by object!&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="c1"&gt;# As it&amp;#39;s only interface, you should not give body to it, but we want to learn our lesson so:&lt;/span&gt;
        &lt;span class="c1"&gt;# anything that you do in this will be disregarded&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ImplementingHowNotCreateInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;implements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IHowNotCreateInterfaceWithMethodBody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestingHowNotCreateInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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;test_verify&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="c1"&gt;# at this point it will not fail with &amp;quot;NotImplementedError&amp;quot; - instead you can invoke your method and have AttributeError.&lt;/span&gt;
        &lt;span class="n"&gt;testobj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImplementingHowNotCreateInterface&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;testobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method_that_should_be_implemented&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BrokenImplementation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;verifyClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IHowNotCreateInterfaceWithMethodBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ImplementingHowNotCreateInterface&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://zopetoolkit.readthedocs.io/en/latest/index.html"&gt;Zope Toolkit docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/zopefoundation/zope.interface"&gt;Zope Interface - source on github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zopeinterface.readthedocs.io/en/latest/"&gt;Zope Interface Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zopeinterface.readthedocs.io/en/latest/api.html"&gt;Zope Interface - api docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://zopeinterface.readthedocs.io/en/latest/verify.html"&gt;Zope Interface Verify docs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/2521189/purpose-of-zope-interfaces"&gt;Purpose of Zope Interfaces?&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/2124190/how-do-i-implement-interfaces-in-python"&gt;How do I implement interfaces in python?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="python"></category><category term="zope-toolkit"></category><category term="zope-interface"></category><category term="pyramid"></category><category term="python-interface"></category><category term="interface"></category></entry><entry><title>Making Own Colander Validator with Tests</title><link href="http://witkowskibartosz.com/blog/making-own-colander-validator-with-tests.html" rel="alternate"></link><published>2018-02-11T20:05:00+01:00</published><updated>2018-02-11T20:05:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-11:/blog/making-own-colander-validator-with-tests.html</id><summary type="html">&lt;p&gt;Today I present you a my own Colander Validators! This includes tests that uses those validators! Check them out!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I present you a my own Colander Validators! This includes tests that uses those validators! Check them out!&lt;/p&gt;
&lt;p&gt;This episode is a series about &lt;a href="tag/colander.html"&gt;colander&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;S0-E9/E30 :)&lt;/p&gt;
&lt;h1&gt;Colander Validator Extended&lt;/h1&gt;
&lt;p&gt;Did you ever needed to create a more advanced validation than what Colander offers? I did!&lt;/p&gt;
&lt;p&gt;There is a way to create your own validations for elements. You can even extend pre-existing validations and add your own stuff in it.&lt;/p&gt;
&lt;p&gt;Let's say that you want to make sure at the validation step that data you will pass-on will have leading zero in one field.&lt;/p&gt;
&lt;p&gt;There are no validators like that in standard Colander library - you would need to extend it.&lt;/p&gt;
&lt;p&gt;Ofcourse you could use Regexp also.&lt;/p&gt;
&lt;p&gt;Let's make that, shall we ? :)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;colander&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LeadingZeroValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Validator for specific check if value has leading 0&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__call__&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;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Invalid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;No leading 0: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&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;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MappingSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;LeadingZeroValidator&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="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SequenceSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MappingSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;list_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&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;get_example_data&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;users&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Somlesna&amp;quot;&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="s2"&gt;&amp;quot;list_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;name_of_users&amp;quot;&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;get_validation_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;api_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# print api_data&lt;/span&gt;
    &lt;span class="n"&gt;json_loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dicted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_loaded&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;dicted&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;deserialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deserialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_validation_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_example_data&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;make_validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This code will now give information at the &lt;code&gt;make_validation&lt;/code&gt; step (&lt;code&gt;Data().deserialize(data)&lt;/code&gt;), that there is element with no leading zero value.&lt;/p&gt;
&lt;h1&gt;Using Colander in Unittests&lt;/h1&gt;
&lt;p&gt;Now let's make a unittest that will validate if our LeadingZeroValidator is working properly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;colander&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;extended_validation1&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_validation_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;make_validation&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;extended_validation1&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LeadingZeroValidator&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestLeadingZeroValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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;test_simplest_leading_zero&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;test_case&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;01&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LeadingZeroValidator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_case&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;test_simplest_failing_leading_zero&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;test_case&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LeadingZeroValidator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Invalid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_case&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;test_invalid_assert_raises&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;dict_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;users&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;02&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Somlesna&amp;quot;&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="s2"&gt;&amp;quot;list_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;name_of_users&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;testcase1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_validation_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Invalid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;make_validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testcase1&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;test_invalid_not_raises&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;dict_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;users&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;01&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2Anselmos&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;02&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2Somlesna&amp;quot;&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="s2"&gt;&amp;quot;list_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;name_of_users&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;testcase1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_validation_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;make_validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testcase1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And it does :) how sweet.&lt;/p&gt;
&lt;h1&gt;Where to go from here ?&lt;/h1&gt;
&lt;p&gt;You may check also information about SchemaTypes and creating your own SchemaType! :)&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Pylons/colander"&gt;Colander Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.pylonsproject.org/projects/colander/en/latest/api.html#validators"&gt;Colander Validators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;BTW - today is the last day when I eat junk food - why ? Because I'm starting another challenge for not eating junk food for the time of &lt;code&gt;fasting&lt;/code&gt; - so at least 40 days :) - So Keep finger crossed for me :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="colander"></category><category term="python"></category><category term="colander-python"></category><category term="serialization"></category><category term="deserialization"></category><category term="pyramid"></category><category term="json"></category><category term="colander-nested"></category><category term="colander-validators"></category><category term="validation"></category></entry><entry><title>Using Colander Validators with nested elements</title><link href="http://witkowskibartosz.com/blog/using-colander-validators-with-nested-elements.html" rel="alternate"></link><published>2018-02-10T23:10:00+01:00</published><updated>2018-02-10T23:10:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-10:/blog/using-colander-validators-with-nested-elements.html</id><summary type="html">&lt;p&gt;In todays episode we will use Colander with validators for nested elements :) Checkout my experience with them.&lt;/p&gt;</summary><content type="html">&lt;p&gt;In todays episode we will use Colander with validators for nested elements :) Checkout my experience with them.&lt;/p&gt;
&lt;p&gt;This episode is a series about &lt;a href="tag/colander.html"&gt;colander&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;S0-E8/E30 :)&lt;/p&gt;
&lt;h1&gt;Colander Nested&lt;/h1&gt;
&lt;p&gt;Let's say you have a nested list elements that also have atributes like this :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;users&amp;quot;&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="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&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="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Somlesna&amp;quot;&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="nt"&gt;&amp;quot;list_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;name_of_users&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Code that I would typically create would look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;dict_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;users&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Somlesna&amp;quot;&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="s2"&gt;&amp;quot;list_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;name_of_users&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;api_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;api_data&lt;/span&gt;
&lt;span class="n"&gt;json_loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dicted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_loaded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;dicted&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JsonDeserialize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;entry&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__dict__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;classed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonDeserialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;dicted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;classed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;classed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;What is the problem with it ? Well you still have to manually create a validator for each &lt;code&gt;user&lt;/code&gt; list-element.&lt;/p&gt;
&lt;p&gt;Colander can fix that with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;colander&lt;/span&gt;
&lt;span class="n"&gt;dict_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;users&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Somlesna&amp;quot;&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="s2"&gt;&amp;quot;list_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;name_of_users&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;api_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;api_data&lt;/span&gt;
&lt;span class="n"&gt;json_loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dicted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_loaded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;dicted&lt;/span&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;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MappingSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&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="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SequenceSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MappingSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;list_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;serialized&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dicted&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;pprint&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;deserialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deserialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dicted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deserialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now I now this looks pretty simple. But let's make another example that will use validator - which you could not create with simple json and dict "hack" :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;colander&lt;/span&gt;
&lt;span class="n"&gt;dict_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;users&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&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="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Somlesna&amp;quot;&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="s2"&gt;&amp;quot;list_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;name_of_users&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;api_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;api_data&lt;/span&gt;
&lt;span class="n"&gt;json_loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dicted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_loaded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;dicted&lt;/span&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;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MappingSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoneOf&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="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SequenceSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MappingSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;list_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;serialized&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dicted&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;pprint&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;deserialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deserialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dicted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deserialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Oh ... now it will fail with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;local/lib/python2.7/site-packages/colander/__init__.py&lt;span class="s2"&gt;&amp;quot;, line 704, in _impl&lt;/span&gt;
&lt;span class="s2"&gt;    raise error&lt;/span&gt;
&lt;span class="s2"&gt;colander.Invalid: {&amp;#39;users.0.id&amp;#39;: u&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot; must not be one of 1&amp;#39;,&lt;/span&gt;
&lt;span class="s2"&gt; &amp;#39;users.1.id&amp;#39;: u&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot; must not be one of 1&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Because we added to our schema validator like that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoneOf&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;/pre&gt;&lt;/div&gt;


&lt;p&gt;Ofcourse the obvious fix for that will be to change id's for user's to different than 1.&lt;/p&gt;
&lt;h1&gt;Colander build-in validators&lt;/h1&gt;
&lt;p&gt;There are 13 build-in colander validators that we can make great use.&lt;/p&gt;
&lt;p&gt;I encourage you to try them :)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_err&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;${val} is less than minimum value ${min}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_err&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;${val} is greater than maximum value ${max}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_err&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Shorter than minimum length ${min}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_err&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Longer than maximum length ${max}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OneOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;6.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoneOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_err&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;quot;${val}&amp;quot; must not be one of ${choices}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;7.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContainsOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;8.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;9.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;10.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;11.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;luhnok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;12.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;

&lt;span class="mf"&gt;13.&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Pylons/colander"&gt;Colander Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.pylonsproject.org/projects/colander/en/latest/api.html#validators"&gt;Colander Validators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;BTW - today is the last day when I eat junk food - why ? Because I'm starting another challenge for not eating junk food for the time of &lt;code&gt;fasting&lt;/code&gt; - so at least 40 days :) - So Keep finger crossed for me :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="colander"></category><category term="python"></category><category term="colander-python"></category><category term="serialization"></category><category term="deserialization"></category><category term="pyramid"></category><category term="json"></category><category term="colander-nested"></category><category term="colander-validators"></category><category term="validation"></category></entry><entry><title>How to use Colander - part1</title><link href="http://witkowskibartosz.com/blog/how-to-use-colander-part1.html" rel="alternate"></link><published>2018-02-09T23:00:00+01:00</published><updated>2018-02-09T23:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-09:/blog/how-to-use-colander-part1.html</id><summary type="html">&lt;p&gt;Did you ever wonder what are alternatives for serializing and deserializing besides of simple json de/serializer ? I didn't but I've found this library that I find pretty neat :)&lt;/p&gt;</summary><content type="html">&lt;p&gt;Did you ever wonder what are alternatives for serializing and deserializing besides of simple json de/serializer ? I didn't but I've found this library that I find pretty neat :)&lt;/p&gt;
&lt;h1&gt;What Colander is all about ?&lt;/h1&gt;
&lt;p&gt;Well, to be honest I would not found this library if it was not for &lt;a href="https://pyramid.readthedocs.io/en/latest/"&gt;pyramid&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;This library is a part of pyramid that integrates well into this &lt;code&gt;pyramid&lt;/code&gt; ;D (yeah a bit to dry humour :D)&lt;/p&gt;
&lt;p&gt;This library's main purpose is a type of serialization/deserialization mechanism with validation that can be extended.&lt;/p&gt;
&lt;h1&gt;How to use Colander?&lt;/h1&gt;
&lt;p&gt;You can use that i.e. within your small scripts / small frameworks that does not have a predefined serializers or where those serializers does not give you any type of extending for validating data.&lt;/p&gt;
&lt;p&gt;In frameworks like django, you should find colander not much usefull, but in flask - I would take it - unless I'd find something more advanced at those frameworks.&lt;/p&gt;
&lt;p&gt;So how to use it ? Let's have a look at small script that I've created for the sake of this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;json_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;height&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;surname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Somlesna&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;None&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;weight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Anselmos&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;bmi&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;26.12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;bmi_health_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Overweight&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;api_json_request_simulated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JsonDeserialize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;entry&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__dict__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;dict_deserialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_json_request_simulated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;test1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_deserialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# no walidation at this point! in colander you have already a validation at this point! that would prevent having something that should not be given validated.&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;JsonDeserialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;JsonDeserialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;JsonDeserialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi_health_name&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is a type of serialization to object that you could use. This ofcourse works. Main problem with it is that for making a validation you would need to replace mechanism for creating object from dict.&lt;/p&gt;
&lt;p&gt;There are no way for json.loads/dumps to validate data (at least I don't know about).&lt;/p&gt;
&lt;p&gt;But if someone from the blog audiance know about, please let me know :)&lt;/p&gt;
&lt;p&gt;With colander you can validate your data before decoding it to dict:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pprint&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;colander&lt;/span&gt;

&lt;span class="n"&gt;json_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;height&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;surname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Somlesna&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;None&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;weight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Anselmos&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;bmi&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;26.12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;bmi_health_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Overweight&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;api_json_request_simulated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dict_deserialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_json_request_simulated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;test1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_deserialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&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;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MappingSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&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="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;bmi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;bmi_health_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;deserialized_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_deserialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This code will give you error! Why? because main int-validator for ID has triggered:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;/local/lib/python2.7/site-packages/colander/__init__.py&lt;span class="s2"&gt;&amp;quot;, line 704, in _impl&lt;/span&gt;
&lt;span class="s2"&gt;    raise error&lt;/span&gt;
&lt;span class="s2"&gt;    colander.Invalid: {&amp;#39;id&amp;#39;: u&amp;#39;&amp;quot;&lt;/span&gt;None&lt;span class="s2"&gt;&amp;quot; is not a number&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;After a bit of changing now second validator will occur in this example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pprint&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;colander&lt;/span&gt;

&lt;span class="n"&gt;json_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;height&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;402&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;surname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Somlesna&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;id&amp;#39;&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="s1"&gt;&amp;#39;weight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Anselmos&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;bmi&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;26.12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;bmi_health_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Overweight&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;api_json_request_simulated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dict_deserialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_json_request_simulated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;test1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_deserialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&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;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MappingSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&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="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;bmi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;bmi_health_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;deserialized_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deserialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_deserialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Will output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;local/lib/python2.7/site-packages/colander/__init__.py&lt;span class="s2"&gt;&amp;quot;, line 704, in _impl&lt;/span&gt;
&lt;span class="s2"&gt;    raise error&lt;/span&gt;
&lt;span class="s2"&gt;    colander.Invalid: {&amp;#39;height&amp;#39;: u&amp;#39;402 is greater than maximum value 400&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Colander schemas and types.&lt;/h1&gt;
&lt;p&gt;This rather small tutorial does not end on this. Colander has many schema-types and extensions that I want do share with you in next episode! So stay tuned!&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Pylons/colander"&gt;Colander Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.pylonsproject.org/projects/colander/en/latest/interfaces.html#colander.interfaces.Validator"&gt;Colander Interfaces docs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/uralbash/awesome-pyramid"&gt;Pyramid Awesome list&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/18632562/catch-empty-list-with-colander"&gt;Catch empty list with colander&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/blob/master/bikingendorphines/api/tests/test_unit.py"&gt;BikingEndorphines unit-test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1305532/convert-python-dict-to-object"&gt;Convert python dict to object&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="30daychallenge-S0"></category><category term="colander"></category><category term="python"></category><category term="colander-python"></category><category term="serialization"></category><category term="deserialization"></category><category term="pyramid"></category><category term="json"></category></entry><entry><title>How to integrate vim with simplenote? Is there a way for that?</title><link href="http://witkowskibartosz.com/blog/how-to-integrate-vim-with-simplenote.html" rel="alternate"></link><published>2018-02-08T07:00:00+01:00</published><updated>2018-02-08T07:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-08:/blog/how-to-integrate-vim-with-simplenote.html</id><summary type="html">&lt;p&gt;Did you ever wonder how would it be to have your vim-files synced with a noting service? Well now you can use SimpleNote with mrtazz vim plugin that enables that ! :)&lt;/p&gt;</summary><content type="html">&lt;p&gt;S0-E6/E30 :)&lt;/p&gt;
&lt;p&gt;&lt;img alt="vim-icon" src="images/vim-icon.png"&gt;&lt;/p&gt;
&lt;h1&gt;How to integrate your SimpleNote account and your vim editor ?&lt;/h1&gt;
&lt;p&gt;There are a simple tutorial how to make your SimpleNote integrated with VIM.&lt;/p&gt;
&lt;p&gt;Use &lt;a href="http://github.com/mrtazz/simplenote.vim"&gt;mrtazz simplenote.vim repo&lt;/a&gt;  - as follows:&lt;/p&gt;
&lt;p&gt;Add this to your &lt;code&gt;.vimrc&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Plugin &lt;span class="s1"&gt;&amp;#39;mrtazz/simplenote.vim&amp;#39;&lt;/span&gt;

&lt;span class="nb"&gt;let&lt;/span&gt; g:SimplenoteUsername &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;your-email-here&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;let&lt;/span&gt; g:SimplenotePassword &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;your-password-here&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And then after re-activating your shell env, you should be able to use &lt;code&gt;vim +SimplenoteList&lt;/code&gt;  - or just make &lt;code&gt;vim&lt;/code&gt; and then in vim press:
&lt;code&gt;:SimplenoteList&lt;/code&gt; to list all your Simplenote Lists.&lt;/p&gt;
&lt;h1&gt;Failure to connect to server ?&lt;/h1&gt;
&lt;p&gt;After a bit of digging and testing I've unfortunatelly found that simplenote.py does not authorize user (it was few months ago when I've first found this project), not creating a proper token data- thous making impossible to use this plugin.&lt;/p&gt;
&lt;p&gt;I have approached &lt;a href="https://twitter.com/mrtazz"&gt;mrtazz&lt;/a&gt; on twitter which you can find &lt;a href="https://twitter.com/anselmos88/status/961477556133351424"&gt;here&lt;/a&gt; - but in the meantime I will try to investigate this problem and find a solution - then make a github PR to his repo :)&lt;/p&gt;
&lt;h1&gt;What's the purpose of this?&lt;/h1&gt;
&lt;p&gt;Why would you need a vim plugin to a SimpleNote ?
Well - for example if you want to make some type of integration with &lt;a href="https://www.grammarly.com/"&gt;Grammarly&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You could make your notes within SimpleNote by saving it with vim and then just go to browser and use Grammarly plugins in browser to fix any issues with your note/article/doc.&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;This article does not end on this un-happy scenario. I will create another with updates. There will be a Part2 of your SimpleNote-Vim Adventure :)&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mrtazz/simplenote.vim"&gt;SimpleNote Vim Plugin on Github by Daniel Schauenberg - &lt;code&gt;mrtazz&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mrtazz/simplenote.py"&gt;SimpleNote python-api plugin on github by mrtazz&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="30daychallenge-S0"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="simplenote"></category><category term="simplenote_vim"></category><category term="vim"></category><category term="vim_plugin"></category></entry><entry><title>How to fix removing docker.io on ubuntu</title><link href="http://witkowskibartosz.com/blog/how-to-fix-removing-docker-io-on-ubuntu.html" rel="alternate"></link><published>2018-02-07T21:30:00+01:00</published><updated>2018-02-07T21:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-07:/blog/how-to-fix-removing-docker-io-on-ubuntu.html</id><summary type="html">&lt;p&gt;Did you tried to purge your docker.io and unfortunatelly it did not make it? Here's a how-to to fix one of the issue that I've found myself.&lt;/p&gt;</summary><content type="html">&lt;p&gt;S0-E5/E30 :)&lt;/p&gt;
&lt;p&gt;&lt;img alt="docker-icon" src="images/docker.png"&gt;&lt;/p&gt;
&lt;h1&gt;How to fix problem on &lt;code&gt;shopt&lt;/code&gt; with &lt;code&gt;nuke-graph-directory.sh&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Did you have a problem while &lt;code&gt;sudo apt-get purge docker.io&lt;/code&gt; ? &lt;/p&gt;
&lt;p&gt;Was this problem related some-how with a &lt;code&gt;shopt&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;./contrib/nuke-graph-directory.sh: &lt;span class="m"&gt;64&lt;/span&gt;: ./contrib/nuke-graph-directory.sh: shopt: not found
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I have a fix for you - the fix is so trivial that untill I've found this &lt;a href="https://github.com/moby/moby/issues/30517"&gt;issue on github&lt;/a&gt; I did not realize that this &lt;code&gt;nuke-graph-directory.sh&lt;/code&gt; could run on different shell environment!&lt;/p&gt;
&lt;p&gt;To fix problem you have to change &lt;a href="https://en.wikipedia.org/wiki/Shebang_(Unix)"&gt;&lt;code&gt;shebang&lt;/code&gt;&lt;/a&gt; for this script:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;/var/lib/docker/nuke-graph-directory.sh
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;With what &lt;a href="https://github.com/tianon"&gt;tianon&lt;/a&gt; have commited in &lt;a href="https://github.com/moby/moby/commit/52379fa76dee07ca038624d639d9e14f4fb719ff#diff-8c7a34d8a429ced63b9fb11ca8f03b8b"&gt;this commit &lt;code&gt;nuke-graph-directory.sh&lt;/code&gt; file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So instead of :
&lt;code&gt;-#!/bin/sh&lt;/code&gt; - change to &lt;code&gt;#!/usr/bin/env bash&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;Why do I write about it today ?&lt;/h1&gt;
&lt;p&gt;Well... that's my little secret I have to confess - I did not checked yesterdays commands from article at the time of creating it.&lt;/p&gt;
&lt;p&gt;I was almost 100% sure command &lt;code&gt;apt-get purge&lt;/code&gt; will work.&lt;/p&gt;
&lt;p&gt;Guess what - when I've check it today on my computer it failed :( That's why I decided to write about this so everyone that will find this issue will know what to do :)&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;You should have a fully remove docker.io from your system.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/moby/moby/issues/30517"&gt;nuke-graph-directory no shopt builtin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.launchpad.net/ubuntu/+source/docker.io/+bug/1724353"&gt;Problem on ubuntu launchpad bug-tracker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="30daychallenge-S0"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="docker"></category><category term="docker-engine"></category></entry><entry><title>How to upgrade docker engine to latest distribution without breaking any containers</title><link href="http://witkowskibartosz.com/blog/how-to-upgrade-docker-engine-to-latest-distribution.html" rel="alternate"></link><published>2018-02-06T20:20:00+01:00</published><updated>2018-02-06T20:20:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-06:/blog/how-to-upgrade-docker-engine-to-latest-distribution.html</id><summary type="html">&lt;p&gt;Do you want to use latest version of docker engine but your *unix distribution does support it yet in packages ? There are solutions for that matter. Check it out :)&lt;/p&gt;</summary><content type="html">&lt;p&gt;S0-E4/E30 :)&lt;/p&gt;
&lt;p&gt;&lt;img alt="docker-icon" src="images/docker.png"&gt;&lt;/p&gt;
&lt;h1&gt;Prerequisites&lt;/h1&gt;
&lt;p&gt;First check from which repository you have installed your docker.&lt;/p&gt;
&lt;p&gt;In my case it was &lt;code&gt;docker.io&lt;/code&gt; with &lt;code&gt;apt-get install docker.io&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Check with command: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt list &lt;span class="p"&gt;|&lt;/span&gt; egrep -i &lt;span class="s2"&gt;&amp;quot;docker&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; egrep -i &lt;span class="s2"&gt;&amp;quot;installed&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This will list you all packages you have installed named "docker" and that have "installed" information.
Something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;WARNING: apt does not have a stable CLI interface yet. Use with caution in scripts.

docker/trusty-updates,now &lt;span class="m"&gt;1&lt;/span&gt;.5-1 amd64 &lt;span class="o"&gt;[&lt;/span&gt;installed&lt;span class="o"&gt;]&lt;/span&gt;
docker.io/trusty-updates,now &lt;span class="m"&gt;1&lt;/span&gt;.6.2~dfsg1-1ubuntu4~14.04.1 amd64 &lt;span class="o"&gt;[&lt;/span&gt;installed&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;BTW - you can ignore the warning for this command - because we only checked which packages are installed, not performing actual installing via &lt;code&gt;apt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you see something different then &lt;code&gt;docker-ce&lt;/code&gt; or &lt;code&gt;docker-ee&lt;/code&gt; - then it means you have an older version like &lt;code&gt;docker.io&lt;/code&gt; / &lt;code&gt;docker-engine&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That means - You classified to be upgraded ! :)&lt;/p&gt;
&lt;h1&gt;Manual upgrade with aptitude.&lt;/h1&gt;
&lt;p&gt;First make update on packages:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get update
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then purge packages that are old:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get purge -y docker.io docker-engine
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then install latest docker (EE - Enterprice Edition, CE- Community Edition) : docker-ce /docker-ee:
! WARNING - please be careful - you should change the "ubuntu-trusty" to your distribution name.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;curl -fsSL https://download.docker.com/linux/ubuntu/gpg &lt;span class="p"&gt;|&lt;/span&gt; sudo apt-key add -
sudo apt-add-repository &lt;span class="s1"&gt;&amp;#39;deb https://apt.dockerproject.org/repo ubuntu-trusty main&amp;#39;&lt;/span&gt;
sudo apt-get update
sudo apt-get install -y docker-ce
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Upgrade using docker-machine&lt;/h1&gt;
&lt;p&gt;If you have used docker-machine and created a Virtual Host, than you can just type:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker-machine upgrade default
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;where "default" is the name of your machine config.&lt;/p&gt;
&lt;p&gt;BTW - you actually can use docker-machine to manage an physical machine with docker installed &lt;a href="https://github.com/docker/machine/issues/3212"&gt;Check this issue on docker-machine repository&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;You should have a fully working docker with latest engine and now be able to use commands like i.e. "docker network"&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://askubuntu.com/a/473720"&gt;How Do i upgrade Docker - comment by Larry Cai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://askubuntu.com/questions/17823/how-to-list-all-installed-packages"&gt;apt - How to list all installed packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/machine/reference/upgrade/"&gt;docker-machine upgrade on docker.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="30daychallenge-S0"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="docker"></category><category term="docker-engine"></category></entry><entry><title>How to create your Selenium Tests with PhantomJS browser integration</title><link href="http://witkowskibartosz.com/blog/how-to-create-your-selenium-tests-with-phantomjs.html" rel="alternate"></link><published>2018-02-05T23:50:00+01:00</published><updated>2018-02-05T23:50:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-05:/blog/how-to-create-your-selenium-tests-with-phantomjs.html</id><summary type="html">&lt;p&gt;Have you created your selenium tests ? You did? And you have created more then one test? Did you know, that you can get them to run faster? Just use PhantomJS! Wait... what? Javascript technology in Python stack?! YEAH! With docker you can combine them without having to use npm and other !&lt;/p&gt;</summary><content type="html">&lt;p&gt;S0-E3/E30 :)&lt;/p&gt;
&lt;p&gt;Did you created your selenium grid tests ? Did you know, that you can get them to run faster? Just use PhantomJS! Wait... what? NodeJS technology in Python stack?! YEAH! With docker you can combine them!&lt;/p&gt;
&lt;h1&gt;PhantomJS.&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://phantomjs.org/"&gt;PhantomJS&lt;/a&gt; is a Javascript Headless browser that at least theoretically should run faster then Firefox.&lt;/p&gt;
&lt;p&gt;This article is connected with &lt;a href="how-to-create-your-first-selenium-grid-compatible-test.html"&gt;How-To-Create-Your-Selenium-Grid-Compatible-Test&lt;/a&gt; - check it out :)&lt;/p&gt;
&lt;h1&gt;How to run your PhantomJS&lt;/h1&gt;
&lt;p&gt;Using docker you can just:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run -d -p &lt;span class="m"&gt;8910&lt;/span&gt;:8910 wernight/phantomjs phantomjs --webdriver&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8910&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Your testcase.&lt;/h1&gt;
&lt;p&gt;And here is what I thought will be a simple integration with Selenium Grid. Then I've found it does not have proper connector to Selenium Grid (eh...).
Moreover I've found it has problems with making "send_keys" because of some strange dependency problems that you can find on stackoverflow (problem exists I've check it, before I found those SO pages):
- &lt;a href="https://stackoverflow.com/questions/17800573/selenium-phantomjs-send-keys-doesnt-work?noredirect=1&amp;amp;lq=1"&gt;here&lt;/a&gt;
- &lt;a href="https://stackoverflow.com/questions/41716339/selenium-phantomjs-can-not-send-keys-to-input-typeerror-undefined-is-not-a-f?noredirect=1&amp;amp;lq=1"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So what can we do? &lt;/p&gt;
&lt;p&gt;Well here's what I've been able to make with a not-fully working python api to remote PhantomJS :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.common.desired_capabilities&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DesiredCapabilities&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PhantomJSTests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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;test_search_in_python_org&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="c1"&gt;# this test will not work on PhantomJS since it has a in-compatible API :(&lt;/span&gt;
        &lt;span class="c1"&gt;# instead we need to create a simulation for that&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://github.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;GitHub&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_element_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;q&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# send_keys does not work on phantomjs - there are some strange workarounds but in my limited time I could not get them to work.&lt;/span&gt;
        &lt;span class="c1"&gt;# I will however make a follow up on this!&lt;/span&gt;
        &lt;span class="c1"&gt;# elem.send_keys(&amp;quot;anselmos&amp;quot;)&lt;/span&gt;
        &lt;span class="c1"&gt;# time.sleep(5)&lt;/span&gt;
        &lt;span class="c1"&gt;# elem.send_keys(Keys.ENTER)&lt;/span&gt;
        &lt;span class="c1"&gt;# time.sleep(5)&lt;/span&gt;
        &lt;span class="c1"&gt;# assert &amp;quot;No results found.&amp;quot; not in driver.page_source&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;command_executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://127.0.0.1:8910&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;desired_capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DesiredCapabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PHANTOMJS&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;OR download it from &lt;a href="examples/selenium/phantomjs_test_case.py"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Is there any other solutions to this ?&lt;/h1&gt;
&lt;p&gt;Well.... yeah. You can either recompile PhantomJS (by using different branch named " backport-ghostdriver-2-0-to-phantomjs-2-1 " and then using command &lt;code&gt;docker run -v $PWD:/src debian:wheezy /src/deploy/docker-build.sh&lt;/code&gt; as suggested &lt;a href="https://github.com/ariya/phantomjs/issues/14211#issuecomment-326546187"&gt;on github issue page in this comment by jesg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Wait until someone will fix PhantomJS (that is apparently untill 2.5 -btw current ver. is 2.1.3 ... )&lt;/p&gt;
&lt;p&gt;Or... use a Javascript API instead as described &lt;a href="https://stackoverflow.com/a/13933894"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this episode as much as I did :)&lt;/p&gt;
&lt;p&gt;BTW I will do a follow up on problems with PhantomJS - and will give you feedback if there are any other solutions to the problem :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="selenium"></category><category term="automatization"></category><category term="testing-automation"></category><category term="30daychallenge-S0"></category><category term="phantomjs"></category><category term="selenium-with-phantomjs"></category></entry><entry><title>How to create your first Selenium Grid Compatible Test</title><link href="http://witkowskibartosz.com/blog/how-to-create-your-first-selenium-grid-compatible-test.html" rel="alternate"></link><published>2018-02-04T17:10:00+01:00</published><updated>2018-02-04T17:10:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-04:/blog/how-to-create-your-first-selenium-grid-compatible-test.html</id><summary type="html">&lt;p&gt;How do you start your first Selenium Grid Test? Yesterday I've given you instructions how to create your Selenium Grid environment. Today I'll focus on how to create your first test that will use this env. Check it Out!&lt;/p&gt;</summary><content type="html">&lt;p&gt;S0-E2/E30 :)&lt;/p&gt;
&lt;p&gt;How do you start your first Selenium Grid Test? Yesterday I've given you instructions how to create your Selenium Grid environment. Today I'll focus on how to create your first test that will use this env. Check it Out!&lt;/p&gt;
&lt;h1&gt;Selenium Grid.&lt;/h1&gt;
&lt;p&gt;This article is connected with &lt;a href="how-to-start-with-selenium-grid.html"&gt;How-To-Start-With-Selenium-Grid&lt;/a&gt; - check it out how to create your Selenium Grid Environment :)&lt;/p&gt;
&lt;h1&gt;Your First testcase.&lt;/h1&gt;
&lt;p&gt;What to start with? You can start with your own Selenium Test and change it into Selenium Grid one :)&lt;/p&gt;
&lt;p&gt;Let's check this example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.common.keys&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Keys&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PythonOrgSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Firefox&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;test_search_in_python_org&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;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://github.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;GitHub&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_element_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;q&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;anselmos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RETURN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;No results found.&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tearDown&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;OR download it from &lt;a href="examples/selenium/your-non-selenium-grid-test.py"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While I tried to run this on my machine, I've used pip to install selenium, then I've found a problem :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="na"&gt;.env&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;local&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;python2.7&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;site-packages&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;selenium&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;webdriver&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;common&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;service.py&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;83&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;in&lt;/span&gt; &lt;span class="no"&gt;start&lt;/span&gt;
    &lt;span class="nf"&gt;os.path.basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;self.path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;self.start_error_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nl"&gt;WebDriverException:&lt;/span&gt; &lt;span class="nl"&gt;Message:&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nf"&gt;geckodriver&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt; &lt;span class="no"&gt;executable&lt;/span&gt; &lt;span class="no"&gt;needs&lt;/span&gt; &lt;span class="no"&gt;to&lt;/span&gt; &lt;span class="no"&gt;be&lt;/span&gt; &lt;span class="no"&gt;in&lt;/span&gt; &lt;span class="no"&gt;PATH.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To fix this issue you have to :&lt;/p&gt;
&lt;h3&gt;1. Download a geckodriver from &lt;a href="https://github.com/mozilla/geckodriver/releases"&gt;here&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As I'm using an x64 bit Linux, I chose geckodriver-v0.19.1-linux64.tar.gz and downloaded it with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;wget https://github.com/mozilla/geckodriver/releases/download/v0.19.1/geckodriver-v0.19.1-linux64.tar.gz
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then ungzip it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;tar -zxvf geckodriver-v0.19.1-linux64.tar.gz
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And moved into path which is executable: (Warning - you'll need root's permissions to move to /usr path)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;mv geckodriver /usr/local/bin/
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And then I could finally run the script with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;python your-non-selenium-grid-test.py
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now to make this Test run on our Selenium Grid, just change the "driver" in script with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;command_executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://127.0.0.1:4444/wd/hub&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;desired_capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;browserName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;firefox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;javascriptEnabled&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final Result - A working example of Selenium Grid Test&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.common.keys&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Keys&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PythonOrgSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;command_executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://127.0.0.1:4444/wd/hub&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;desired_capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;browserName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;firefox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;javascriptEnabled&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&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;test_search_in_python_org&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;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://github.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;GitHub&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_element_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;q&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;anselmos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RETURN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;No results found.&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tearDown&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can download it also from &lt;a href="examples/selenium/your-selenium-grid-compatible-test.py"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Execution on more than one node!&lt;/h1&gt;
&lt;p&gt;If you need to have more than one selenium-node type (besides Firefox), you can customize the script with the following:&lt;/p&gt;
&lt;p&gt;First, create a generalized Unittest that will have only test-cases.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.common.keys&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Keys&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenericSeleniumTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&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&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_search_in_python_org&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="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://github.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;GitHub&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_element_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;q&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;anselmos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RETURN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;No results found.&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tearDown&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="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FirefoxTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GenericSeleniumTest&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&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;command_executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://127.0.0.1:4444/wd/hub&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;desired_capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;browserName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;firefox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;javascriptEnabled&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChromeTests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GenericSeleniumTest&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&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;command_executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://127.0.0.1:4444/wd/hub&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;desired_capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;browserName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;chrome&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;javascriptEnabled&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And that's it! You have a fully working and customizable Tests. You can now extend Generalized tests that will be run on each platform or perform a specific test designed only for Firefox or Chrome.&lt;/p&gt;
&lt;h1&gt;Acknowledgement&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/40388503/how-to-put-geckodriver-into-path"&gt;StackoverFlow- How to put geckodriver into PATH?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/dzitkowskik/0fc641cf59af0dc3de62"&gt;A simple tutorial of using selenium grid in python unittests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this episode as much as I did :)&lt;/p&gt;
&lt;p&gt;BTW: I have something extra for you - since I've used yesterdays commands, I created a simpler script for non-network compatible docker-engines that creates a selenium grid out of the box &lt;a href="examples/selenium/run_selenium_grid.sh"&gt;Check it Here &lt;/a&gt;
(Only for security reasons I'm putting Md5Sum of this file: 7531d8a83d2f9344a752b203e8e1198c run_selenium_grid.sh ) :)&lt;/p&gt;
&lt;p&gt;If you have any suggestions what I should blog about in the next articles - please give me a hint :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="selenium"></category><category term="seleniumgrid"></category><category term="grid"></category><category term="automatization"></category><category term="testing-automation"></category><category term="selenium-grid-compatible-test"></category><category term="30daychallenge-S0"></category></entry><entry><title>How to start with Selenium Grid ? Step by Step.</title><link href="http://witkowskibartosz.com/blog/how-to-start-with-selenium-grid.html" rel="alternate"></link><published>2018-02-03T22:30:00+01:00</published><updated>2018-02-03T22:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-02-03:/blog/how-to-start-with-selenium-grid.html</id><summary type="html">&lt;p&gt;How do you start with selenium grid? From scratch ? When you have no idea of what that is ? Today I'm going to give you answers to that questions! Check it out and share if you liked it !&lt;/p&gt;</summary><content type="html">&lt;p&gt;Day 1 out of 30 :)&lt;/p&gt;
&lt;p&gt;How do you start with selenium grid? From scratch ? When you have no idea of what that is ? Today I'm going to give you answers to that questions! Check it out and share if you liked it !&lt;/p&gt;
&lt;h1&gt;What Selenium Grid is, and what is not ?&lt;/h1&gt;
&lt;p&gt;For sure is not a silver lining for automation. And for sure Selenium Grid for beginner is not a simple solution.&lt;/p&gt;
&lt;p&gt;That's why I create this blog post - for others to start using it with simpler step-by-step guides :)&lt;/p&gt;
&lt;p&gt;Selenium Grid is a type of server, that you can use for making Selenium Automation Testing without having a &lt;a href="https://en.wikipedia.org/wiki/Graphical_user_interface"&gt;GUI&lt;/a&gt; - so for typical server-type computer.&lt;/p&gt;
&lt;p&gt;Selenium Grid has it's potential to make a better testing environment - because you can plug-and-play using docker and then plug it to some type of &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration"&gt;CI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In that way - you can fully combine your web-automation testing into your CI environment.&lt;/p&gt;
&lt;h1&gt;What Selenium Grid is made of ?&lt;/h1&gt;
&lt;p&gt;Selenium Grid consists of Hub and Nodes.&lt;/p&gt;
&lt;p&gt;Hub is the Central point to which you send commands about your tests.&lt;/p&gt;
&lt;p&gt;Nodes are just regular workers &lt;img alt="Like a regular programmer" src="images/programmer_only_god_understand_what_you_created.jpg"&gt; - you push your tests via Hub to them. Nodes can be a of a different type - for example a Firefox Browser Node, or a Mozilla Google Browser Node.&lt;/p&gt;
&lt;h1&gt;How to start Selenium Grid?&lt;/h1&gt;
&lt;p&gt;For start, install docker &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04"&gt;Installation Tips from DigitalOcean for Ubuntu 16.04&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then It's pretty easy to make a Selenium Hub with Nodes. Just follow this instructions &lt;a href="https://github.com/SeleniumHQ/docker-selenium"&gt;Here is link to gh-source for documentation&lt;/a&gt;:&lt;/p&gt;
&lt;h3&gt;Create a docker-internal network&lt;/h3&gt;
&lt;p&gt;Creating for nodes and hub to easier recognize themselves via network:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker network create grid
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Warning - if you have problems with docker network command&lt;/h2&gt;
&lt;p&gt;You should check whether your docker-engine version is of 1.22 API - how ? &lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker version&lt;/code&gt;
Example :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Server API version: 1.18&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Mine unfortunatelly has a 1.18 :( so I'm stuck with no-docker-network)&lt;/p&gt;
&lt;p&gt;You can also check &lt;a href="https://docs.docker.com/engine/api/v1.29/#section/Versioning"&gt;Docker Engine Versions&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Create a Hub (including docker network)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run -d -p 4444:4444 --net grid --name selenium-hub selenium/hub:3.8.1-francium
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Create a Hub ( without docker network):&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run -d -p 4444:4444 --name selenium-hub selenium/hub:3.8.1-francium
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now you can also check whether a hub has started it's job, by checking:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker logs selenium-hub 
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you see something like :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;- Selenium Grid hub is up and running&lt;/code&gt; as a last line from log - that it means you have successfully created a working Selenium Hub ! :)&lt;/p&gt;
&lt;h3&gt;Create Nodes (including docker network)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-chrome:3.8.1-francium
docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-firefox:3.8.1-francium
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Create Nodes (without docker network)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run -d --link selenium-hub:hub --name selenium-node-chrome -v /dev/shm:/dev/shm selenium/node-chrome:3.8.1-francium
docker run -d --link selenium-hub:hub --name selenium-node-firefox -v /dev/shm:/dev/shm selenium/node-firefox:3.8.1-francium
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you can see from:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker logs selenium-node-chrome
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;06.319&lt;/span&gt; &lt;span class="n"&gt;INFO&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Selenium&lt;/span&gt; &lt;span class="n"&gt;Grid&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;
&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;06.324&lt;/span&gt; &lt;span class="n"&gt;INFO&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Starting&lt;/span&gt; &lt;span class="n"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;registration&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Will&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt; &lt;span class="n"&gt;every&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt; &lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;06.325&lt;/span&gt; &lt;span class="n"&gt;INFO&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Registering&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="mf"&gt;172.17&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4444&lt;/span&gt;&lt;span class="sr"&gt;/grid/&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;
&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;06.377&lt;/span&gt; &lt;span class="n"&gt;INFO&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;registered&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Than it means you have successfully registered a Selenium Node ! Which means you have successfully created a Selenium Grid Stack from which you can create your automated tests within CI :)&lt;/p&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment, share or don't :)&lt;/p&gt;
&lt;p&gt;BTW : I have a Todoist redeem code for anyone how will give me a good idea for next article :)&lt;/p&gt;
&lt;p&gt;BTW! This post is inspired by &lt;a href="https://www.youtube.com/watch?v=7CPtT7nMI-w"&gt;MiroBurn VLog S3E34&lt;/a&gt; ! Totally out of the blue I've decided to accept his challenge of 30-days contributing to society(in my version it's a 30 days of posting an article for blog).&lt;/p&gt;
&lt;p&gt;Keep Finger crossed for me :)&lt;/p&gt;
&lt;p&gt;See you tomorrow! Cheers!&lt;/p&gt;</content><category term="30daychallenge"></category><category term="miroburn"></category><category term="miroburn_challenge"></category><category term="selenium"></category><category term="seleniumgrid"></category><category term="grid"></category><category term="automatization"></category><category term="testing-automation"></category><category term="30daychallenge-S0"></category></entry><entry><title>How to start New 2018 Year?</title><link href="http://witkowskibartosz.com/blog/how-to-start-new-2018-year.html" rel="alternate"></link><published>2018-01-11T07:00:00+01:00</published><updated>2018-01-11T07:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2018-01-11:/blog/how-to-start-new-2018-year.html</id><summary type="html">&lt;p&gt;How to start New 2018 Year ? Is there any advice that you could get about making your new-years todo-list ?&lt;/p&gt;</summary><content type="html">&lt;p&gt;Before we begin with how to start new year, let me summarize 2017:&lt;/p&gt;
&lt;h1&gt;Summarizing 2017&lt;/h1&gt;
&lt;p&gt;It's been a long journey for me to get back to blogging. Since the last article was published, I have found billions of excuses not to blog, and other excuses not to make any progress with my BikingEndorphines project :(&lt;/p&gt;
&lt;p&gt;As the result of that, I did not complete project in a beta-phase.&lt;/p&gt;
&lt;p&gt;That's about failures.... - there was more failures, but is there any sunshine out-there?&lt;/p&gt;
&lt;p&gt;Yes! I'm writing this article! That's a huge step to get back with my unfinished businesses.&lt;/p&gt;
&lt;p&gt;What else ... Let's summarize 2017 in 10 brief points:&lt;/p&gt;
&lt;h5&gt;1. Challenged myself to create this blog and post in a DSP competition articles about BikingEndorphines project&lt;/h5&gt;
&lt;h5&gt;2. Finally broke the ice with flying tourist jets.&lt;/h5&gt;
&lt;h5&gt;3. Came back to driving a car - something that I did not anticipate myself that would be possible.&lt;/h5&gt;
&lt;h5&gt;4. Started Master-Mind sessions with my 2 friends - Special thanks for @Wojciech&lt;/h5&gt;
&lt;h5&gt;5. Went to conferences- which embraced my ambitions.&lt;/h5&gt;
&lt;h5&gt;6. Came-back to drawing on paper&lt;/h5&gt;
&lt;h5&gt;7. Decided it was time to change my employer.&lt;/h5&gt;
&lt;h5&gt;8. Started early morning routines (waking up at 5 am or earlier).&lt;/h5&gt;
&lt;h5&gt;9. Successfully completed Associate Android Developer course by Udacity, certified by Google (https://developers.google.com/training/certification/associate-android-developer/)&lt;/h5&gt;
&lt;h5&gt;10. Finally decided to buy a better phone to be more mobile.&lt;/h5&gt;
&lt;h1&gt;So... How to start New Year?&lt;/h1&gt;
&lt;p&gt;How about from... Happy New Year! :)&lt;/p&gt;
&lt;p&gt;But ehm.... seriously ?&lt;/p&gt;
&lt;p&gt;Everyone has made their commitments for this year. If you did not, you are the lucky sailor above this challenges.&lt;/p&gt;
&lt;p&gt;I also made my commitments. This time I've finally used "3 layers" or "3 Poziomy" (in polish lang) to keep my goals real and more achievable ( you can check out about "3 poziomy" https://trzypoziomy.pl/zadania/ ).&lt;/p&gt;
&lt;p&gt;But how can you change your new year and be more of yourself in this year?&lt;/p&gt;
&lt;p&gt;Let's ask yourself a few questions that may lead you to the path you were looking for, shall we?&lt;/p&gt;
&lt;p&gt;First of all, let's start with a big one - where do you see yourself in 5 years?&lt;/p&gt;
&lt;p&gt;That's the question I've been asked year by year on a "yearly work employee reviews" - of course, it had work-related context, but let's think about this in a bit more comprehensive way.&lt;/p&gt;
&lt;p&gt;Let's for example assume that in past you have wonder how it would be to become a great piano artist. Maybe you thought about taking that piano lessons but since you think there is no time for that, you did not even started?&lt;/p&gt;
&lt;p&gt;For this example, let's remove money from the equation. Let's focus only on time needed to master in a beginning level piano playing.&lt;/p&gt;
&lt;p&gt;Learning how to play a piano needs - that's my imagination - 100hours.&lt;/p&gt;
&lt;p&gt;If you are working/walking to school and sleeping regularly, it takes about 16 hours in average. Add time needed for transport and preparation to work/school and you are left with about 4-5 hours of free time that you can spend on anything you want.&lt;/p&gt;
&lt;h1&gt;Sky is the limit, right ?&lt;/h1&gt;
&lt;p&gt;Yes and no. The only one that divides you from winning is yourself and your motivations. But let's come back to our calculations.&lt;/p&gt;
&lt;p&gt;Let's assume that you want to spend at least 1 hour a day for relax - i.e. playing games/reading books/watching movies/tv-series. That means you have about 4 hours of free time per work day that you could spend on something productive and/or for expending your relations with others.&lt;/p&gt;
&lt;p&gt;If you want to spend 1 hour per day for learning how to play piano, you would need :&lt;/p&gt;
&lt;p&gt;100h / 5 hours per week = 20 weeks = approx. 5 months.&lt;/p&gt;
&lt;p&gt;That's less then half year! (Remember - &lt;a href="https://en.wikipedia.org/wiki/Is_the_glass_half_empty_or_half_full%3F"&gt;half-full glass of water&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;Think, what you could do with second half of the year ? :-)&lt;/p&gt;
&lt;h1&gt;My 2018 plans?&lt;/h1&gt;
&lt;p&gt;I you wonder what are my plans(especially connected with blog-context):&lt;/p&gt;
&lt;h5&gt;1. Blogging at least twice per month&lt;/h5&gt;
&lt;h5&gt;2. Focus on my BikingEndorphines project&lt;/h5&gt;
&lt;h5&gt;3. Change deployment system of new articles to blog into more mobile way&lt;/h5&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;That's it :) Comment and share if you liked this article.&lt;/p&gt;
&lt;p&gt;BTW : I'd appreciate any suggestions about next articles.&lt;/p&gt;
&lt;p&gt;PS Next time there will be a more technical stuff :) but Ciiiiiii - no-one needs to know :-)&lt;/p&gt;
&lt;p&gt;See you! Cheers :)&lt;/p&gt;</content><category term="blog"></category><category term="motivational"></category><category term="3poziomypl"></category><category term="plans"></category></entry><entry><title>How to use Stack Hive?</title><link href="http://witkowskibartosz.com/blog/how-to-use-stack-hive.html" rel="alternate"></link><published>2017-08-16T21:30:00+02:00</published><updated>2017-08-16T21:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-08-16:/blog/how-to-use-stack-hive.html</id><summary type="html">&lt;p&gt;This time we will talk about using Stack Hive for designing your own web-based project!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;--EDIT 28-02-2018 Stackhive Deprecated!&lt;/h1&gt;
&lt;p&gt;From 1.03.2018 StackHive is no longer available. Informations below does not apply anymore :(&lt;/p&gt;
&lt;h1&gt;About StackHive&lt;/h1&gt;
&lt;p&gt;In the last article, we talked about how to use some online-designing tools that could help out-of-the-box to design your own website/product.&lt;/p&gt;
&lt;p&gt;I've picked StackHive to check it's abilities to create a dynamic web page with a source-code visible with a "WYSIWYG" editor-type.&lt;/p&gt;
&lt;p&gt;Now I have one warning for those not familiar with this product - You will probably need to wait at least few days (in my case it was about 3 days) till my account was fully activated and I could use their interface to make changes in projects.&lt;/p&gt;
&lt;p&gt;By default account you create will be a free-type and you can use it for creating max 3 projects with the ability to edition and exporting.&lt;/p&gt;
&lt;p&gt;There may be other repercussions (that some features may not work in the free-account type) but I do hope that most of the features I'll be using will work :)&lt;/p&gt;
&lt;p&gt;Enough chit-chat - let's go with our initial project.&lt;/p&gt;
&lt;h1&gt;First project in StackHive.&lt;/h1&gt;
&lt;p&gt;After making an account, you can "Create your project" by clicking one of 3 options : 
- "Start a project with our templates"
- "Upload your own code via zip"
- "Pull from live website"&lt;/p&gt;
&lt;p&gt;For now, I only used the first option. Just for this post I"ve started the third option to check if it will download my blog website for the edition.&lt;/p&gt;
&lt;h3&gt;Choosing project from templates&lt;/h3&gt;
&lt;p&gt;You can use free-templates within free-account. There are (at least I suppose) non-free templates that may be more advanced - out of the box.&lt;/p&gt;
&lt;p&gt;Let's assume you picked a "Blog Template" or any other template.&lt;/p&gt;
&lt;p&gt;Now at the "Manage Projects" section, you will find your projects that either you imported or created from a template.&lt;/p&gt;
&lt;p&gt;I used my 3 free projects, the first project is for testing importing my blog for checking the "Pull from live website" - I must admit it works pretty great for a static-generated blog.&lt;/p&gt;
&lt;p&gt;Other 2 projects are my new-template based projects. &lt;/p&gt;
&lt;p&gt;Going back to the business - you can either "View Project", "Edit Project" or click the "trash-bin" icon to remove the project, once you move the cursor on the project.&lt;/p&gt;
&lt;p&gt;Let's see what editor can do for us :)&lt;/p&gt;
&lt;h1&gt;StackHive Editor!&lt;/h1&gt;
&lt;p&gt;&lt;img alt="StackHive Editor" src="images/stackhive_editor.png"&gt;&lt;/p&gt;
&lt;p&gt;As you may see now, the editor has a cool option. You have the ability to "Preview" your "work-in-progress" site, to check how it will look on a different type of devices i.e. Tablet/ Phone/ HD Desktop. It also includes the Portrait and Landscape mode.&lt;/p&gt;
&lt;p&gt;Also, there is the "Plus" sign with "Create" name, that gives the possibility to add new elements to the website.&lt;/p&gt;
&lt;p&gt;This element comes with filtering, just as in other graphical editors.&lt;/p&gt;
&lt;p&gt;I particularly searched for "list" and 3 elements returned "List", "ListItem" and "Navigation List"&lt;/p&gt;
&lt;h1&gt;Images and uploading&lt;/h1&gt;
&lt;p&gt;In this fantastic editor, you can change and upload your own images that can be put anywhere in the project.&lt;/p&gt;
&lt;h1&gt;Publishing the website (staging/production)&lt;/h1&gt;
&lt;p&gt;A great thing that you can also check is an option to publish your own live version of the site you were working on.&lt;/p&gt;
&lt;p&gt;Just click at Manager (at the left site) and then the "Stack" icon. Then you will be able to choose from a subdomain of "stackhive.com" for free or at your own custom domain (that you paid).&lt;/p&gt;
&lt;p&gt;WOW - that was my impression after using it! After making some changes in the theme, I've gone to the "Publish" options and clicked "Push" - it immediately pushed changes I've made into the subdomain.&lt;/p&gt;
&lt;p&gt;You may check my initial and very drafty version of the site here:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bikingendorphines.stackhive.com"&gt;BikingEndorphines-On-StackHive&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;BTW - Great support from StackHive service technicians!&lt;/h1&gt;
&lt;p&gt;At the middle of writing of this article, I could not use the service, because of some domain problem.&lt;/p&gt;
&lt;p&gt;Fortunately, after reaching out to StackHive on Facebook, after only an hour, the problem was solved - thanks again!&lt;/p&gt;
&lt;h1&gt;Comment and share :)&lt;/h1&gt;
&lt;p&gt;Afterall (I've changed the publish date few times) - StackHive looks like a very intuitive site for building sites! I will definitely use it in the future.&lt;/p&gt;
&lt;p&gt;I'd love to hear an opinion from you! Would you use StackHive?&lt;/p&gt;
&lt;p&gt;What other online-design tools you use?&lt;/p&gt;
&lt;p&gt;Thanks and see you soon! &lt;/p&gt;</content><category term="biking-endorphines"></category><category term="stackhive"></category><category term="how-to-use-stack-hive"></category><category term="how-to"></category><category term="online-web-design-tools"></category></entry><entry><title>Designing Biking Endorphines - what went wrong?</title><link href="http://witkowskibartosz.com/blog/designing-biking-endorphines.html" rel="alternate"></link><published>2017-08-04T20:00:00+02:00</published><updated>2017-08-04T20:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-08-04:/blog/designing-biking-endorphines.html</id><summary type="html">&lt;p&gt;Lately I've found out why I don't make any effective progress on B-Endorphines project. Come with me on this journey where we will discover some potential problems that you too may have struggled.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Original Design&lt;/h1&gt;
&lt;p&gt;Initially I did not have any design at all. I just planned my work few steps ahead for development. &lt;/p&gt;
&lt;p&gt;I didn't realize untill lately, that I did a terrible thing - I didn't have an idea of how "almost finished" product will look like with Biking Endorphines project.&lt;/p&gt;
&lt;p&gt;Fortunatelly for me, my colleagues from our "MasterMind" group gave me a great feedback about that - Thanks &lt;a href="http://blog.geekydevs.com/"&gt;@Grzegorz&lt;/a&gt; and &lt;a href="http://www.codinghappiness.com/"&gt;@Wojtek&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I gave too much effort and was focused almost 100% on the code instead of the product itself.&lt;/p&gt;
&lt;p&gt;That's why I've decided to cross-out all the plans I had and start almost from begining with designing web-based application.&lt;/p&gt;
&lt;p&gt;In that situation I will know where the work needs to go (the path I'm leading it) and know how much there is left to do.&lt;/p&gt;
&lt;p&gt;And then I can focus on the REST-API and Android APP. (which btw will also need to be designed first)&lt;/p&gt;
&lt;h1&gt;Web Design tools/services&lt;/h1&gt;
&lt;p&gt;A part of me didn't want to do this in an online-tool. Instead I'd prefer to make a drawing by hand sketch.&lt;/p&gt;
&lt;p&gt;But online and the "software" tools have a lot of things already prepared for job I want to do that it would not be productive - it would be a bit of wasting time on sketching.&lt;/p&gt;
&lt;p&gt;I will probably do some hand-sketching after-all just as a POF- but for now let's focus on what the Web has for us.&lt;/p&gt;
&lt;p&gt;Tools &amp;amp; Services I've found for making web design:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This is a recurring one from Tim Ferris - &lt;a href="https://99designs.com"&gt;"99designs.com"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bootstrapstudio.io/"&gt;The Bootstrap Studio&lt;/a&gt; - not free - when I've checkout it out- it was about 25$ for a "lifetime" offline licence.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stackhive.com/"&gt;StackHive&lt;/a&gt; - online web-based application for making designs of web-application. What is great about this app- it has a "free" plan in which you have 2 projects available. Also this application allows you to export your project and have it used elsewhere.&lt;/li&gt;
&lt;li&gt;Tools like &lt;a href="https://www.weebly.com/"&gt;Weebly&lt;/a&gt;, &lt;a href="http://www.webs.com/"&gt;Webs.com&lt;/a&gt;  - where you probably don't have access to files you created - platform provides included hosting of web-site created in online-creator&lt;/li&gt;
&lt;li&gt;Much more, checkout : &lt;a href="http://alternativeto.net/software/bootstrap-studio/?license=free"&gt;AlternativeToLink Of BootstrapStudio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;B-Endorphines Web Design&lt;/h1&gt;
&lt;p&gt;Well it's a tough decision, but for now I'll probably stick with the "StackHive" - to checkout they're free-plan. If this will not work-out as I would want to, I might even think about buying the "Bootstrap Studio" - based on their demo it looks also promising.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.stackhive.com/"&gt;&lt;img alt="StackHive" src="images/stackhive_logo.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Biking Endorphines design will contain elements such as:&lt;/p&gt;
&lt;h4&gt;1. Login Page&lt;/h4&gt;
&lt;h4&gt;2. Demo site page where the diagrams and functionality is presented.&lt;/h4&gt;
&lt;h4&gt;3. Biking Statistics page sorted by day/week/month/year and even by route-location-points, that you could filter.&lt;/h4&gt;
&lt;h4&gt;4. Biking Endorphines Badges Acquired page that will contain all the Badges user gathered (when logged-in) and information which badges are yet to be discovered (some of them will be hidden).&lt;/h4&gt;
&lt;p&gt;And so I've created account on "StackHive" and choosed template called "Pratt Theme".&lt;/p&gt;
&lt;p&gt;It looks like after creating a new project in "StackHive" (from template) it needs to be loaded within some type of a Queue as the message follows: "Please wait while we load your website".&lt;/p&gt;
&lt;p&gt;As I'm currently in a bus using my 3G internet - if the "loading" is not on the server site, but on the client site, it will take a bit longer than I thought.&lt;/p&gt;
&lt;p&gt;Well it looks like for the final thoughts about "StackHive" you will need to wait till next article.&lt;/p&gt;
&lt;h1&gt;Making commitment to stage project into steps&lt;/h1&gt;
&lt;p&gt;That's the next thing I need to do. I need to stage all the steps and user-stories into plan and then start by making these steps as easy to achive as possible. &lt;/p&gt;
&lt;p&gt;First "chunk" of story was to create this article with information about designing B-Endorophines project.&lt;/p&gt;
&lt;p&gt;Then I will need to re-think if using Github Issues was such a great idea.&lt;/p&gt;
&lt;p&gt;I might even think about moving into some other platform after-all. We will see.&lt;/p&gt;
&lt;p&gt;I will for sure make list of the features splitted into as small "chunks" as possible and setup this as my tasks per day/week/month.&lt;/p&gt;
&lt;h1&gt;Thanks for reading!&lt;/h1&gt;
&lt;p&gt;Thanks for reading! Please stay tuned - I will make next article about using "StackHive" :)&lt;/p&gt;
&lt;p&gt;Please share and comment in the box bellow :) Till next time!&lt;/p&gt;</content><category term="biking-endorphines"></category><category term="design"></category><category term="stackhive"></category><category term="bootstrap-studio"></category></entry><entry><title>Web Clicking Automation using Selenium IDE test recording</title><link href="http://witkowskibartosz.com/blog/web-clicking-automation-using-selenium-ide-test-recording.html" rel="alternate"></link><published>2017-07-27T22:20:00+02:00</published><updated>2017-07-27T22:20:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-07-27:/blog/web-clicking-automation-using-selenium-ide-test-recording.html</id><summary type="html">&lt;p&gt;Did you ever wished to automate your web-clicks? Me too! This time it's more than possible - it's really easy with Selenium IDE test recording!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Selenium IDE for those in hurry.&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://www.seleniumhq.org/"&gt;&lt;img alt="Selenium" src="images/selenium_big_logo.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Have you got into a situation where you had to test your latest development feature manually, not using TDD?&lt;/p&gt;
&lt;p&gt;Maybe you want to have an automation to make your tedious work for you?&lt;/p&gt;
&lt;p&gt;In both situations, Selenium IDE may be your friend  :)&lt;/p&gt;
&lt;h1&gt;IDE Test recording&lt;/h1&gt;
&lt;p&gt;Selenium has an IDE add-on that is fully integrated with Firefox &lt;a href="https://addons.mozilla.org/en-us/firefox/addon/selenium-ide/"&gt;Find it HERE&lt;/a&gt;. Originally it was designed for making a simplified test-case recording if you don't need to create more advanced stuff using programming languages (i.e. Page Object Models ).&lt;/p&gt;
&lt;p&gt;After you install the addon, it almost looks like nothing happen. But yet you have already installed IDE - it's available at &lt;code&gt;Open Menu&lt;/code&gt; (those three dashes) then &lt;code&gt;Developer&lt;/code&gt; and then you click &lt;code&gt;Selenium IDE&lt;/code&gt; - it should be the first element in &lt;code&gt;Developer&lt;/code&gt; context menu.&lt;/p&gt;
&lt;p&gt;Then you can see this type of box:&lt;/p&gt;
&lt;p&gt;&lt;img alt="SeleniumIDEFirefoxPlugin" src="images/selenium_ide_firefox_plugin.png"&gt;&lt;/p&gt;
&lt;p&gt;Ther you can see the red ball that is for recording. When you start it and go to the page from &lt;code&gt;Base URL&lt;/code&gt; and make some action in there, it will start to be recorded.&lt;/p&gt;
&lt;h1&gt;How to use Selenium IDE (record your first automation).&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;Setup &lt;code&gt;Base URL&lt;/code&gt; - the URL for which your automation should happen.&lt;/li&gt;
&lt;li&gt;Start recording -Just click the red ball at the right top side.&lt;/li&gt;
&lt;li&gt;Do on the site whatever you need to/want to automate.&lt;/li&gt;
&lt;li&gt;When you are done with the task that you wanted to automate - click the red ball again to stop recording.&lt;/li&gt;
&lt;li&gt;You just completed your first Web-Based automation! Congratulations!&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;What now?&lt;/h1&gt;
&lt;p&gt;Now you can repeat your automation steps as much as you want!&lt;/p&gt;
&lt;p&gt;You may even have a temptation to move on with selenium. Great!&lt;/p&gt;
&lt;p&gt;Your "test case" or rather "automation" can be exported into different programming languages i.e. &lt;code&gt;C#&lt;/code&gt;, &lt;code&gt;Java&lt;/code&gt;, &lt;code&gt;Python&lt;/code&gt;, &lt;code&gt;Ruby&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;How to export your Selenium IDE recorded session?&lt;/h1&gt;
&lt;p&gt;Go to &lt;code&gt;File&lt;/code&gt; -&amp;gt; &lt;code&gt;Export Test Case As&lt;/code&gt; -&amp;gt; (and there you pick one of your favorite programming languages) i.e. Python2/unittest/Webdriver.&lt;/p&gt;
&lt;h1&gt;Last but not least&lt;/h1&gt;
&lt;p&gt;This was the first article about Selenium. Be prepared for more!&lt;/p&gt;
&lt;h1&gt;Thanks  - and a bonus!&lt;/h1&gt;
&lt;p&gt;Today it was a very short article - more a simplified tutorial.&lt;/p&gt;
&lt;p&gt;For make it more juicy I'm adding my script that I did today to check if it's even possible.&lt;/p&gt;
&lt;p&gt;A PacktPub Free Learning Claiming Automation Script - just change login and password in script and you good to go.&lt;/p&gt;
&lt;p&gt;&lt;a href="examples/PacktPub_Free_Learning_Selenium_IDE.seleniumide"&gt;PacktPub Free Learning Selenium IDE&lt;/a&gt;&lt;/p&gt;</content><category term="selenium"></category><category term="recording-test-case"></category><category term="automation"></category></entry><entry><title>ListSerializers - Django Rest Framework</title><link href="http://witkowskibartosz.com/blog/list-serializer-django-rest-framework.html" rel="alternate"></link><published>2017-07-21T00:20:00+02:00</published><updated>2017-07-21T00:20:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-07-21:/blog/list-serializer-django-rest-framework.html</id><summary type="html">&lt;p&gt;Today we are going to talk about List Serializer! Check out how you can create a bulk of items in one API-request!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;DRF - what is that?&lt;/h1&gt;
&lt;p&gt;&lt;img alt="DRF" src="images/drf_logo.png"&gt;&lt;/p&gt;
&lt;p&gt;It's a simplifier for creating API using Python's Django framework.&lt;/p&gt;
&lt;p&gt;You can check my short comparison between different type of Django-supported API frameworks &lt;a href="biking-endorphines-rest-api-within-django.html"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Django Rest Framework example project&lt;/h1&gt;
&lt;p&gt;Initially, I wanted to make my own sample Django REST Framework project that will be used in this tutorial. &lt;/p&gt;
&lt;p&gt;Then I've thought to myself- "There must be a better way" (quoting &lt;a href="https://sites.google.com/site/unclebobconsultingllc/"&gt;Uncle Bob&lt;/a&gt; ^^) - so I've found a repository at GitHub with already predefined simple logic for maintaining TODO-list as an REST-api.&lt;/p&gt;
&lt;p&gt;Check it &lt;a href="https://github.com/anselmos/DRF-TDD-example.git"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;DRF Environment setup&lt;/h1&gt;
&lt;p&gt;Check out my prepared GitHub-Gist with a simple Linux-commands that you use to prepare your environment &lt;a href="https://gist.github.com/anselmos/e106ddc2f7e9949b2386957cb2cdf397"&gt;HERE&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Checking out the source code of sample project for bulk todo-elements creation.&lt;/h1&gt;
&lt;p&gt;So first things first - let's check if our code will enable use creation of more than one element using API at once.
Let's make a POST request with a list of todos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;TEST1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;TEs&amp;lt;t2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The output of it is :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;non_field_errors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;Invalid data. Expected a dictionary, but got list.&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Means - no. No luck this time :) Let's un-release this and make a bulk of TODOs per one request.&lt;/p&gt;
&lt;h1&gt;List Serializer&lt;/h1&gt;
&lt;p&gt;I'm writing this post-heading information after about 3 hours. I've struggled to work with List-Serializer. I tried to use it in a "django" way - but for now, it's beyond my perception. I've found a solution at &lt;a href="https://stackoverflow.com/questions/36577692/listserializer-when-serializing-a-queryset-using-django-rest-framework"&gt;stackoverflow&lt;/a&gt; that after few adoption tricks started to work properly.
It's not perfect - but quoting "Done is better than perfect" - I consider it a work-in-progress solution.&lt;/p&gt;
&lt;p&gt;I might go back to this and try to investigate how it should be done in more "Django" way&lt;/p&gt;
&lt;p&gt;Checkout code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoBatchAPIView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListCreateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    API endpoint that allows multiple members to be created.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TodoSerializer&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&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;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&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;queryset&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&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;request&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;serializer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_serializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;many&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raise_exception&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="n"&gt;todo_created&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;list_elt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;todo_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;list_elt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;todo_created&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todo_obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id__in&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;todo_created&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;output_serializer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TodoSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;many&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="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output_serializer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&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;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;and in urls.py:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^batch/$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TodoBatchAPIView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&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="s2"&gt;&amp;quot;batch&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Thanks :)&lt;/h1&gt;
&lt;p&gt;Hope you find this solution valuable.&lt;/p&gt;
&lt;p&gt;I for sure will use it in my &lt;a href="tag/biking-endorphines.html"&gt;Biking-Endorphines&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;Please comment and feel free to post your solution to this problem!&lt;/p&gt;</content><category term="django-rest-framework"></category><category term="list-serializer"></category></entry><entry><title>Biking Endorphines - Points Serializer!</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-points-serializer.html" rel="alternate"></link><published>2017-07-16T15:10:00+02:00</published><updated>2017-07-16T15:10:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-07-16:/blog/biking-endorphines-points-serializer.html</id><summary type="html">&lt;p&gt;It's been a long time since I've been looking into this project from code-perspective.  I needed few deeper moments with it to find myself again in it after those 2 months (woooot??) - yeah...&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Long Time No See&lt;/h1&gt;
&lt;p&gt;It's been a long time since I've been looking into this project from code-perspective.&lt;/p&gt;
&lt;p&gt;I needed few deeper moments with it to find myself again in it after those 2 months (woooot??) - yeah...&lt;/p&gt;
&lt;h1&gt;What task should I get ?&lt;/h1&gt;
&lt;p&gt;That's the first thing I've asked myself.&lt;/p&gt;
&lt;p&gt;I've grabed github issues to investigate on which task would not need so much time.&lt;/p&gt;
&lt;p&gt;Initially I've started looking at issues estimated for 2h. &lt;/p&gt;
&lt;p&gt;I have found issue on which I was working on - the &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/55"&gt;#55&lt;/a&gt; - subtask of &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/46"&gt;#46&lt;/a&gt; which in fact is also a subtask of &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/26"&gt;#26&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It was not foreseen by me at first glance - initially I've started working on #55 - then I've found out about #46 from commits in repository - Then I've found what problem I've been struggling with last time.&lt;/p&gt;
&lt;p&gt;The infamous File-Upload with Route-information. &lt;/p&gt;
&lt;p&gt;This time I've decided to move with different approach - step-by-step - not all-in-one :)&lt;/p&gt;
&lt;h1&gt;To the &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/56"&gt;#56&lt;/a&gt; !&lt;/h1&gt;
&lt;p&gt;After re-thinking this problem I've found out that without Point serializer I will not be able to create Route-serializer.&lt;/p&gt;
&lt;p&gt;So I've changed my mind and instead of working on &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/46"&gt;#46&lt;/a&gt; I went with making Point-Serializer instead of resolving issues with File-Uploading/Json Uploading( json uploading in fact is working properly - nothing to work on in that area)&lt;/p&gt;
&lt;h1&gt;Fixing time!&lt;/h1&gt;
&lt;p&gt;Code I've found did not work properly - it failed at 2 levels - both pylint's perspective and pytests were broken.&lt;/p&gt;
&lt;p&gt;I decided to first fix the pytests perspective - cause fixing pylint's perspective would give a false-positive affect that It's done - which in fact could not be after making changes for pytests working properly.&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;Finally I've completed only part of Point-Serializer - for making only single point creation instead of bulk. I will find out what was wrong with my code next time.&lt;/p&gt;
&lt;p&gt;Source Code:&lt;/p&gt;
&lt;h4&gt;1. In &lt;code&gt;api/serializers.py&lt;/code&gt;&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PointListSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Point List serializer&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&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;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Create and return list of a new `Point` instances, given the validated data.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;item&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;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;validated_data&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;Point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bulk_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;points&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;update&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;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Maps for id-&amp;gt;instance and id-&amp;gt;data item.&lt;/span&gt;
        &lt;span class="n"&gt;point_mapping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;data_mapping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Perform creations and updates.&lt;/span&gt;
        &lt;span class="n"&gt;ret&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;point_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data_mapping&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point_mapping&lt;/span&gt;&lt;span class="o"&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;point_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&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;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c1"&gt;# Perform deletions.&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;point_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;point_mapping&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;point_id&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data_mapping&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&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;ret&lt;/span&gt;



&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PointSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Point serializer&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&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;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&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="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;lat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;lon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;elevation&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;list_serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PointListSerializer&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&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;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Create and return a new `Point` instance, given the validated data.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;2. In &lt;code&gt;web/models&lt;/code&gt; added &lt;code&gt;time&lt;/code&gt; field in Point.&lt;/h4&gt;
&lt;p&gt;Tests:&lt;/p&gt;
&lt;h4&gt;1. In &lt;code&gt;api/tests/test_integration.py&lt;/code&gt;&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestFileUploadView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;File Upload tests&amp;quot;&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="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&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;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FileUploadView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nd"&gt;@unittest.skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;test not ready&amp;quot;&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;test_json_file&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        This test has been setup as skipped temporarily - because it does not make what it should&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if making api request for uploading json file succeed&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

        &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
        &lt;span class="n"&gt;dir_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;realpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;file_&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="n"&gt;dir_path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/samples/routesample.json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;api_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;filename&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;file_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HTTP_AUTHORIZATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Token {}&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;/api/file/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;api_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;HTTP_AUTHORIZATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Token {}&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;202&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestPointView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Tests for Point View&amp;quot;&amp;quot;&amp;quot;&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="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&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;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PointView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/api/point/&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_uploading_one_point&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="s2"&gt;&amp;quot; Tests if making api request updates user with new name&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;11.22&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;11.33&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2001-01-22T07:05:05Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;ele&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;11.1&amp;quot;&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="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response_user_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;all_points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_points&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestPointListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Tests for List of Points View&amp;quot;&amp;quot;&amp;quot;&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="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&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;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PointList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/api/points/&amp;quot;&lt;/span&gt;


    &lt;span class="nd"&gt;@unittest.skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;test not ready&amp;quot;&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;test_uploading_multiple_points&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="s2"&gt;&amp;quot; Tests if making api request updates user with new name&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;11.22&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;11.33&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2001-01-22T07:05:05Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;ele&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;11.1&amp;quot;&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="s2"&gt;&amp;quot;lat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;22.22&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;22.33&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2001-01-22T07:05:05Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;ele&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;22.1&amp;quot;&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="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response_user_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&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;all_points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_points&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;/pre&gt;&lt;/div&gt;


&lt;h4&gt;2. In &lt;code&gt;api/tests/test_unit.py&lt;/code&gt;:&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestPointSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Point Serializer test&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_point_serialize&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="s2"&gt;&amp;quot;Tests if Point object serialize with PointSerializer&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;33.2&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;34.2&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;elevation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;11.2&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2017-03-03T12:00:00+00:00&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;input_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PointSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_serialized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;lat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;33.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;lon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;34.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;elevation&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;11.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2017-03-03T12:00:00+00:00&amp;quot;&lt;/span&gt;
            &lt;span class="p"&gt;}&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;test_point_list_serialize&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="s2"&gt;&amp;quot;Tests if Point object serialize with PointSerializer&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;11.1&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;11.1&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;elevation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;11.1&lt;/span&gt;
        &lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2011-01-01T11:00:00+00:00&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;input_point2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;input_point2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;22.2&lt;/span&gt;
        &lt;span class="n"&gt;input_point2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;22.2&lt;/span&gt;
        &lt;span class="n"&gt;input_point2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;elevation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;22.2&lt;/span&gt;
        &lt;span class="n"&gt;input_point2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2012-02-02T12:00:00+00:00&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;input_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PointSerializer&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;input_point&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_point2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;many&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_serialized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;OrderedDict&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="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;11.1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;11.1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;elevation&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;11.1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2011-01-01T11:00:00+00:00&amp;#39;&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="n"&gt;OrderedDict&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="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;22.2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;22.2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;elevation&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;22.2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2012-02-02T12:00:00+00:00&amp;#39;&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;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/80c6c9e"&gt;Fixes #56. Adds PointSerializer.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/da259bf"&gt;Fixes issue on tests for JSON-type file uploading.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Release:&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/releases/tag/16-07-2017-point-serializer"&gt;16-07-2017-point-serializer&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What else I've found out when looking into code and environment I'm currently working on?&lt;/h1&gt;
&lt;h4&gt;1. Lack of debug mode when using tests which in fact may help to figure out problems with code.&lt;/h4&gt;
&lt;h4&gt;2. Pylint's report contains too much information when developing and fixing - it leads to problems but it's too much of data (simple file line and error of that line would be enough)&lt;/h4&gt;
&lt;h4&gt;3. Development environment for writing drafts of articles needs a bit of my attention to make it a bit simpler to use.&lt;/h4&gt;
&lt;h4&gt;4. Figure out that I need a plugin in pelican that will automatically convert issues numbers into http-links to project in some fancy-way that I would only need to put the &lt;code&gt;[#46]&lt;/code&gt; and it would be enough for pelican plugin to read it and convert to &lt;code&gt;[#46](https://github.com/anselmos/Biking-Endorphines/issues/46)&lt;/code&gt;&lt;/h4&gt;
&lt;h4&gt;5. Lack of a simplified check-list that I'll use each time writing blog post and developing b-endorphines.&lt;/h4&gt;
&lt;h1&gt;To Be Continued - See you next time!&lt;/h1&gt;
&lt;p&gt;&lt;img alt="Till next time" src="images/tobecontinued.png"&gt;&lt;/p&gt;</content><category term="biking-endorphines"></category><category term="points-serializer"></category><category term="serializer"></category><category term="listserializer"></category><category term="list-serializer"></category><category term="django-rest-framework"></category><category term="django-rest-framework-list-serializer"></category></entry><entry><title>Time of coming back to blogging experience!</title><link href="http://witkowskibartosz.com/blog/time-to-come-back-to-blogging-experience.html" rel="alternate"></link><published>2017-07-09T13:00:00+02:00</published><updated>2017-07-09T13:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-07-09:/blog/time-to-come-back-to-blogging-experience.html</id><summary type="html">&lt;p&gt;I'm back to my blogging experience. It was so long that I almost gave it up! Check out my story for today!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Employer change!&lt;/h1&gt;
&lt;p&gt;I'm back into mode of blogging experience :) . It was a bit too long vacations from blogging, so I've almost forgot how to blog :)&lt;/p&gt;
&lt;p&gt;I had to make this vacations from blogging to speedup learning new things to company that I've started working in this month.&lt;/p&gt;
&lt;p&gt;Yeah- you guest it - I've changed my employer! It was a long journey with Mobica - and finally - after 4 years - I've decided to make changes.&lt;/p&gt;
&lt;p&gt;I'm really greatfull for all the experience I've gathered there! Great people and great projects that I had a chance to work on.&lt;/p&gt;
&lt;p&gt;There was also some less fun projects - but that's normal in our IT-industry. Unfortunatelly in my experience they are the onces that made me think about change.&lt;/p&gt;
&lt;p&gt;Finally thanks to my a bit too high ambitions I've decided to move on and find new challenge. As far as this week went by in new work - I personally think it was good choice.&lt;/p&gt;
&lt;p&gt;For now I find it both challengeful and joyful, so as a bit scary - but that's normal. &lt;code&gt;We fear things that we kind-of should do. That's why we are scared of them - they present a challenge for us. Problems we will be fighting against will shape us.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I don't think all of us should go and challenge them-self. I just wanted to say - it works for me.&lt;/p&gt;
&lt;p&gt;I personally think now that I'm not fearfull being. But being brave means to be scared but move on!&lt;/p&gt;
&lt;p&gt;Just a bit about new work - I'm working as a python developer within project that uses framework much similar to django.&lt;/p&gt;
&lt;h1&gt;Changes part 2 :)&lt;/h1&gt;
&lt;p&gt;That's not all. I've decided to go the unknown path of using "3 levels of tasks"&lt;a href="http://trzypoziomy.pl/"&gt;3 poziomy pl - thanks to Mirek!&lt;/a&gt; and check if it will lead me to any progress. And it kind of did.&lt;/p&gt;
&lt;p&gt;Unfortunatelly while I tried to fulfill my task of "5 am domination of day" I got health problems and finally I got flu - and got myself banned from outside world for a week. &lt;/p&gt;
&lt;p&gt;You may wonder how in the middle of summer I got flu? That's because I was not thinking straight :) I thought that I will just try all things that I got in my mind and bring them ASAP.&lt;/p&gt;
&lt;p&gt;That's why my organism gave up - I did not sleep enough (means at least for 7-8 hours - i did about 5-6 hours) and also first thing I did after waking up was riding a bike and then having a shower. All of this would not be something bad - unfortunatelly one time temperature outside was not enough to wear a short outfit (shortened on shorts and shirt) - and that my shower was not a hot-shower, but a half hot half cold shower - and that got my organism finally to gave up. :( (LL - lesson learned. )&lt;/p&gt;
&lt;p&gt;There was also a good side of 3-levels - after making each level of task you should give yourself something in reward (as Mirek says and does in his 3-levels - &lt;a href="http://trzypoziomy.pl/zadania/"&gt;check his big list!&lt;/a&gt; ).&lt;/p&gt;
&lt;p&gt;So I also did - After making progress in some fields (i.e. having Android badge ) - I reward myself - but in a way that will bring my attention to move with next challenges in 3-levels. &lt;/p&gt;
&lt;p&gt;That's why I've bought 16GB of RAM to my Lenovo X220 that I currently use - check pictures:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Ram before unpacking" src="images/android_badge_reward_ram_packed_for_x220_768.jpg"&gt;
&lt;img alt="Ram while installing" src="images/android_badge_reward_ram_installed_in_x220_768.jpg"&gt;&lt;/p&gt;
&lt;h1&gt;Blogging against full-time job.&lt;/h1&gt;
&lt;p&gt;Taking into account that my current job requires a full attention from me - when I come back to home I kind-of don't have any more left energy to make any progress with anything that is combined with programming.&lt;/p&gt;
&lt;p&gt;That means that probably I will make progress with my private projects in weeekends.&lt;/p&gt;
&lt;p&gt;I hope to find solution to work on them also in work-week days - using some tricks like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;After come back from work go ride a bike for 30 minutes to get more relaxed.&lt;/li&gt;
&lt;li&gt;Take a shower after going back to home to refresh myself ( &lt;code&gt;self.refresh()&lt;/code&gt;  :D )&lt;/li&gt;
&lt;li&gt;Bring pomodoro technique and my todo-lists in life and try to make a least one additional thing per day. (to motivate myself)&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;Plans?&lt;/h1&gt;
&lt;p&gt;The only plan I have is to blog at least ones a week. It may be about my current project (BikingEndorphines) or my back-side projects or other things :)&lt;/p&gt;
&lt;p&gt;Also I do hope, till end of this year I will manage to complete in some usable stage my current project (B-Endorphines) - finger crossed ! :)&lt;/p&gt;
&lt;h1&gt;THANKS!&lt;/h1&gt;
&lt;p&gt;Thanks for all of you that reads this blog - it encourages me to move on and make progress with priv. projects. :)&lt;/p&gt;
&lt;p&gt;This time it was not a technical-stuff - but beaware - you may or maynot find next article more technical :) That's a surprise !&lt;/p&gt;</content><category term="blog"></category><category term="motivational"></category><category term="3poziomypl"></category></entry><entry><title>DSP Gala!</title><link href="http://witkowskibartosz.com/blog/dsp-2017-gala.html" rel="alternate"></link><published>2017-06-18T14:30:00+02:00</published><updated>2017-06-18T14:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-06-18:/blog/dsp-2017-gala.html</id><summary type="html">&lt;p&gt;Yesterday there was a DSP Gala at Warsaw in Microsoft headquaters in which I attendeed. Check my report from it!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;DSP Gala?&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devstyle.pl/daj-sie-poznac"&gt;&lt;img alt="GetNoticed 2017" src="images/dsp2017-2-2x.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For everyone that does not know yet - DSP is a contest made by Maciej Aniserowicz in which one had a chance to &lt;code&gt;Get Noticed&lt;/code&gt;, create a blog with at least 2 articles by week and creating open-sourced project at github.&lt;/p&gt;
&lt;p&gt;It's the second edition of "Get Noticed" Gala.&lt;/p&gt;
&lt;p&gt;The Agenda for the Gala event can be found in &lt;a href="https://devstyle.pl/daj-sie-poznac/gala/"&gt;here - in polish lang.&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;My attendance in DSP Gala?&lt;/h1&gt;
&lt;p&gt;I have been one of the finalist of DSP2017 (the one that have made 2 articles per week).&lt;/p&gt;
&lt;p&gt;I've decided to meet Maciej Aniserowicz and other participants. Also I had high hopes to introduce myself and my project to others in some way.&lt;/p&gt;
&lt;h1&gt;From Paris to Berlin... I mean... From Bydgoszcz to Warsaw&lt;/h1&gt;
&lt;p&gt;So to attend in gala, I had to either drive by car, take a bus or use train.&lt;/p&gt;
&lt;p&gt;I've decided to go by train - because after checking arrival time - I had high hopes not to be late :)&lt;/p&gt;
&lt;p&gt;Sure thing - I was not - I managed to be at registration short before ending :)&lt;/p&gt;
&lt;h1&gt;Handshaking Maciej Aniserowicz!&lt;/h1&gt;
&lt;p&gt;So that was first time I had a chance to meet &lt;a href="https://devstyle.pl/o-mnie/"&gt;Maciej!&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It was a great opportunity for me to work on my introvertism and hand-shake his hand! &lt;/p&gt;
&lt;p&gt;And I did! Man - that was so liberating, I feel so good even now!&lt;/p&gt;
&lt;h1&gt;DSP Participants!&lt;/h1&gt;
&lt;p&gt;Wow ! That was my first shock when I've arrived at Warsaw with my colleague - &lt;a href="http://www.codinghappiness.com"&gt;Wojciech&lt;/a&gt; - At the Gala there was a full-house of people. I knew that there will be around 150 people, but I did not anticipate almost all of them will come!&lt;/p&gt;
&lt;p&gt;Since Maciej was so generous and add information that no-formal-style was needed - All of us could feel more comfortable in our usual daily outfit :)&lt;/p&gt;
&lt;p&gt;I had high hopes to get to know other people and participants that I compete against :)&lt;/p&gt;
&lt;p&gt;From first glance I knew there will be a lot of Dot-Net programmers - but I found a lot of programmers that knew more then Dot-Net. I even found a pythonist! - High-Five to you &lt;a href="https://rock-it.pl"&gt;Jakub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I even found one of them got more interested in my project ! Fantastic! My goal has been achieved!&lt;/p&gt;
&lt;h1&gt;DSP participants and their presentations!&lt;/h1&gt;
&lt;p&gt;Participants of DSP had a chance to have their presentation at Gala.&lt;/p&gt;
&lt;p&gt;Applause for all of them! I personally had a lot of fun on each and every one!&lt;/p&gt;
&lt;p&gt;Even my colleague had his presentation! The &lt;code&gt;“Daj się poznać’ się skończyło. Twoja przygoda z blogowaniem dopiero się rozpoczyna”&lt;/code&gt; - I had to admit Wojciech - you did great job! You have motivated me personally to move on with project!&lt;/p&gt;
&lt;h1&gt;Afterparty&lt;/h1&gt;
&lt;p&gt;After DSP there was an afterparty. Unfortunatelly I could not participate in it. I hope to find all of you at other conferences and meetups!&lt;/p&gt;
&lt;h1&gt;Blog and What now?&lt;/h1&gt;
&lt;p&gt;Lately I tried to make a plan of creating 2 articles in week.&lt;/p&gt;
&lt;p&gt;That did not worked out because of my learning to work and also because of my weekend Android-Google-Exam that I passed! &lt;/p&gt;
&lt;p&gt;See my my badge: &lt;a href="http://bcert.me/snwwceze"&gt;&lt;img alt="Associate Android Developer Badge" src="images/aad-badge-240-240.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I've decided that for next 2 weeks (till end of June) I will not blog. I had to focus on learning stuff needed in work.&lt;/p&gt;
&lt;p&gt;After that time, I hope to blog at least once a week.&lt;/p&gt;
&lt;p&gt;So let's see you in July! Thanks!&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category></entry><entry><title>Biking Statistics - Who Cares about Them actually?</title><link href="http://witkowskibartosz.com/blog/biking-statistics-who-cares-about-them-actually.html" rel="alternate"></link><published>2017-06-04T20:30:00+02:00</published><updated>2017-06-04T20:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-06-04:/blog/biking-statistics-who-cares-about-them-actually.html</id><summary type="html">&lt;p&gt;Today we'll focus on who really cares about statistics, and why so many people out there believes in them?&lt;/p&gt;</summary><content type="html">&lt;h1&gt;What are statistics ?&lt;/h1&gt;
&lt;p&gt;Statistics are just numbers that are collected (in biking context) from variety of devices, starting from simple count-down timer and ending on more technology advanced collectors like Endomondo Android application, bicycle counter with gps/heart rate/elevation and prognosis of progress.&lt;/p&gt;
&lt;p&gt;Based on data that you can obtain, you may create different forms of statistics:
- Graphs 
- Diagrams
- Counters i.e. average m/h(miles per hour)&lt;/p&gt;
&lt;p&gt;Also notable would be to acknowledge statistics data:
- Simplest average km/miles per race-route
- Highest/Lowest elevation of route
- Heart Rate levels on route ( i.e. in which points of route you get tired - which gives feedback on what elements of route (mounting) you could level-up)
- many more that I did not yet discovered&lt;/p&gt;
&lt;h1&gt;Why are they important ?&lt;/h1&gt;
&lt;h3&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Motivation - you obtain knowledge that you otherwise would not gain with which you are getting more motivation to bring more from yourself!&lt;/li&gt;
&lt;li&gt;Measure progress - especially needed within racing/trainings.&lt;/li&gt;
&lt;li&gt;Focusing on your goals! - you can focus on specific goal - i.e. to make next lap in training faster then before.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You may get dismotivated ! - if you will not have progress with your goals,&lt;/li&gt;
&lt;li&gt;It's not for everyone - short term bikers should first learn to enjoy making best of biking instead of focusing on numbers.&lt;/li&gt;
&lt;li&gt;Statistics can be bound to your matter - you may start to fool yourself by using statistics (as they say - "There's truth, semitruth and statistics" )&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Who really cares about statistics ?&lt;/h1&gt;
&lt;p&gt;In short answer to this is simple - anyone who wants to achieve something in sport - it does not matter if its cycling, athletics, swimming or running.&lt;/p&gt;
&lt;p&gt;Elaborating, in each of this sports you use statistics and numbers to make competition between each participants.&lt;/p&gt;
&lt;p&gt;This then makes a good ground to motivate players to level-up and be better than your competition and yourself sometimes (beat your own records).&lt;/p&gt;
&lt;p&gt;I myself in particular find statistics fascinating and motivational. They not only gives me a feedback about how my body feels and where it stands, but also describes my successes and failures.&lt;/p&gt;
&lt;p&gt;But there is also the second side of the coin - sometimes I find statistics in applications - especially combined with competition - a bit demotivational. Taking an example - if you don't have so much time in some month as you had in previous, then you see lower progress against opponent then you expected it to be. And it should be perfectly fine, because you didn't have time, but still statistics don't have that accounted.&lt;/p&gt;
&lt;h1&gt;Why our Biking Endorphine project uses statistics??&lt;/h1&gt;
&lt;p&gt;First of all when I've created this project initially it was called "biking-stats" - that means I wanted to achieve a better statistics than there is in free-mode at Endomondo. Let's look at arguments against and for statistics in project:&lt;/p&gt;
&lt;h3&gt;For:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You have real feedback from gps about progress of each user&lt;/li&gt;
&lt;li&gt;You can count information about such user and give them feedback - since each and almost every sport-applications does.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Against:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;As previously said statistics can lie to you in some way&lt;/li&gt;
&lt;li&gt;Using statistics with competition creates a winner/looser situation, where none of them are good way to achieve more(in a positive way)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks&lt;/h1&gt;
&lt;p&gt;Thanks folks, that's all. 
In the comments below, you can give me a feedback what do you think about statistics in our sport-life and programming?&lt;/p&gt;
&lt;p&gt;Do you find them atractive and positive ? Do you care about them ??&lt;/p&gt;
&lt;p&gt;Maybe not and you struggle against them ? Any comment is appreciated.&lt;/p&gt;
&lt;p&gt;See you soon :)&lt;/p&gt;</content><category term="biking-endorphines"></category><category term="biking-statistics"></category></entry><entry><title>Blogging and Final DSP article - Bye Bye to DSP</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-final-dsp-article.html" rel="alternate"></link><published>2017-05-31T15:50:00+02:00</published><updated>2017-05-31T15:50:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-31:/blog/biking-endorphines-final-dsp-article.html</id><summary type="html">&lt;p&gt;Blogging and DSP contest - Is this over? Today I will focus on how much things I've accomplished because of DSP contest and the outcome of Biking-Endorphines project. Check out what future holds :)&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Why did you start Blogging?&lt;/h1&gt;
&lt;p&gt;Before I've decided to get involved in blogging, I've thought - I don't have time for this.
I should be learning, programming, but not blogging. &lt;/p&gt;
&lt;p&gt;Where is fun in that? &lt;/p&gt;
&lt;p&gt;For more then few years I did not blog ( I had an internal blog - one that does not qualify as a blog, but more for a note-taking place about technical stuff). It's not that I haven't been thinking about it, but I didn't considered it as a way for making more progress in programming.&lt;/p&gt;
&lt;p&gt;Years passed by and finally I've found myself in work at project in which I did not develop any features. I thought to myself - just get over with it, it will pass, someday you will program new things. But day after day, week after week I've struggle with not programming and my frustration levels went far beyond any understanding.&lt;/p&gt;
&lt;p&gt;Then I've though - it's time to get back on my biking-trainings at mornings that always gave me such a pleasure for almost all day.&lt;/p&gt;
&lt;p&gt;It worked partially. At the final stage I've decided to go with something more than just relaxing myself before work!&lt;/p&gt;
&lt;h1&gt;Strike 1 - online-courses!&lt;/h1&gt;
&lt;p&gt;Online courses worked out for few weeks. But not for long. I didn't want to spend my time only on some useless courses that didn't bring any potential measure outcome in meaning - a project that I could maintain.&lt;/p&gt;
&lt;h1&gt;Strike 2 - power of conferences!&lt;/h1&gt;
&lt;p&gt;That was my second and more successful attempt to get out of comfort zone.
That worked very well - not only I had to overcome my shyness to new people, but also I could learn something new.&lt;/p&gt;
&lt;p&gt;Yeah you could just play youtube-channel with some conference, but that is just a substitute of how much you can gain going on such event!&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://2017.boilingfrogs.pl/"&gt;BoilingFrogs conference&lt;/a&gt; on which my friend &lt;a href="http://www.codinghappiness.com/"&gt;Wojciech&lt;/a&gt; asked me to go, was the one that inspired me a lot.&lt;/p&gt;
&lt;p&gt;It was that much of inspiration, that I've decided to start my own Blog. I will not say about "Why you should have your own blog" - there has been a lot of articles out there about that and youtube-videos that I would just repeat other's thoughts.&lt;/p&gt;
&lt;p&gt;To simply summarize why I started blog - for learning new things, making articles that could be useful for potential future audience. Learn by explaining!&lt;/p&gt;
&lt;h1&gt;DSP and final thoughts&lt;/h1&gt;
&lt;p&gt;At the BoilingConference I've found out about DSP contest. It was 25 of February. Just few days before end of registration for this contest. I didn't know back then If I want to participate in such a big thing. Initially I've started my blog without DSP - with my simple Wednesdays Tutorials article.&lt;/p&gt;
&lt;p&gt;Few days later at 2nd of March I read information that registration has been extended for another 10 days - And thought to myself - what's the worse that can happen? Even if I fail to make project in that time - I will learn new things that may push myself away from comfort zone!&lt;/p&gt;
&lt;p&gt;And I've created my &lt;a href="get-noticed.html"&gt;first article with DSP tag&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For project I've figure out - why not restart my long waiting project of Biking statistics that I've kind-of abandoned.&lt;/p&gt;
&lt;p&gt;Within this project I've made a lot little successes that I did not anticipate before making it!
So yea... it worked out! A lot! Thanks &lt;a href="http://devstyle.pl/"&gt;Maciej&lt;/a&gt; that I could participate in this contest!&lt;/p&gt;
&lt;h1&gt;Accomplished at Biking-Endorphines Projects!&lt;/h1&gt;
&lt;p&gt;Originally I thought I will create both Android application and python backend with web module.&lt;/p&gt;
&lt;p&gt;That was not realistic thinking taking into consideration my previous duties (full-time job, weekend course and other).
Fortunatelly I've cut-off Android-part somewhere in the middle of April.&lt;/p&gt;
&lt;p&gt;Now to the optimistic part :) &lt;/p&gt;
&lt;p&gt;I've accomplished:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines"&gt;GitHub project created&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://travis-ci.org/anselmos/Biking-Endorphines"&gt;Integration with Travis build and having pylint&amp;amp;tests integrated&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pull/11"&gt;Integration of pyreverse to create live diagrams with Travis build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Source code for Rest-API&lt;/li&gt;
&lt;li&gt;Initial source code for endorphine-algorithms.&lt;/li&gt;
&lt;li&gt;TDD in mind :)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues?q=is%3Aissue+is%3Aclosed"&gt;Github Issues Closed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pulls?q=is%3Apr+is%3Aclosed"&gt;Github Pull Requests Closed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Overall - I've done pretty much good job. I know I could have done more - but as I've recently said in one of my posts - &lt;code&gt;Done is better then perfect!&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;To Be continued&lt;/h1&gt;
&lt;p&gt;No, it's not over :) Projects will be continued.&lt;/p&gt;
&lt;h1&gt;Plans - What's next?&lt;/h1&gt;
&lt;p&gt;I plan to have at least 2 articles per week.&lt;/p&gt;
&lt;p&gt;First article is going to be strictly Tutorials - where I will discover new things that may/may not be of any usefulness :)&lt;/p&gt;
&lt;p&gt;Second article will be about Biking Endorphines project!&lt;/p&gt;
&lt;h1&gt;Thanks to all my readers! And ofcourse , Monty Python !&lt;/h1&gt;
&lt;p&gt;&lt;img alt="MontyPython-It's only a flesh wound" src="images/monty-python-only-a-flesh-wound.jpg"&gt;&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="final-dsp-article"></category><category term="blogging"></category><category term="reasons-behind-curtain-for-blogging"></category></entry><entry><title>File Uploading at REST API with JSON Parsing into list of route-Points</title><link href="http://witkowskibartosz.com/blog/file-uploading-at-rest-api-with-json-parsing-into-list-of-route-points.html" rel="alternate"></link><published>2017-05-30T23:50:00+02:00</published><updated>2017-05-30T23:50:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-30:/blog/file-uploading-at-rest-api-with-json-parsing-into-list-of-route-points.html</id><summary type="html">&lt;p&gt;File Uploads using REST-API. Is this even needed ? Oh yes. Especially for in-coming Android Client! Check out my work on customising JSONParser from Django-Rest-Framework and making File-uploads possible via Rest-API!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Custom JSONParser - extending Django-Rest-Framework JSONParser?&lt;/h1&gt;
&lt;p&gt;Why would you even need to extend JSONParser ? Well... I want to have a list of Points at the end of parsing, not a json-type data.&lt;/p&gt;
&lt;p&gt;In that way I can easily manipulate this data and check information on it, i.e. using endorphine-algorithms to find out if badge can be applied to specific route!&lt;/p&gt;
&lt;h1&gt;How to start working on custom Parser from Djagno-Rest-Framework?&lt;/h1&gt;
&lt;p&gt;TDD approach of-course! But how? Well I didn't know myself when I started to figure it out, but then I thought to myself- why not check at source-code of Djagno-Rest-Framework - &lt;a href="https://github.com/encode/django-rest-framework/blob/master/tests/test_parsers.py"&gt;Django-Rest-Framework Parsers Test-case&lt;/a&gt;- But unfortunatelly this code does not provided me any valid answers.&lt;/p&gt;
&lt;p&gt;Then I've looked into &lt;a href="https://github.com/encode/django-rest-framework/blob/master/rest_framework/parsers.py"&gt;source code of parser&lt;/a&gt; and realized that the &lt;code&gt;parse&lt;/code&gt; method is the one used. So I've went that way to extend functionality with mine.&lt;/p&gt;
&lt;p&gt;I've firstly made an test for checking if only extending JSONParse without changing content and picking &lt;code&gt;parse&lt;/code&gt; method will create at the end the same output as input (as a  StringIO stream).&lt;/p&gt;
&lt;p&gt;Then I've changed tests so they fit my assumptions about behaviour of this custom JSON parser.&lt;/p&gt;
&lt;h1&gt;Initial tests with source-code:&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RouteJSONParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JSONParser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Route JSON Parser - parses JSON file into list of Points&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestRouteJSONParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot; Tests for RouteJSONParser class parse method overloaded&amp;quot;&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RouteJSONParser&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;test_parse&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="s2"&gt;&amp;quot; tests parser &amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;input_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;53.126699&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;18.072322&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2000-01-01T07:47:02Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;ele&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;107.0&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;53.126699&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;18.072322&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2001-01-01T07:47:02Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;ele&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;99.0&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;input_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StringIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dict&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final Source code of RoutesJSONParser with Tests&lt;/h1&gt;
&lt;p&gt;Tests:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestRouteJSONParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot; Tests for RouteJSONParser class parse method overloaded&amp;quot;&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RouteJSONParser&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;test_parse&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="s2"&gt;&amp;quot; tests parser &amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;input_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;53.126699&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;18.072322&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2000-01-01T07:47:02Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;ele&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;107.0&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;53.126699&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;lon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;18.072322&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2001-01-01T07:47:02Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;ele&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;99.0&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;53.126699&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;18.072322&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2000-01-01T07:47:02Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;ele&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;107.0&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;53.126699&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;18.072322&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2001-01-01T07:47:02Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;ele&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;99.0&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;input_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StringIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dict&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Source-code - that resides in a test-module for now. I will definitely move that into source-files.&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# pylint: disable=too-few-public-methods&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Point object with lat/lon time and ele &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lon&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;ele&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lat&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lon&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ele&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ele&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__repr__&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="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;{},{},{},{}&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ele&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# pylint: disable=too-few-public-methods&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RouteJSONParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JSONParser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Route JSON Parser - parses JSON file into list of Points&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse&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;stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;media_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parser_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;json_content&lt;/span&gt; &lt;span class="o"&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;RouteJSONParser&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;media_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parser_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;points&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;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;json_content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ele&amp;#39;&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;points&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;File uploading via REST-API.&lt;/h1&gt;
&lt;p&gt;I wanted to follow TDD approach at this, but first I had to check how to create FileUploading solution cause I don't remember when I've done such thing!&lt;/p&gt;
&lt;p&gt;So I've broke my "first test than production code", and first created a production code to check how it will look like, So I could find out how I should test it.&lt;/p&gt;
&lt;p&gt;Fortunatelly for me &lt;a href="http://www.django-rest-framework.org/api-guide/parsers/#fileuploadparser"&gt;Django-Rest-Framework Documentation on that subject&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After struggling for few hours with having still a "Not found" feedback information from source-code in tests, I've passed for now.&lt;/p&gt;
&lt;p&gt;I'll figure this out someway, but this will not be today unfortunatelly :(&lt;/p&gt;
&lt;p&gt;When checking manually source-code seems to be working, but I'm not sure if it does in all cases because of lack of passing tests... :/&lt;/p&gt;
&lt;h3&gt;Source-Code:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileUploadView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot; A view for file upload &amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;parser_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JSONParser&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;post&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;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;json&amp;#39;&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;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Tests that is not passing yet:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestFileUploadView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;File Upload tests&amp;quot;&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="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&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;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FileUploadView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&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;_create_test_file&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;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;f&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="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test123&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;f&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="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;datafile&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&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;test_update_user&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="s2"&gt;&amp;quot; Tests if making api request updates user with new name&amp;quot;&lt;/span&gt;

        &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
        &lt;span class="n"&gt;dir_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;realpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;file_&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="n"&gt;dir_path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/samples/routesample.json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;api_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;filename&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;file_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HTTP_AUTHORIZATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Token {}&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;/api/file/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;api_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;json&amp;#39;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;multipart&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Bugs /Features I've found while working&lt;/h1&gt;
&lt;h3&gt;Bugs:&lt;/h3&gt;
&lt;p&gt;Non so-far.&lt;/p&gt;
&lt;h3&gt;Features:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/55"&gt;Parser for Routes in JSON data format #55&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;In branch &lt;a href="https://github.com/anselmos/Biking-Endorphines/tree/feature/55-parser-for-routes-in-json-data-format"&gt;feature/55-parser-for-routes-in-json-data-format&lt;/a&gt;:
- &lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/33d767d"&gt;Adds tests with RouteJSONParser&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In branch &lt;a href="https://github.com/anselmos/Biking-Endorphines/tree/feature/46-Endpoint-for-adding-new-routes-should-take-json-content-in-body"&gt;feature/46-Endpoint-for-adding-new-routes-should-take-json-content-in-body&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/31cb8b7"&gt;Adds a failing test for FileUploadView&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/b147c85"&gt;Testing FileUpload - to be changed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;StackOverFlow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods"&gt;Understanding Python super() with &lt;strong&gt;init&lt;/strong&gt;() methods [duplicate]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/20473572/django-rest-framework-file-upload"&gt;Django Rest Framework File Upload&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/21129020/how-to-fix-unicodedecodeerror-ascii-codec-cant-decode-byte"&gt;How to fix: “UnicodeDecodeError: 'ascii' codec can't decode byte”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/25707558/json-valueerror-expecting-property-name-line-1-column-2-char-1"&gt;JSON ValueError: Expecting property name: line 1 column 2 (char 1)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/14721062/python-comparing-2-lists-of-instances"&gt;python: comparing 2 lists of instances&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1227121/compare-object-instances-for-equality-by-their-attributes-in-python"&gt;Compare object instances for equality by their attributes in Python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.brightcove.com/en/video-cloud/concepts/postman/postman.html"&gt;Use Postman for HTTP Requests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Djagno-Rest-Framework Documentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.django-rest-framework.org/api-guide/parsers/#jsonparser"&gt;JSONParser&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;p&gt;Contest is almost over. But working on project is not :)&lt;/p&gt;
&lt;p&gt;Anndd.....&lt;/p&gt;
&lt;h1&gt;Monty Python is here again!&lt;/h1&gt;
&lt;p&gt;&lt;img alt="Literally Disarmed still does his job" src="images/monty-python-literally-disarmed-still-does-his-job.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Thanks! See you soon!&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="rest-api"></category><category term="file-upload"></category><category term="rest-api-file-upload"></category><category term="rest-api-json-body-parser"></category><category term="custom-django-rest-framework-json-parser"></category><category term="extending-django-rest-framework"></category><category term="toggl"></category><category term="pomodoro-technique"></category><category term="tdd-approach"></category></entry><entry><title>Splitting bigger issues into smaller &amp; Endorphine Badges Acquired</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-splitting-big-tasks-endorphine-badges-acquired.html" rel="alternate"></link><published>2017-05-28T18:40:00+02:00</published><updated>2017-05-28T18:40:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-28:/blog/biking-endorphines-splitting-big-tasks-endorphine-badges-acquired.html</id><summary type="html">&lt;p&gt;Yesterday and today I've been working on Biking-Endorphines project. To accomplish at least some key-parts that are needed for web-page work, I've splitted bigger tasks into smaller ones. Check my work on Endorphine-Badges endpoint and what new bugs/features I've found while working on it!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Splitting big tasks into smaller one!&lt;/h1&gt;
&lt;p&gt;So I've been thinking, why I'm so not productive lately - and I've found reason - I've been scared of big tasks that consumes a lot of time!&lt;/p&gt;
&lt;p&gt;I've decided to spend at least one Pomodoro timer (25 minutes) for splitting issues on Biking-Endorphines project.&lt;/p&gt;
&lt;p&gt;At least ones that are estimated on more then 4 h.&lt;/p&gt;
&lt;h1&gt;Endorphine-Badges-Acquired &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/23"&gt;#23&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;While reading this issue I've found it's not properly specified and should be splitted into smaller issues/features to make it more "pomodoro-a-like".&lt;/p&gt;
&lt;p&gt;So I've added additional 2 tasks that helped me a lot to make progress with this issue.&lt;/p&gt;
&lt;h1&gt;Subtasks of &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/23"&gt;#23&lt;/a&gt; : &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/44"&gt;#44&lt;/a&gt; and &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/45"&gt;#45&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Endpoint for gathering all acquired badges needed 2 models with following them tables :
- Badges
- UserBadges&lt;/p&gt;
&lt;p&gt;And then I could work on creating endpoint with serializer.&lt;/p&gt;
&lt;p&gt;So I've created corresponding &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/44"&gt;[REST-API] Badges Model needed #44&lt;/a&gt; and &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/45"&gt;[REST-API] Badge-To-User model #45&lt;/a&gt; and described them as specific as I could.&lt;/p&gt;
&lt;h1&gt;Pomodoro Technique Timer from Toggl :)&lt;/h1&gt;
&lt;p&gt;I've also recently started testing new platform called Toggl - for tracking time. &lt;/p&gt;
&lt;p&gt;It has such a fancy-pancy chrome-addon that helps to track of time for specific github-issue and has build-in pomodoro timer that after 25 minutes can trigger notification from browser.&lt;/p&gt;
&lt;p&gt;Using it helped me with "high-density" working on issues above.&lt;/p&gt;
&lt;h1&gt;Bugs /Features I've found while working&lt;/h1&gt;
&lt;p&gt;I've found few bugs/features that I'll be working on soon after this Python-Milestone will end.&lt;/p&gt;
&lt;p&gt;Bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/48"&gt;[REST-API] Generic Model Test Case needs fields types check #48&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/51"&gt;[REST-API] Point model fields lat-lon unique #51&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/47"&gt;[REST-API] Add processing method for adding new route endpoint #47&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/50"&gt;[REST-API] Need to create Test-cases for unicode checking of Models #50&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/46"&gt;[REST-API] Endpoint for adding new routes should take json content in body. #46&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/47"&gt;#47&lt;/a&gt; and &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/46"&gt;#46&lt;/a&gt; were put into Python-Milestone because they are closely related with &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/26"&gt;#26&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Final version&lt;/h1&gt;
&lt;p&gt;Test code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;at api/tests/test_unit.py:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestUserBadgeSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;UserBadge Serializer test&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_user_badge_serialize&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="s2"&gt;&amp;quot;Tests if user_badge object serialize with RouteSerializer&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&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;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Somlesna&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;175&lt;/span&gt;

        &lt;span class="n"&gt;badge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;FasterThenUniverse&amp;#39;&lt;/span&gt;
        &lt;span class="n"&gt;badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;you&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;re average lap was faster then previous one&amp;#39;&lt;/span&gt;

        &lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;NameOfThisFancyRoute&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;avg_route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;19.9&lt;/span&gt;


        &lt;span class="n"&gt;input_user_badge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserBadge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;input_user_badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
        &lt;span class="n"&gt;input_user_badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_badge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;badge&lt;/span&gt;
        &lt;span class="n"&gt;input_user_badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;
        &lt;span class="n"&gt;input_user_badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;input_user_badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;badge_acquiring_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2017-03-03T12:00:00+00:00&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;input_user_badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activation_modification_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2017-03-03T12:00:00+00:00&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;input_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserBadgeSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_user_badge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_serialized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;id_badge&amp;#39;&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="s1"&gt;&amp;#39;id_user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;id_route&amp;#39;&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="s1"&gt;&amp;#39;active&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;badge_acquiring_date&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2017-03-03T12:00:00+00:00&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;activation_modification_date&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2017-03-03T12:00:00+00:00&amp;#39;&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;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;at &lt;code&gt;api/tests/test_integration.py::APIGeneralTestCase&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="c1"&gt;# pylint: disable=no-self-use&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_badge_in_db&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="s2"&gt;&amp;quot; Creates new badge object in database &amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;FasterThenUniverse&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;you&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;re average lap was faster then previous one&amp;#39;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# pylint: disable=no-self-use&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_route_in_db&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="s2"&gt;&amp;quot; Creates new route object in database &amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;route_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;NameOfThisFancyRoute&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;avg_route&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;19.9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# pylint: disable=no-self-use&lt;/span&gt;
    &lt;span class="c1"&gt;# pylint: disable=too-many-arguments&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user_badge_in_db&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;badge_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation_date&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot; Creates new UserBadge object in database &amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UserBadge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;id_user&lt;/span&gt;&lt;span class="o"&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;id_badge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;id_route&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;badge_acquiring_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;badge_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;activation_modification_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;activation_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;at &lt;code&gt;api/tests/test_integration.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestUserBadgeList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;User Update tests&amp;quot;&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="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&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;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserBadgeList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&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;test_update_user&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="s2"&gt;&amp;quot; Tests if making api request updates user with new name&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;badge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_badge_in_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_route_in_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_user_in_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;date_badge_acquired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2017-02-02T22:00:00&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;date_badge_activation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2017-02-02T22:00:00&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;user_badge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_user_badge_in_db&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;badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;date_badge_acquired&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;+00:00&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;date_badge_activation&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;+00:00&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/api/badge/{}/&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response_user_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;pk_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_user_badge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;user_badge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;unicode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date_badge_acquired&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nb"&gt;unicode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date_badge_activation&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# pylint: disable=too-many-arguments&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assert_user_badge&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;user_badge_object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;badge_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;route_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;badge_acquiring_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation_modification_date&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Asserts user badge object with parameters &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_badge_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;id_user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_badge_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;id_badge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;badge_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_badge_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;id_route&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;route_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_badge_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;active&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;user_badge_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;badge_acquiring_date&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;badge_acquiring_date&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;user_badge_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;activation_modification_date&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;activation_modification_date&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Source Code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;at web/models.py:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Badge Model&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;help_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;describes in short name of the badge&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;help_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;More thorough information about badge acquiring (i.e. criteria)&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="s2"&gt;&amp;quot;Returns Badge unicode as name: description &amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;{}: {}&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserBadge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Users acquired Badges!&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;id_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&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;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;id_badge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;id_route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;help_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;id of route on which badge has been acquired&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BooleanField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&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="n"&gt;badge_acquiring_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;activation_modification_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="s2"&gt;&amp;quot;Returns Badge unicode as name: description &amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;User : {},  Badge acquired-id: {}: &amp;quot;&lt;/span&gt;\
        &lt;span class="s2"&gt;&amp;quot;Route-id: {}, active?: {}, badge_acquired_date: {}, &amp;quot;&lt;/span&gt;\
        &lt;span class="s2"&gt;&amp;quot;activation_modification_date: {}&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;badge_acquiring_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activation_modification_date&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;at api/serializers.py:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserBadgeSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    User serializer&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&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;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserBadge&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="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;id_badge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;id_user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;id_route&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;active&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;badge_acquiring_date&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;activation_modification_date&amp;#39;&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;create&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;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Create and return a new `UserBadge` instance, given the validated data.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UserBadge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;at api/views.py:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserBadgeList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListCreateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    get:&lt;/span&gt;
&lt;span class="sd"&gt;    Return a list of all existing user badges.&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserBadge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserBadgeSerializer&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;In branch &lt;a href="https://github.com/anselmos/Biking-Endorphines/tree/feature/44-Badges-Model-needed"&gt;feature/44-Badge-model-needed&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/ba68b44"&gt;Fixes issues with Pylint. Fixes migration script.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/664a0c3"&gt;Adds Badge Model to web-models. Fixes #44.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In branch &lt;a href="https://github.com/anselmos/Biking-Endorphines/tree/feature/45-Badge-to-User-model"&gt;feature/45-Badge-to-User-model&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/b64b193"&gt;Fixes #45. Adds UserBadge Model with tests.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/1bc8b8b"&gt;Adds Badge Model to web-models. Fixes #44. (#49)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In branch &lt;a href="https://github.com/anselmos/Biking-Endorphines/tree/feature/23-Endorphine-badges-acquired"&gt;feature/23-Endorphine-badges-acquired&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/b44deb7"&gt;Fixes #23. Fixes pylint issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/f6cd743"&gt;Adds passing integration test for UserBadge API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/4b87a61"&gt;Adds failing UserBadge integration test.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/5bf015f"&gt;Adds UserBadge Serializer with UnitTests.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/a812469"&gt;Fixes #45. Adds UserBadge Model with tests. (#53)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/1bc8b8b"&gt;Adds Badge Model to web-models. Fixes #44. (#49)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Release:&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/releases/tag/28-05-07-badges-acquiring-api"&gt;28-05-07-badges-acquiring-api&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;p&gt;Hunting never ends!! &lt;img alt="Monty Python Hunting" src="images/monty-python-not-witch-hunt.jpg"&gt;.&lt;/p&gt;
&lt;p&gt;I'm still on my python-hunting for collecting as much of &lt;a href="https://github.com/anselmos/Biking-Endorphines/milestone/1"&gt;Python Milestone Issues&lt;/a&gt; as I can : &lt;/p&gt;
&lt;h4&gt;Due by May 31, 2017 66% complete (9 Open/ 18 Closed)&lt;/h4&gt;
&lt;p&gt;Thanks! See you soon!&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="endorphine-badges"></category><category term="badge-model"></category><category term="user-badge-model"></category><category term="toggl"></category><category term="pomodoro-technique"></category><category term="tdd-approach"></category></entry><entry><title>Biking Endorphines - Zero Division Error</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-zero-division-error.html" rel="alternate"></link><published>2017-05-24T18:30:00+02:00</published><updated>2017-05-24T18:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-24:/blog/biking-endorphines-zero-division-error.html</id><summary type="html">&lt;p&gt;Yesterday I've worked on &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/40"&gt;Zero Division Error bug #40&lt;/a&gt;. Come and see my code! :)&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Zero Division Error bug &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/40"&gt;#40&lt;/a&gt;.&lt;/h1&gt;
&lt;p&gt;So yesterday I've started working on this bug. I've estimated it for about 1h.&lt;/p&gt;
&lt;p&gt;It was fortunatelly a very realistic estimation. When making changes and creating Test-case for this issue, I've found myself thinking, is it really possible to use BMI health check for people who are less then 1m hight.&lt;/p&gt;
&lt;p&gt;So I've looked at internet and Voilà! Other calculators do that! So without struggle I've adapted my code to be able to put less height then 1m long.&lt;/p&gt;
&lt;p&gt;I know it may sound like a trifle, but I've thought that people using this application will probably not lie to themselves and make a fake data.&lt;/p&gt;
&lt;h1&gt;What was wrong with my code?&lt;/h1&gt;
&lt;p&gt;My assuption is that height is setup in centimeters.&lt;/p&gt;
&lt;p&gt;That's why I've fallen into situation where I need to change floating point number to adjust formula not to return zeros.&lt;/p&gt;
&lt;h1&gt;Test source code:&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_height_less_hundred&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot; tests for height less then hundred if not raises ZeroDivisionError&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;under hundred height&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;under fifty weight&amp;quot;&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mf"&gt;51.02&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;BMI method source code:&lt;/h1&gt;
&lt;p&gt;As you can see by code below, I've decided to change all the parameters inside of bmi method into float's .&lt;/p&gt;
&lt;p&gt;It's not best, because I could change them at the initialization part, but still - &lt;code&gt;*Done is better then perfect!*&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bmi&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Body Mass Index calculator simplified to number&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&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;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/4809dc3"&gt;Refactors from pylint issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/d632c97"&gt;Fixes #40.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/1a55efb"&gt;Adds failing test for BMI ZeroDivisionError&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/9d002f1"&gt;Feature/24 routes user have been based on gpx files (#42)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nhlbi.nih.gov/health/educational/lose_wt/BMI/bmicalc.htm"&gt;Calculate Your Body Mass Index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.calculator.net/bmi-calculator.html"&gt;BMI Calculator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bmi-calculator.net/bmi-formula.php"&gt;BMI Formula&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;p&gt;I'm going to continue my hunt for &lt;a href="https://github.com/anselmos/Biking-Endorphines/milestone/1"&gt;Python Milestone Issues&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thanks! See you soon!&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="webserver"></category><category term="the-plan"></category></entry><entry><title>Biking Endorphines - Python Web Server with API</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-python-web-server-with-api.html" rel="alternate"></link><published>2017-05-21T19:00:00+02:00</published><updated>2017-05-21T19:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-21:/blog/biking-endorphines-python-web-server-with-api.html</id><summary type="html">&lt;p&gt;Web Server I'm going to build within May :) Check out on what I'll focus my attention ? :)&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Status of project&lt;/h1&gt;
&lt;p&gt;As promissed I'm giving information on how is the progress with features/bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Completed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/41"&gt;Feature/22 users api&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/22"&gt;[REST-API] Users api&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/38"&gt;Refactors pylint. Moves to Github Issues if needed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/9"&gt;Remove all obsolete pylint:disable statements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/35"&gt;Feature/10 bmi name per specific bmi value&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/10"&gt;BMI name per specific bmi value.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/6"&gt;Think-through how to manage coordinates at db level.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/32"&gt;Merge all features-branches.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In-progress&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/40"&gt;BMI algorithm raise ZeroDivisionError #40&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Not-started-yet&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/39"&gt;[Web-Page] Docs- Token Authentication blocks static-files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/29"&gt;[Web-Page] log-in page.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/31"&gt;[Web-Page] Endorphine Badges Acquired&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/30"&gt;[Web-Page] Statistics about each route user have been&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/23"&gt;[REST-API] Endorphine-Badges Acquired&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/24"&gt;[REST-API] Routes User have been (based on gpx files)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/25"&gt;[REST-API] Routes User have been -test-for-user-authenticated-routes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/26"&gt;[REST-API] Possibility to put new routes using endpoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/27"&gt;[REST-API] Requests only per user&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/28"&gt;[REST-API] Secure REST API with https security on a server-site (i.e. nginx)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Milestone update.&lt;/h1&gt;
&lt;p&gt;As you may noticed it's also the same info as in the &lt;a href="https://github.com/anselmos/Biking-Endorphines/milestone/1"&gt;Python Milestone&lt;/a&gt; that I've recently updated due-day to 31 of may.&lt;/p&gt;
&lt;p&gt;I do hope this timing will be more realistic and more realistic estimated then what it was at previous stages!&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomatoid.com/pomodoro"&gt;Tomatoid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/pygithub_playground"&gt;pygithub-playground&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Thanks&lt;/h1&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="webserver"></category><category term="the-plan"></category></entry><entry><title>Biking Endorphines - Plans that were not Real-Life correlated.</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-plans-not-real-life-correlated.html" rel="alternate"></link><published>2017-05-20T18:00:00+02:00</published><updated>2017-05-20T18:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-20:/blog/biking-endorphines-plans-not-real-life-correlated.html</id><summary type="html">&lt;p&gt;I've messed up  :( I have to give myself this bad credit of a bit giving up blog and competition :( But let's raise up! Check out my estimates and where is this going now!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;What happen?&lt;/h1&gt;
&lt;p&gt;Let's start from &lt;a href="biking-endorphines-the-plan-for-future.html"&gt;last post about the plans&lt;/a&gt; - I did terrible thing of a bit giving up. And the only one to blame is myself.&lt;/p&gt;
&lt;p&gt;I've planned to produce till end of this week a python-part. &lt;/p&gt;
&lt;p&gt;My plan was too much optimistic that I'll have at least 1-2 hours per day to make commits and release code.
Also this features that I had to create were not well documented of what I'm suppose to actually do.&lt;/p&gt;
&lt;p&gt;Unfortunatelly there was few things that I did not anticipate in my plan - i.e. going to JUG conference.&lt;/p&gt;
&lt;p&gt;Lately I've found a youtube clip from &lt;a href="https://www.youtube.com/watch?v=4a9GTtTUsIc"&gt;Tim Ferris about productivity and procrastination&lt;/a&gt; that made me more optimistic about future!&lt;/p&gt;
&lt;p&gt;He says that every task should be splitted into&lt;code&gt;chunks&lt;/code&gt;. Then you need to make estimation of how much of this tasks you can do per day - and while making that you should make sure that it's less that you know you could produce - in that way you will everyday pass your task by making this &lt;code&gt;chunk&lt;/code&gt; of task and if lucky you may notice yourself exceeding this limit.&lt;/p&gt;
&lt;h1&gt;What now ?&lt;/h1&gt;
&lt;p&gt;From now I will not make any plans that are not at least estimated and prioritized.&lt;/p&gt;
&lt;p&gt;Let's find out if Github Issues can be handled with estimation points ?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;After 10 minutes of searching&lt;/em&gt; - Well there's no obvious option like "it will take me 1 hour of work".&lt;/p&gt;
&lt;p&gt;Unfortunatelly Github is not like a Redmine or Trac that gives option to setup things like that.&lt;/p&gt;
&lt;p&gt;Let's for now use labels instead.&lt;/p&gt;
&lt;h1&gt;Raise Up like Phoenix!&lt;/h1&gt;
&lt;p&gt;Yes! I'm now going to raise up and make an effort on focusing on python backend/rest-api part till end of May.&lt;/p&gt;
&lt;p&gt;Then go back to Android part, create simplest application that will bind with python-api and give end-user information about biking-routes/endorphines.&lt;/p&gt;
&lt;h1&gt;Final word&lt;/h1&gt;
&lt;p&gt;Now... I'm going to change issues and add labels. :)&lt;/p&gt;
&lt;p&gt;Less talking - more coding! :D&lt;/p&gt;
&lt;p&gt;BTW: I've lately started working on &lt;a href="https://github.com/anselmos/pygithub_playground"&gt;pygithub_playground for gathering github-issues&lt;/a&gt; - Checkout how fast and easy it is to get github issues from python command line!&lt;/p&gt;
&lt;p&gt;Thanks!&lt;/p&gt;
&lt;p&gt;See you soon!&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="the-plan"></category><category term="raise-up-like-a-phoenix"></category><category term="pygithub-playground"></category></entry><entry><title>Biking Endorphines - User API Serializer</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-user-api-serializer.html" rel="alternate"></link><published>2017-05-13T20:30:00+02:00</published><updated>2017-05-13T20:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-13:/blog/biking-endorphines-user-api-serializer.html</id><summary type="html">&lt;p&gt;Today I've started working on &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/22"&gt;User-API #22&lt;/a&gt;, then found that not all elements are working correctly and... that tests for User-API-serializer are not working correctly. Check what also was wrong ! :) You might be surpriced !&lt;/p&gt;</summary><content type="html">&lt;h1&gt;User Model and it's failure&lt;/h1&gt;
&lt;p&gt;I've started working on Users-API feature &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/22"&gt;#22&lt;/a&gt;. Found that the Token-Authentication blocked api-docs - so I've created bug &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/39"&gt;#39&lt;/a&gt;. 
I've temporarily commented out Token-Authentication and begun my work on User-API.&lt;/p&gt;
&lt;p&gt;Then to my surprise ... User's API didn't properly handle &lt;code&gt;bmi&lt;/code&gt; and the &lt;code&gt;bmi-health-name&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So I've figure out it had to be some issue on Serializer site or on the QuerySet.&lt;/p&gt;
&lt;p&gt;But no such luck, looking up this in internet lead me to some strange source-code changes that did nothing.&lt;/p&gt;
&lt;p&gt;So I've dig a little deeper and debug the &lt;code&gt;BMI algorithm itself&lt;/code&gt;. And voila! There was the problem!&lt;/p&gt;
&lt;p&gt;As it turns out, yesterday I've made some testing for User model and for &lt;code&gt;bmi-health-name&lt;/code&gt; function. While making that, I've used &lt;a href="https://pypi.python.org/pypi/mock"&gt;Mocking&lt;/a&gt; - which is in a general way a good idea. But to make use of Mocking you should be sure (having proper working tests!) that method/function you are mocking will output proper value. I didn't learn that lesson properly :)&lt;/p&gt;
&lt;p&gt;So the BMI-Algorithm returned 0 all the time. When I've figure out where was the problem all other elements start ticking as they should ! &lt;/p&gt;
&lt;p&gt;As it turns out - I didn't learned lesson about making Unit-Tests independent from source-code - why ? Because of my &lt;code&gt;laziness&lt;/code&gt; I've put some math-algorithm inside of test - instead of using hard-coded value.&lt;/p&gt;
&lt;p&gt;When I've finally found it out- I've change code and then tests started to fail with wrong output as expected. I've fixed that :)&lt;/p&gt;
&lt;h1&gt;Now what about that User API ?&lt;/h1&gt;
&lt;p&gt;Well, when changing all of this things I've said before, I've changed the standard &lt;code&gt;Serializer&lt;/code&gt; into a &lt;code&gt;ModelSerializer&lt;/code&gt;. I also added &lt;code&gt;Meta&lt;/code&gt;  as described in &lt;a href="http://www.django-rest-framework.org/api-guide/serializers/#modelserializer"&gt;ModelSerializer&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Then I've found that there is not tests for User Create/Update/Delete and retrieving list is not handled as it should.&lt;/p&gt;
&lt;p&gt;So I've put effort into making best of this tests that are a coverage for User-API.&lt;/p&gt;
&lt;p&gt;I also found bug &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/40"&gt;#40&lt;/a&gt; - when making tests for updating user.&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;Source Code of User API model:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    User model for obtaining personal information about biking riders&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Returns User information when using str/printing&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bmi&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Body Mass Index calculator simplified to number&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10000&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;bmi_health_name&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        BMI Health Name - Returns proper naming for value of BMI&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;18.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Underweight&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;18.5&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;24.9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Normal weight&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;24.9&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;29.9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Overweight&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;29.9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Obesity&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Source Code tests of User API:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Tests for API&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;api.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserSerializer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;api.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserDetail&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;web.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;AuthUser&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework.authtoken.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;APIClient&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;force_authenticate&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;General Test Case for API&amp;quot;&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/api/user/&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AuthUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_superuser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;admin&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;admin@admin.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;admin123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&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&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="s2"&gt;&amp;quot;Removes all AuthUser and Users objects at the end of each test&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&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;get_response_user_api&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;api_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pk_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot; Creates response for /api/user List get with forcing login with Token-Authentication &amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;force_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&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;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;api_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;HTTP_AUTHORIZATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Token {}&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;force_authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pk_id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pk_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&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;assert_status_code&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;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot; Asserts response status code with 200&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# pylint: disable=no-self-use&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user_in_db&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="s2"&gt;&amp;quot; Creates new user object in database &amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Bart&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;surname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Trab&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestUserSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;UserSerializer tests&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_user_serialize_to_json&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="s2"&gt;&amp;quot;test if serializing to JSON works&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;mocked&lt;/span&gt; &lt;span class="o"&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;mocked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;mocked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Somlesna&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;mocked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
        &lt;span class="n"&gt;mocked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;175&lt;/span&gt;

        &lt;span class="n"&gt;user_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mocked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_serialized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;height&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;surname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Somlesna&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;weight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Anselmos&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;bmi&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;&amp;#39;bmi_health_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Overweight&amp;#39;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestUserList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;UserList tests&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_user_get_return_json&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="s2"&gt;&amp;quot;test if using get returns json data&amp;quot;&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;force_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response_user_api&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_status_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&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;test_user_list_return_json_list&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="s2"&gt;&amp;quot; Test if setting up user returns user list&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;input_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_user_in_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;force_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response_user_api&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_status_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_user_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;input_user&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;test_get_two_user_list&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="s2"&gt;&amp;quot; Test if setting up user returns user list&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;input_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_user_in_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;input_user2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;B222art&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;surname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Trabaaaa&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response_user_api&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_status_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_user_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;input_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_user_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&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="n"&gt;input_user2&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;assert_user_object&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;input_json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;Asserts response User input json object == expected user model object. &amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;surname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;weight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;height&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bmi&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bmi_health_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi_health_name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestPostUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;User Post tests&amp;quot;&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="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&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;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_return_user_object&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="s2"&gt;&amp;quot; Tests if making api request returns user object &amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Test&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;surname&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tester1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;weight&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;height&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;173&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response_user_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDeleteUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;User Delete tests&amp;quot;&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="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&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;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserDetail&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&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;test_delete_user&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="s2"&gt;&amp;quot; Tests if making api request deletes user with 204&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_user_in_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/api/user/{}/&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response_user_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;204&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestUpdateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIGeneralTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;User Update tests&amp;quot;&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="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&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;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&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;test_update_user&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="s2"&gt;&amp;quot; Tests if making api request updates user with new name&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_user_in_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/api/user/{}/&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response_user_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;newName&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;weight&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;height&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;111&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
            &lt;span class="n"&gt;pk_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/d0520ab"&gt;Refactors code a bit. Changes few comments.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/e96349f"&gt;Adds Update checker for User API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/5359f44"&gt;Refactors code. Changes names to proper one.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/46f5975"&gt;Refactors code. Adds Delete-API test for User API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/0d31666"&gt;Refactors code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/59f54e1"&gt;Refactors code.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/a0b5740"&gt;Refactors code. Creates APIGeneralTestCase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/c8f2516"&gt;Adds test for creating user with API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/c7b3335"&gt;Refactors code.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/a8b501b"&gt;Adds tests for checking if user-list contains element from api&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/fee8a7a"&gt;Fixes #22. Fixes User-API and bmi-algorithm.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Release:&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/releases/tag/13-05-17-user-api"&gt;13-05-17-user-api&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomatoid.com/pomodoro"&gt;Tomatoid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements of links I've found usefull while writing this article:&lt;/h1&gt;
&lt;p&gt;Others:&lt;/p&gt;
&lt;p&gt;Django-Rest-Framework:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.django-rest-framework.org/api-guide/serializers/#modelserializer"&gt;Model Serializer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.django-rest-framework.org/api-guide/exceptions/#methodnotallowed"&gt;MethodNotAllowed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;StackOverFlow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods"&gt;Understanding Python super() with &lt;strong&gt;init&lt;/strong&gt;() methods [duplicate]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/4532681/how-to-remove-all-of-the-data-in-a-table-using-django"&gt;How to remove all of the data in a table using django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/2840467/problems-using-user-model-in-django-unit-tests"&gt;Problems using User model in django unit tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;Issue &lt;a href="https://github.com/anselmos/biking-endorphines/issues/22"&gt;#22&lt;/a&gt; - User API &lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;Final word&lt;/h1&gt;
&lt;p&gt;I wanted to make all of the issues that are there for &lt;a href="https://github.com/anselmos/Biking-Endorphines/milestone/1"&gt;1st Milestone&lt;/a&gt;.
Unfortunatelly I already see that it's impossible to make 6 big features in 4 hours (even less).&lt;/p&gt;
&lt;p&gt;I'll move end time till Wednesday and let's see how much progress I will make.&lt;/p&gt;
&lt;p&gt;Next time I'll just have to create less optimistic estimation of time per issue :)&lt;/p&gt;
&lt;p&gt;That's all, thanks ! Keep in touch :)&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="user-api"></category><category term="user-api-serializer"></category><category term="serializer"></category><category term="django-rest-framework"></category><category term="tdd-approach"></category><category term="tdd"></category><category term="integration-tests"></category></entry><entry><title>Biking Endorphines - User Model and TDD.</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-user-model-and-tdd.html" rel="alternate"></link><published>2017-05-12T20:00:00+02:00</published><updated>2017-05-12T20:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-12:/blog/biking-endorphines-user-model-and-tdd.html</id><summary type="html">&lt;p&gt;Recently I've created User model that wasn't tdd-friendly. All about the time - ironic isn't it? To save time of figuring out how to make proper tdd-approach to django-models, I've created model without them. What a shame! Today I'm going to fix that :) Also the bmi-specific name will be done :) Check it out :)&lt;/p&gt;</summary><content type="html">&lt;h1&gt;User Model and the Tdd&lt;/h1&gt;
&lt;p&gt;So I've got &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/10"&gt;BMI name per specific bmi value. #10&lt;/a&gt; issue.&lt;/p&gt;
&lt;p&gt;I've started work on it. Went to master branch. Created &lt;a href="https://github.com/anselmos/Biking-Endorphines/tree/feature/10-BMI-name-per-specific-bmi-value"&gt;feature-branch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And then.... I've found out django-models that has no test-coverage or other things like that and looks a bit more then little as not TDD-approach.&lt;/p&gt;
&lt;p&gt;Well... let's go and fix that, shall we ?&lt;/p&gt;
&lt;h1&gt;Fixing User Model not tested yet.&lt;/h1&gt;
&lt;p&gt;So I've figure out I'll first create test for checking if fields exists in model.&lt;/p&gt;
&lt;p&gt;Initially I've created test method that was a bit product-specific, but then finally I've moved it to a &lt;code&gt;GenericModelTestCase&lt;/code&gt; class and added test only in this generic-type class.&lt;/p&gt;
&lt;p&gt;Then in specific-model-class I only inherited by this generic-type class and added &lt;code&gt;cls&lt;/code&gt; and &lt;code&gt;fields&lt;/code&gt; fields :)&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;GenericModelTestCase&lt;/code&gt; looks like that (in &lt;code&gt;generics.py&lt;/code&gt; module):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;All generic type of classes used in django-tests&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;AuthUser&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenericModelTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Generic Model Test Case.&lt;/span&gt;
&lt;span class="sd"&gt;    Contains:&lt;/span&gt;
&lt;span class="sd"&gt;    - assert_fields - assertion for checking if all fields in model exists&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="bp"&gt;cls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AuthUser&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assert_fields&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;fields&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; asserting if fields exists in model&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;fields_in_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="c1"&gt;# fields as django fields:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_fields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;include_hidden&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;if&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;fields_in_model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# method as fields:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__dict__&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fields_in_model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;fields_in_model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields_in_model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&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;test_fields&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Uses asserting fields for checking with naming convention of django-type &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_fields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And the &lt;code&gt;UserModelTestCase&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Unit tests for User model&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;web.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;web.tests.django_type.generics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GenericModelTestCase&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserModelTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GenericModelTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; User Model TestCase &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="bp"&gt;cls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&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="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;surname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;weight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;height&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bmi&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Clean and simple ! :)&lt;/p&gt;
&lt;h1&gt;Now... how about that feature branch, huh?&lt;/h1&gt;
&lt;p&gt;Yeah I know I should not mix feature branch with a fixing lack-of-tests branch, but for sake of simplicity I'll skip that this time.&lt;/p&gt;
&lt;p&gt;Now moving to the feature it self.&lt;/p&gt;
&lt;p&gt;It should be pretty simple, isn't it ?&lt;/p&gt;
&lt;p&gt;Let's find it out ! :)&lt;/p&gt;
&lt;h1&gt;Feature branch code&lt;/h1&gt;
&lt;p&gt;At &lt;code&gt;models.py&lt;/code&gt;, User class :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    User model for obtaining personal information about biking riders&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Returns User information when using str/printing&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bmi&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Body Mass Index calculator simplified to number&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bmi_health_name&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        BMI Health Name - Returns proper naming for value of BMI&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;18.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Underweight&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;18.5&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;24.9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Normal weight&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;24.9&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;29.9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Overweight&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;29.9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Obesity&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;At &lt;code&gt;tests_user.py&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Unit tests for User model&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mock&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MagicMock&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;web.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;web.tests.django_type.generics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GenericModelTestCase&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserModelTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GenericModelTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; User Model TestCase &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="bp"&gt;cls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&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="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;surname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;weight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;height&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bmi&amp;#39;&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&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;SetUp&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&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;assert_bmi_health&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;bmi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot; Asserts BMI health name&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MagicMock&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="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi_health_name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_bmi_health_name&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot; tests for bmi_health_name method &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_bmi_health&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_bmi_health&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Underweight&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_bmi_health&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="s2"&gt;&amp;quot;Underweight&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_bmi_health&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;18.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Underweight&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_bmi_health&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;18.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Normal weight&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_bmi_health&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;25.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Overweight&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_bmi_health&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;30.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Obesity&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/0cf0774"&gt;Refactors code. Removes useless pylint disable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/615a5bb"&gt;Refactors code.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/123295b"&gt;Moves bmi_health_name into User Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/049c6f8"&gt;Fixes test for obesity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/34bcd76"&gt;Adds failing test for obesity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/7d7cce8"&gt;Fixes overweight test case&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/e5519d3"&gt;Adds failing overweight test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/df4a38d"&gt;Fixes normal weight test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/fa417f6"&gt;Adds failing test for normal weight&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/cf66fc7"&gt;Refactors code for bmi-health-name&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/db0979c"&gt;Adds tests for underweight for bmi-health-name&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/ed38769"&gt;Adds passing test for 0 element&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/c526397"&gt;Adds failing test for bmi_health_name&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/8ce4be8"&gt;Fixes pylint issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/54f6c10"&gt;Refactors code. Moves generic class to generics module.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/bba2e3f"&gt;Refactors code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/8461f39"&gt;Adds fields as methods check for existing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/7fafe7a"&gt;Adds User Model testing fields&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomatoid.com/pomodoro"&gt;Tomatoid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Release&lt;/h1&gt;
&lt;p&gt;You can find &lt;a href="https://github.com/anselmos/Biking-Endorphines/releases/tag/12-05-17-bmi-health-name"&gt;release of source code here&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Acknowledgements of links I've found usefull while writing this article:&lt;/h1&gt;
&lt;p&gt;DjangoProjects.com:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields"&gt;Model &lt;code&gt;_meta&lt;/code&gt; API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;StackOverFlow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/29034721/check-if-model-field-exists-in-django"&gt;Check if model field exists in Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/1436444/python-passing-a-class-name-as-a-parameter-to-a-function"&gt;Python: Passing a class name as a parameter to a function?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/1388818/how-can-i-compare-two-lists-in-python-and-return-matches"&gt;How can I compare two lists in python and return matches&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/3647805/get-models-fields-in-django"&gt;Get model's fields in Django&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt; TDD Approach for Django Models! &lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;Final word! -&amp;gt; NEW BADGE UNLOCKED!&lt;/h1&gt;
&lt;p&gt;You have one new badge unlocked ! - Making Django Generic Model Test Case! - Huuuraaay ! :)&lt;/p&gt;
&lt;p&gt;Check my 1st Milestone &lt;a href="https://github.com/anselmos/Biking-Endorphines/milestone/1"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Will I be able to complete it till Sunday?&lt;/p&gt;
&lt;p&gt;Give a comment in box below :)&lt;/p&gt;
&lt;p&gt;Thanks ! Keep in touch :)&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="user-model"></category><category term="tdd-approach"></category><category term="tdd"></category><category term="django-model-testing"></category><category term="testing-django-models"></category></entry><entry><title>Biking Endorphines - Pull Requests and Merge Conflicts!</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-pull-requests-and-merge-conflicts.html" rel="alternate"></link><published>2017-05-11T22:00:00+02:00</published><updated>2017-05-11T22:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-11:/blog/biking-endorphines-pull-requests-and-merge-conflicts.html</id><summary type="html">&lt;p&gt;Checkout what happened when I've made too much commits on the same files and how YOU TOO can merge a conflicted pull-requests!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;What are conflicts ?&lt;/h1&gt;
&lt;p&gt;If you are not familiar with git conflicts, than you were very lucky using git or you didn't use it in such ways that you could fly instead of run.&lt;/p&gt;
&lt;p&gt;Conflicts are such a wonderfull things, that sometimes you just can't help yourself by swearing at them (NOT people who did commits - obviously!).&lt;/p&gt;
&lt;p&gt;But to be more professional - let's go back and explain - Conflicts... hmmm&lt;/p&gt;
&lt;p&gt;Well you have your branch, let's say it's a &lt;code&gt;master&lt;/code&gt; branch. You create new branch called "feature/New-Wonderful-Functionality".&lt;/p&gt;
&lt;p&gt;Let's say you create 2 commits and one of them makes changes in &lt;code&gt;README.md&lt;/code&gt; file in line &lt;code&gt;2&lt;/code&gt;.
Then your manager/supervisor/whoever goes to your room/cubic/table and says has a quick hot-fix that needs urgent change in README.md file.&lt;/p&gt;
&lt;p&gt;So you create a new branch based on &lt;code&gt;master&lt;/code&gt; called "hotfix/Fixing-Bad-Name-in-README".
You make changes in &lt;code&gt;README.md&lt;/code&gt; file in &lt;code&gt;2&lt;/code&gt; line. You commit your changes, push changes to remote branch and then make pull-request and merge them finally to &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And then you forget about it. You go back to your &lt;code&gt;new-wonderful-functionality&lt;/code&gt; branch. Make some additional commits (say - 2). You push your branch to remote branch.&lt;/p&gt;
&lt;p&gt;Then you want to make pull-request to master. And That's when magic  happens.&lt;/p&gt;
&lt;p&gt;Your &lt;code&gt;master&lt;/code&gt; branch has already changes in &lt;code&gt;README.md&lt;/code&gt; at line &lt;code&gt;2&lt;/code&gt; that are different then what you are having. Git don't know which change has priority and thus fires with "I"m not going to merge your code automatically - your changes conflicts with what you already have in your branch!" :)&lt;/p&gt;
&lt;p&gt;So you have to work with this to fix issue. In most cases you will take only elements from your "hotfix" and leave your "new-wonderful-functionality" in next line.&lt;/p&gt;
&lt;p&gt;Also check in Acknowledgements links that may or may not explain it better.&lt;/p&gt;
&lt;h1&gt;What type of conflicts I've encountered ?&lt;/h1&gt;
&lt;p&gt;Well let's see it in action, shall we ?&lt;/p&gt;
&lt;p&gt;&lt;link rel="stylesheet" type="text/css" href="css/asciinema-player.css" /&gt;
&lt;asciinema-player src="asciinema/bikingendorphines-pull-requests-conflicts.json"&gt;&lt;/asciinema-player&gt;
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;After making this recording I also needed to make a pushing with &lt;code&gt;force&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git push origin +HEAD:branch
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Notice the &lt;code&gt;+HEAD&lt;/code&gt; - sign &lt;code&gt;+&lt;/code&gt; makes forcing pushing to remote branch regretless of what was before on that particular branch.&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomatoid.com/pomodoro"&gt;Tomatoid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements of links I've found usefull while writing this article:&lt;/h1&gt;
&lt;p&gt;Other:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.atlassian.com/blog/2015/01/a-better-pull-request/"&gt;A better pull request&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;StackOverFlow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/161813/how-to-resolve-merge-conflicts-in-git"&gt;How to resolve merge conflicts in Git&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt; Merging all feature-branches at biking-endorphines&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What about you? How do YOU manage your conflicts?&lt;/h1&gt;
&lt;p&gt;Give me your comment, how do you manage your conflicts? Do you use a GUI tools ? Do you make it via console/command line?&lt;/p&gt;
&lt;p&gt;If you reached this point - I personally want to thank you for time you've spend!&lt;/p&gt;
&lt;p&gt;Thanks ! Keep in touch :)&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="git"></category><category term="pull-requests"></category><category term="git-merge-conflict"></category><category term="merge-conflict"></category><category term="conflict"></category><category term="merge-manually"></category></entry><entry><title>Pelican Plugins playground still continue - Asciinema!</title><link href="http://witkowskibartosz.com/blog/pelican-plugins-playground-still-continue.html" rel="alternate"></link><published>2017-05-10T22:00:00+02:00</published><updated>2017-05-10T22:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-10:/blog/pelican-plugins-playground-still-continue.html</id><summary type="html">&lt;p&gt;Checkout what plugin I'm currently working on for Pelican! ASCIINEMA!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Asciinema, what is that?&lt;/h1&gt;
&lt;p&gt;Asciinema is a tty(console session) recorder that enables to copy-paste a recorded commands when watching them played.&lt;/p&gt;
&lt;p&gt;Best of all, you can use not only &lt;a href="https://asciinema.org/"&gt;their site&lt;/a&gt;, but you can also make your own player at your site &lt;a href="http://blog.asciinema.org/post/self-hosting/"&gt;more about that here&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;How to use Asciinema?&lt;/h1&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;css/asciinema-player.css&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;asciinema-player&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;asciinema/biking_endorphines_pyreverse.json&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;asciinema-player&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;scripts/asciinema-player.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Pretty easy huh? Well, yea, you may use then only this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;asciinema-player&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;asciinema/biking_endorphines_pyreverse.json&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;asciinema-player&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And that is fine. Now why would I create a plugin for such a thing? To make my life a bit easier, and not having to repeat myself by adding over and over again the css and js files into markdown files or the theme itself (theme then is changeable, I'm not stuck with only this changed theme).&lt;/p&gt;
&lt;h1&gt;Demo?? Where can I see how it works ??&lt;/h1&gt;
&lt;p&gt;You could check how it works &lt;a href="modelling-tools-for-software-pyreverse-for-bikingendorpines.html"&gt;at my previous post&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What are key concepts?&lt;/h1&gt;
&lt;p&gt;I want to have added javascript and css stylesheets whenever a &lt;asciinema-player&gt; tag will be found in markdown file. When not, then plugin should not add anything to content of markdown files at the generation stage.&lt;/p&gt;
&lt;h1&gt;What's now?&lt;/h1&gt;
&lt;p&gt;Well I have'nt got enough proper time to sit down and make this plugin yet. But I've created &lt;a href="https://github.com/anselmos/pelican-asciinema"&gt;pelican-asciinema repository at github&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomatoid.com/pomodoro"&gt;Tomatoid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'll give feedback next Wednesday :)&lt;/p&gt;
&lt;p&gt;Thanks!&lt;/p&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Start working on plugin for asciinema player.&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. See &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/issues"&gt;ISSUES&lt;/a&gt; task-list for this 'mini' growing project :)&lt;/h4&gt;</content><category term="anselmos-pelican-blog-source"></category><category term="mini-project"></category><category term="pelican"></category><category term="pelican-plugin"></category><category term="asciinema"></category><category term="asciinema-pelican-plugin"></category></entry><entry><title>Biking Endorphines - The Plan for Future!</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-the-plan-for-future.html" rel="alternate"></link><published>2017-05-07T17:15:00+02:00</published><updated>2017-05-07T17:15:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-07:/blog/biking-endorphines-the-plan-for-future.html</id><summary type="html">&lt;p&gt;Check now what are the detailed plans for Biking Endorphines for this month (May 2017)!&lt;/p&gt;</summary><content type="html">&lt;h1&gt;The Plan!&lt;/h1&gt;
&lt;p&gt;Lately I've found that there is only &lt;strong&gt;3 weeks&lt;/strong&gt; left for BikingEndorphines project to be done for &lt;a href="http://devstyle.pl/daj-sie-poznac/"&gt;GetNoticed2017 contest&lt;/a&gt;. &lt;img alt="GetNoticed 2017" src="images/dsp2017-2.png"&gt;&lt;/p&gt;
&lt;p&gt;Here you can check &lt;a href="http://uczestnicy.dajsiepoznac.pl/profil/bartosz-witkowski"&gt;my Get-Noticed profile&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So I'm currently changing my working into a weekly sprints (something similar to a &lt;a href="https://en.wikipedia.org/wiki/Scrum_(software_development)"&gt;scrum-based development workflow&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After each week, bunch of features will be done. I'll try my best to make as much articles about that features :)&lt;/p&gt;
&lt;p&gt;At the end of each week I'll give You feedback, about my progress in list of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Completed&lt;/li&gt;
&lt;li&gt;In-progress&lt;/li&gt;
&lt;li&gt;Not-started-yet&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So stay tuned! A lot of new content is comimg :)&lt;/p&gt;
&lt;h1&gt;Details of the Plan!&lt;/h1&gt;
&lt;p&gt;Since there is only 3 weeks left to at least complete key-features, I presume the best will be to make each week about the same things.
This will help me to keep up and stay focused on one stage of project for few days and then go to other stage of project.&lt;/p&gt;
&lt;h1&gt;Week for Python&lt;/h1&gt;
&lt;p&gt;Key features to be done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;REST API with :&lt;ul&gt;
&lt;li&gt;Users&lt;/li&gt;
&lt;li&gt;Endorphine-Badges Acquired&lt;/li&gt;
&lt;li&gt;Routes User have been (based on gpx files)&lt;/li&gt;
&lt;li&gt;Possibility to put new routes using endpoint and a gpx input-file.&lt;/li&gt;
&lt;li&gt;API requests per-user.&lt;/li&gt;
&lt;li&gt;Secure REST API with https security on a server-site (i.e. nginx)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nice to have, if time will be given:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Frontend web-page with:&lt;ul&gt;
&lt;li&gt;log-in page.&lt;/li&gt;
&lt;li&gt;Statistics about each route user have been&lt;/li&gt;
&lt;li&gt;Endorphine Badges Acquired&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Week for Android&lt;/h1&gt;
&lt;p&gt;Key features to be done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Android UI mockups.&lt;/li&gt;
&lt;li&gt;Connection to REST API using some library &lt;a href="https://android-arsenal.com/tag/85?sort=rating&amp;amp;category=1"&gt;check at android-arsenal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Starting/Stopping route recording&lt;/li&gt;
&lt;li&gt;Sending gpx route to REST API automatically whenever Wifi/Internet is available&lt;/li&gt;
&lt;li&gt;Gathering routes history.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nice to have, if time will be given:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Preferences of sending gpx files (if using wifi or not)&lt;/li&gt;
&lt;li&gt;Gathering Badges Acquired information&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Week for mashup!&lt;/h1&gt;
&lt;p&gt;Key features to be done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Android and Python backend syncing data between each-other&lt;/li&gt;
&lt;li&gt;Moving locally accessible rest-service to outside-world i.e. using Heroku.&lt;/li&gt;
&lt;li&gt;Problems that for now I'm not fully aware and may raise while working on those 2 weeks above.&lt;/li&gt;
&lt;li&gt;Resolving as much as possible of 'nice to have' from past 2 weeks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomatoid.com/pomodoro"&gt;Tomatoid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Let's go and TDD the whole WORLD ! :D&lt;/h1&gt;
&lt;p&gt;All features will be done in a &lt;a href="tag/tdd.html"&gt;Test-Driven-Development&lt;/a&gt; workflow&lt;/p&gt;
&lt;h1&gt;Acknowledgements of links I've found usefull while writing this article:&lt;/h1&gt;
&lt;p&gt;Other:
- &lt;a href="https://robinpowered.com/blog/best-practice-system-for-organizing-and-tagging-github-issues/"&gt;Best Practice System for Organizing and Tagging github Issues&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://android-arsenal.com/"&gt;Android Arsenal&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.conceptdraw.com/examples/scrum-based-development"&gt;Scrum-Based Development&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;StackOverFlow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/27716001/how-to-post-https-request-using-retrofit"&gt;How-to-Post-HTTPS-request-using-retrofit&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/20778072/sniffing-an-android-app-to-find-api-url"&gt;Sniffing-an-Android-App-to-Find-Api-URL&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Plans for Biking-Endorphines.&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Badge Gathering source-code and tests.&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="biking-endorphines-database"></category><category term="biking-endorphines-plan"></category><category term="the-plan"></category><category term="weekly-sprints"></category><category term="scrum-based-sprints"></category><category term="tdd"></category></entry><entry><title>Biking Endorphines - How to secure our REST-API?</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-secure-biking-endorphines-api.html" rel="alternate"></link><published>2017-05-05T21:00:00+02:00</published><updated>2017-05-05T21:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-05:/blog/biking-endorphines-secure-biking-endorphines-api.html</id><summary type="html">&lt;h1&gt;Security - why should I care?&lt;/h1&gt;
&lt;p&gt;Let's say that you will want to make your REST-API available for others to use it. Let's face it - you will need to restrict use of API based on users.
If you don't do that, you may face the reality of having issues with your …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Security - why should I care?&lt;/h1&gt;
&lt;p&gt;Let's say that you will want to make your REST-API available for others to use it. Let's face it - you will need to restrict use of API based on users.
If you don't do that, you may face the reality of having issues with your data that's used by your API.&lt;/p&gt;
&lt;h1&gt;Let's play old game "What if".&lt;/h1&gt;
&lt;p&gt;You have your API for User accounts. You don't restrict access.
What if someone discover API that you didn't published and reuse it in his own purpose ? i.e. for making dangerous calls that may lead to DATA LOSS ?&lt;/p&gt;
&lt;p&gt;You may have some type of recovery mode (backups/snapshots), but what if this problem will not end in an "one-time-shot"?&lt;/p&gt;
&lt;p&gt;So let's move to some possibilities to restrict access to your API !&lt;/p&gt;
&lt;h1&gt;What Django REST API can give out of the box?&lt;/h1&gt;
&lt;p&gt;In article - &lt;a href="http://www.django-rest-framework.org/api-guide/authentication/"&gt;Authentication with Django-Rest-Framework&lt;/a&gt; you can find information how to add some security by using Authentication there.&lt;/p&gt;
&lt;p&gt;There are :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BasicAuthentication&lt;/li&gt;
&lt;li&gt;TokenAuthentication&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the purpose of checking out, I'll use the TokenAuthentication even if it's not best secure. But still it's available within rest-framework (out of the box thinking :) )&lt;/p&gt;
&lt;h1&gt;What are alternatives to django-rest-framework security?&lt;/h1&gt;
&lt;p&gt;Well there is a lot of frameworks that supports OAuth, but not all will natively support API.&lt;/p&gt;
&lt;p&gt;Below you can check some of them that are mentioned at the "Authentication" article at Django-Rest-Framework:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://django-oauth-toolkit.readthedocs.io/en/latest/"&gt;Django-OAuth-Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jpadilla.github.io/django-rest-framework-oauth/"&gt;RestFramework OAuth by jpadilla&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Source code I've applied to Biking Endorphines.&lt;/h1&gt;
&lt;p&gt;At &lt;code&gt;/bikingendorphines/api/models.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db.models.signals&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;post_save&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.dispatch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;receiver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework.authtoken.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&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;# This code is triggered whenever a new user has been created and saved to the database&lt;/span&gt;

&lt;span class="nd"&gt;@receiver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_save&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AUTH_USER_MODEL&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;create_auth_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&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;if&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;At &lt;code&gt;/bikingendorphines/bikingendorphines/settings.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# in `INSTALLED_APPS` this:&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;rest_framework.authtoken&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;# And added this&lt;/span&gt;

&lt;span class="n"&gt;REST_FRAMEWORK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;DEFAULT_PERMISSION_CLASSES&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;rest_framework.permissions.IsAuthenticated&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;DEFAULT_AUTHENTICATION_CLASSES&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;rest_framework.authentication.TokenAuthentication&amp;#39;&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;/pre&gt;&lt;/div&gt;


&lt;p&gt;All I needed to do is create a new superuser and Grab Token from database, then apply it to requests like this (&lt;a href="https://github.com/jakubroztocil/httpie"&gt;httpie&lt;/a&gt; in example used)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;http GET &lt;span class="m"&gt;127&lt;/span&gt;.0.0.1:8000/api/user/ &lt;span class="s1"&gt;&amp;#39;Authorization: Token XXXXX&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;Check out my release for this article: &lt;a href="https://github.com/anselmos/Biking-Endorphines/releases/tag/5-05-17-secure-api"&gt;5-05-17 secure-api&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/55f6a93"&gt;Adds TokenAuthentication to project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomatoid.com/pomodoro"&gt;Tomatoid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/14838128/django-rest-framework-token-authentication"&gt;Django-Rest-Framework Token Authentication- at StackOverFlow&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. How to secure biking-endorphines REST-API.&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Plans for Biking-Endorphines&lt;/h4&gt;
&lt;h4&gt;2. Badge Gathering source-code and tests.&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="biking-endorphines-database"></category><category term="API"></category><category term="REST"></category><category term="SOAP"></category><category term="webservice"></category><category term="secure-api"></category><category term="REST-API-security"></category><category term="security"></category><category term="TokenAuthentication"></category><category term="BasicAuthentication"></category></entry><entry><title>FancyBox Plugin Heads Up!</title><link href="http://witkowskibartosz.com/blog/fancybox-plugin-heads-up.html" rel="alternate"></link><published>2017-05-03T21:30:00+02:00</published><updated>2017-05-03T21:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-05-03:/blog/fancybox-plugin-heads-up.html</id><summary type="html">&lt;h1&gt;FancyBox Pelican Plugin&lt;/h1&gt;
&lt;p&gt;Yes! It's a ready-to-use product :)&lt;/p&gt;
&lt;p&gt;So... how to use it ??&lt;/p&gt;
&lt;h1&gt;FancyBox Plugin Installation!&lt;/h1&gt;
&lt;p&gt;I will add a README information in github project, but for now let's go to specifics of HOW TO:&lt;/p&gt;
&lt;p&gt;Best is if you use release 1.0 version or code from master, in below …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;FancyBox Pelican Plugin&lt;/h1&gt;
&lt;p&gt;Yes! It's a ready-to-use product :)&lt;/p&gt;
&lt;p&gt;So... how to use it ??&lt;/p&gt;
&lt;h1&gt;FancyBox Plugin Installation!&lt;/h1&gt;
&lt;p&gt;I will add a README information in github project, but for now let's go to specifics of HOW TO:&lt;/p&gt;
&lt;p&gt;Best is if you use release 1.0 version or code from master, in below example I'll use release:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;wget https://github.com/anselmos/pelican-fancybox/archive/v1.0.zip
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then unzip file.&lt;/p&gt;
&lt;p&gt;You should have a directory called "v1.0" or other that you have named your zip file.&lt;/p&gt;
&lt;p&gt;Change name into &lt;code&gt;fancybox&lt;/code&gt; and move it to your &lt;code&gt;pelican-plugins&lt;/code&gt; directory&lt;/p&gt;
&lt;p&gt;Now add plugin as usually into pelican:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;PLUGIN_PATHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pelican-plugins&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;PLUGINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fancybox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That's for only this plugin, but if you have more plugins then this, you just add &lt;code&gt;fancybox&lt;/code&gt; or other name of directory inside of which fancybox source code exists, into &lt;code&gt;PLUGINS&lt;/code&gt; list.&lt;/p&gt;
&lt;p&gt;And voilà. You should be ready to use plugin!&lt;/p&gt;
&lt;h1&gt;Fancybox Plugin Usage!&lt;/h1&gt;
&lt;p&gt;But wait ... so how can you use it ??&lt;/p&gt;
&lt;p&gt;That's the magic! You only add something like this into article:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Title: First
Date: 2017-04-03
When writing a post or page, add a footnote like this:

test


&lt;span class="nt"&gt;&amp;lt;fancybox&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;http://img06.deviantart.net/63b8/i/2012/178/2/8/jarvis___shield_interface___rainmeter_theme_by_edreyes-d54z5ky.jpg&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Url&lt;span class="nt"&gt;&amp;lt;/fancybox&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;Final result is available at &lt;a href="https://github.com/anselmos/pelican-fancybox"&gt;master branch of project&lt;/a&gt; or at &lt;a href="https://github.com/anselmos/pelican-fancybox/releases/tag/v1.0"&gt;v1.0 release tag&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/b5cfe2d"&gt;Merge pull request #2 from anselmos/tdd-approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/a763acb"&gt;Adds test for fancybox plugin itself.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/1f687e4"&gt;Fixes test for no-fancyboxscript if no fancybox element in article found&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/465c796"&gt;Adds failing test for no-fancyboxscript if no fancybox element in article&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/ebc8d5f"&gt;Adds test that passes for check if no fancybox exists with replace function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/1c498ad"&gt;Refactors code. Moves test upper. Adds Comment about function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/6b56fca"&gt;Refactors code with 'assert_dependency'&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/5b694ed"&gt;Fixes test for no-fancybox - no adding dependency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/c9f03e2"&gt;Adds failing test of checking if no fancybox is added dont add dependency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/ff4e7d3"&gt;Refactors code. Fixes problem with no dependency files in system with CDN files&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Little UPDATE  :)&lt;/h1&gt;
&lt;p&gt;I've finished drawing a pseudo logo for my plugin that you can check &lt;a href="images/fancybox_pelican_plugin_handraw_published.png"&gt;here&lt;/a&gt;. or &lt;a href="https://www.instagram.com/p/BTpO-GYh9iV/?taken-by=anselmos88"&gt;at Instagram&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hope you'll like it ! &lt;/p&gt;
&lt;p&gt;Please leave a comment below :)&lt;/p&gt;
&lt;p&gt;Thanks!&lt;/p&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt; 1. Make final commit for source-code of fancybox plugin&lt;/s&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;s&gt; 2. Draw a logo for pelican-fancybox-plugin&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Start working on plugin for asciinema player.&lt;/h4&gt;
&lt;h4&gt;2. See &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/issues"&gt;ISSUES&lt;/a&gt; task-list for this 'mini' growing project :)&lt;/h4&gt;</content><category term="anselmos-pelican-blog-source"></category><category term="mini-project"></category><category term="pelican"></category><category term="fancy-box"></category><category term="fancybox-plugin"></category><category term="image-viewer-plugin"></category><category term="tdd"></category><category term="tdd-approach"></category><category term="pelican-plugin"></category></entry><entry><title>Refreshed Blog Look!</title><link href="http://witkowskibartosz.com/blog/refresh-blog-look.html" rel="alternate"></link><published>2017-04-30T10:30:00+02:00</published><updated>2017-04-30T10:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-30:/blog/refresh-blog-look.html</id><summary type="html">&lt;h1&gt;Refreshed Look!&lt;/h1&gt;
&lt;p&gt;I've decided that my blog needs a little bit refreshing and adding some cool stuff.&lt;/p&gt;
&lt;p&gt;So I've used knowledge from my previous project - &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/"&gt;anselmos-pelican-blog&lt;/a&gt; and used it well (at least I hope I did :) )&lt;/p&gt;
&lt;p&gt;You can compare how this blog looked like before change and after in this …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Refreshed Look!&lt;/h1&gt;
&lt;p&gt;I've decided that my blog needs a little bit refreshing and adding some cool stuff.&lt;/p&gt;
&lt;p&gt;So I've used knowledge from my previous project - &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/"&gt;anselmos-pelican-blog&lt;/a&gt; and used it well (at least I hope I did :) )&lt;/p&gt;
&lt;p&gt;You can compare how this blog looked like before change and after in this images:&lt;/p&gt;
&lt;p&gt;&lt;a href="images/before_refresh_30_04.png"&gt;Before&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="images/after_refresh_30_04.png"&gt;After&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's next ??&lt;/h1&gt;
&lt;p&gt;Well... let's see :&lt;/p&gt;
&lt;h3&gt;1. &lt;a href="https://github.com/anselmos/pelican-fancybox"&gt;Pelican-Fancybox plugin&lt;/a&gt; that I'm currently working on (finalizing)&lt;/h3&gt;
&lt;h3&gt;2. Usage of Github "Gists" with &lt;a href="https://github.com/streeter/pelican-gist"&gt;Pelican-Gist Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;h3&gt;3. Other that I might forgot... :)&lt;/h3&gt;
&lt;h1&gt;Thanks!&lt;/h1&gt;
&lt;p&gt;Do you like the refreshed style of blog ? Give a comment, don't be shy! :)&lt;/p&gt;
&lt;p&gt;Stay Tuned! Soon new posts !&lt;/p&gt;</content><category term="blog"></category><category term="refresh-look"></category><category term="new-blog-features"></category></entry><entry><title>Biking Endorphines - REST-API Documentation</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-rest-api-documentation.html" rel="alternate"></link><published>2017-04-28T00:00:00+02:00</published><updated>2017-04-28T00:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-28:/blog/biking-endorphines-rest-api-documentation.html</id><summary type="html">&lt;h1&gt;What can you use for API documentation?&lt;/h1&gt;
&lt;p&gt;According to topic &lt;a href="http://www.django-rest-framework.org/topics/documenting-your-api/"&gt;Documenting your API at Django-Rest-Framework&lt;/a&gt; you have following options to use as API documentation:&lt;/p&gt;
&lt;h3&gt;1. Django REST Framework documentation&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;This is the most basic documentation that you can get &amp;quot;out of the box&amp;quot; - almost.
The only dependency needed here is …&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;h1&gt;What can you use for API documentation?&lt;/h1&gt;
&lt;p&gt;According to topic &lt;a href="http://www.django-rest-framework.org/topics/documenting-your-api/"&gt;Documenting your API at Django-Rest-Framework&lt;/a&gt; you have following options to use as API documentation:&lt;/p&gt;
&lt;h3&gt;1. Django REST Framework documentation&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;This is the most basic documentation that you can get &amp;quot;out of the box&amp;quot; - almost.
The only dependency needed here is the &amp;quot;renderer&amp;quot; - to be more precise - the `coreapi`.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;2. DRF Docs&lt;/h3&gt;
&lt;p&gt;Quoting information Django-REST-Framework Documentation topic:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;DRF Docs allows you to document Web APIs made with Django REST Framework and it is authored by Emmanouil Konstantinidis.
It&amp;#39;s made to work out of the box and its setup should not take more than a couple of minutes.
Complete documentation can be found on the website while there is also a demo available for people to see what it looks like.
Live API Endpoints allow you to utilize the endpoints from within the documentation in a neat way.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;3. Django REST Swagger&lt;/h3&gt;
&lt;p&gt;Quoting information Django-REST-Framework Documentation topic:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Marc Gibbons&amp;#39; Django REST Swagger integrates REST framework with the Swagger API documentation tool. The package produces well presented API documentation, and includes interactive tools for testing API endpoints.
Django REST Swagger supports REST framework versions 2.3 and above.
Mark is also the author of the REST Framework Docs package which offers clean, simple autogenerated documentation for your API but is deprecated and has moved to Django REST Swagger.
Both this package and DRF docs are fully documented, well supported, and come highly recommended.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;4. DRF AutoDocs&lt;/h3&gt;
&lt;p&gt;Quoting information Django-REST-Framework Documentation topic:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Oleksander Mashianovs&amp;#39; DRF Auto Docs automated api renderer.
Collects almost all the code you written into documentation effortlessly.
Supports:

- functional view docs
- tree-like structure
- Docstrings:
- markdown
- preserve space &amp;amp; newlines
- formatting with nice syntax
- Fields:
- choices rendering
- help_text (to specify SerializerMethodField output, etc)
- smart read_only/required rendering
- Endpoint properties:
- filter_backends
- authentication_classes
- permission_classes
- extra url params(GET params)
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Why we chose DRF for documentation of Biking-Endorphines&lt;/h1&gt;
&lt;p&gt;Other options ( DRF Docs and Django REST Swagger) uses swagger-ui for documentation. In my professional career I've already used swagger-ui.&lt;/p&gt;
&lt;p&gt;I'd probably do some follow-up about how to use other options, but this time I want to use something out-of-box.&lt;/p&gt;
&lt;h1&gt;How do we implement documentation of our project??&lt;/h1&gt;
&lt;p&gt;Just like in other's options, first you need to document your API! So let's check how it will look like, shall we?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListCreateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    get:&lt;/span&gt;
&lt;span class="sd"&gt;    Return a list of all existing users.&lt;/span&gt;

&lt;span class="sd"&gt;    post:&lt;/span&gt;
&lt;span class="sd"&gt;    Create a new user instance.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserSerializer&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now that we finally add documentation (it was just few comment-code on class ), we can add dependencies to our django application:&lt;/p&gt;
&lt;p&gt;(At urls.py):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework.documentation&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;include_docs_urls&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^admin/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^api/user/$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^docs/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include_docs_urls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;API Documentation&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="c1"&gt;# TEST&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Also for API to be accessible and handled you need to install coreapi that's used as default for rendering.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install coreapi
pip install coreapi-cli
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;I've figure out best solution to deliver code that is not yet merged into master is by using Annotated tagging.&lt;/p&gt;
&lt;p&gt;So to get source-code you can wget'it or check it &lt;a href="https://github.com/anselmos/Biking-Endorphines/releases/tag/28-04-17-api-documentation"&gt;at this tag-release information&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/5dcafbe"&gt;Adds coreapi-cli for Heroku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/6250d0a"&gt;Adds cd to project dir in Procfile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/1ffc485"&gt;Clears path second time in Procfile.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/945d5b2"&gt;Clears path to project in Procfile.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/c002000"&gt;Adds gunicorn to requirements.txt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/b0bd92c"&gt;Adds Procfile and runtime.txt for Heroku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/b3aac38"&gt;Adds STATIC_ROOT for fixing heroku collect-static.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/0474491"&gt;Adds API-documentation. Adds UserDetail url.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/33f9742"&gt;Adds generic-view of API and adds verbosity=2 to django-tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. Heroku - how things failed.&lt;/h3&gt;
&lt;p&gt;I had too-ambitious plan of deploying source-code to Heroku to have a working example od Documentation out-of-the-box.&lt;/p&gt;
&lt;p&gt;Unfortunatelly last time I've used Heroku was in January 2016, so I didn't remember a lot about it.&lt;/p&gt;
&lt;p&gt;Also proper setup of project was needed from beginning, moving on with tutorial step-by-step.&lt;/p&gt;
&lt;p&gt;As our project is not best compatible with heroku setup, I've found myself in situation where there is more work needed to properly deploy content.&lt;/p&gt;
&lt;p&gt;Everything would work, but unfortunatelly the static pages setup was not good enought for documentation, which you can check &lt;a href="https://pacific-fortress-36357.herokuapp.com/docs/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;Follow tutorial about &lt;a href="https://devcenter.heroku.com/articles/deploying-python"&gt;How to use Heroku in Django-Based projects&lt;/a&gt;.
For those impatient, you can use &lt;a href="https://github.com/heroku/heroku-django-template"&gt;template for Django 1.10 that is supported with Heroku&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I will make a follow-up article about how to properly setup your project using Heroku, and also how to fix your project if have different directory structure (as BikingEndorphines has).&lt;/p&gt;
&lt;h1&gt;Tips &amp;amp; Tricks&lt;/h1&gt;
&lt;h3&gt;1. Too Many Ancestors!  Pylint Error.&lt;/h3&gt;
&lt;p&gt;So After using documentation and trying the generic-class based Django REST Framework I've found myself having this issue.&lt;/p&gt;
&lt;p&gt;Initialy I've made a workaround using &lt;code&gt;# pylint disable=too-many-ancestors&lt;/code&gt;, but then I've figure out - It's ugly, it should be setup in pylintrc!&lt;/p&gt;
&lt;p&gt;And so the hunt for setup in pylintrc began, finally checking &lt;a href="http://stackoverflow.com/questions/22834392/understanding-too-many-ancestors-from-pylint"&gt;this article at StackOverFlow&lt;/a&gt; I've found resolution - by changing one variable at &lt;code&gt;pylintrc&lt;/code&gt; - &lt;code&gt;max-parents=15&lt;/code&gt; which will conclude in using more then 7 default class inheritance.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/agconti/cookiecutter-django-rest"&gt;CookieCutter-Django-Rest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Making API documentation - research for best API documentation!&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. How to secure biking-endorphines REST-API.&lt;/h4&gt;
&lt;h4&gt;2. Badge Gathering source-code and tests.&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="biking-endorphines-database"></category><category term="API"></category><category term="REST"></category><category term="SOAP"></category><category term="webservice"></category><category term="ORM"></category><category term="django-rest-swagger"></category><category term="drf-docs"></category><category term="documentation"></category><category term="drf-autodocs"></category></entry><entry><title>FancyBox Plugin Finalizing</title><link href="http://witkowskibartosz.com/blog/fancybox-plugin-finalizing.html" rel="alternate"></link><published>2017-04-26T23:50:00+02:00</published><updated>2017-04-26T23:50:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-26:/blog/fancybox-plugin-finalizing.html</id><summary type="html">&lt;h1&gt;FancyBox Pelican Plugin - are you done already?&lt;/h1&gt;
&lt;p&gt;The FancyBox is almost complete. Need to adjust some elements. But main functionality is almost complete.&lt;/p&gt;
&lt;p&gt;Down below are all functions that I've created:&lt;/p&gt;
&lt;h1&gt;Replace function.&lt;/h1&gt;
&lt;p&gt;Needed to create a replace function for replacing fancybox markdown element from article with a fancybox-type element …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;FancyBox Pelican Plugin - are you done already?&lt;/h1&gt;
&lt;p&gt;The FancyBox is almost complete. Need to adjust some elements. But main functionality is almost complete.&lt;/p&gt;
&lt;p&gt;Down below are all functions that I've created:&lt;/p&gt;
&lt;h1&gt;Replace function.&lt;/h1&gt;
&lt;p&gt;Needed to create a replace function for replacing fancybox markdown element from article with a fancybox-type element used with fancybox javascript engine.&lt;/p&gt;
&lt;p&gt;Test for replace function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assert_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Asserts replace equals expected&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_given_article_with_fancybox_replace&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Checks if Replace method makes replacement of &amp;lt;fancybox&amp;gt;&amp;lt;/fancybox&amp;gt;element into &amp;lt;a class=&amp;#39;fancybox_group&amp;#39;&amp;gt;&amp;lt;/a&amp;gt; &amp;quot;&lt;/span&gt;

    &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Data data data&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt; &amp;lt;{}&amp;gt;TEST&amp;lt;/{}&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;data data data&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Data data data&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt; &amp;lt;a class=&amp;quot;{}&amp;quot;&amp;gt;TEST&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;data data data&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CLASS_SELECTOR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;assert_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&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;test_given_multiple_fancybox_elements_in_article_replace&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Checks if multiple fancybox elements will be replaced with fancybox-type engine element&amp;quot;&lt;/span&gt;

    &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Data data data&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt; &amp;lt;{}&amp;gt;TEST&amp;lt;/{}&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;data &amp;lt;{}&amp;gt;TEST&amp;lt;/{}&amp;gt;data &amp;lt;{}&amp;gt;TEST&amp;lt;/{}&amp;gt;data&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Data data data&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt; &amp;lt;a class=&amp;quot;{}&amp;quot;&amp;gt;TEST&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;data &amp;lt;a class=&amp;quot;{}&amp;quot;&amp;gt;TEST&amp;lt;/a&amp;gt;data &amp;lt;a class=&amp;quot;{}&amp;quot;&amp;gt;TEST&amp;lt;/a&amp;gt;data&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CLASS_SELECTOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CLASS_SELECTOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CLASS_SELECTOR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;assert_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Source code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Replaces fancybox tag with &amp;lt;a class=&amp;#39;fancybox&amp;#39;&amp;gt;&amp;lt;/a&amp;gt;&amp;quot;&lt;/span&gt;

    &lt;span class="n"&gt;elements_fancybox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;find_fancybox_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&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;fancybox&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;elements_fancybox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fancybox&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TAG_REPLACEMENT&lt;/span&gt;
        &lt;span class="n"&gt;fancybox&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CLASS_SELECTOR&lt;/span&gt;
        &lt;span class="n"&gt;fancybox&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;href&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fancybox&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
        &lt;span class="n"&gt;fancybox&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;html.parser&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;img&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fancybox&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Add Dependency function.&lt;/h1&gt;
&lt;p&gt;"add_dependency" function - adds all javascript and css dependency files as &lt;script&gt;&lt;/script&gt; / &lt;link&gt;&lt;/link&gt; to source of markdown article. Probably now it's not added, but soon this "dependency" will only be added if &lt;fancybox&gt; element is found in markdown article source file.&lt;/p&gt;
&lt;p&gt;Test for "add dependency" function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_given_article_add_dependency&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Checks if article contains css element after using &amp;#39;add_css&amp;#39; function - only if fancybox element exists&amp;quot;&lt;/span&gt;

    &lt;span class="n"&gt;expected_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;script src=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;script src=&amp;quot;fancybox/jquery.fancybox-1.3.4.pack.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;expected_content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;link href=&amp;quot;fancybox/jquery.fancybox-1.3.4.css&amp;quot; media=&amp;quot;screen&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot;/&amp;gt;&amp;#39;&lt;/span&gt;

    &lt;span class="n"&gt;article_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Data data data&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt; &amp;lt;{}&amp;gt;TEST&amp;lt;/{}&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;data data data&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_content&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;article_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;add_dependency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Source code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_dependency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;Adds CSS/JS dependency to article only if article contains fancybox element&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;script_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;html.parser&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;script&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;css_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;html.parser&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;link&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;media&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;screen&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;script_tag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;src&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DEPS_JS_JQUERY_URL&lt;/span&gt;

    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script_tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;script_tag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;src&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DEPS_JS_FANCYBOX_URL&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script_tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;css_tag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;href&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DEPS_CSS_FANXYBOX_URL&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;css_tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Add Binding Fancyboxscript function.&lt;/h1&gt;
&lt;p&gt;This function adds Javascript binding between fancybox elements in markdown source and fancybox engine.&lt;/p&gt;
&lt;p&gt;Tests :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_given_article_add_binding_fancyboxscript&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Checks if article contains javascript binding between name of class and fancybox script&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;article_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Data data data&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt; &amp;lt;{}&amp;gt;TEST&amp;lt;/{}&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;data data data&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FANCYBOXNAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expected_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;article_content&lt;/span&gt;
    &lt;span class="n"&gt;expected_content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;script&amp;gt;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;expected_content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&amp;quot;$(document).ready(function() {$(&amp;quot;a.fancybox&amp;quot;).fancybox({&amp;#39;hideOnContentClick&amp;#39;: true});});&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;expected_content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;/script&amp;gt;&amp;quot;&lt;/span&gt;

    &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;add_binding_fancyboxscript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Source code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_binding_fancyboxscript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Adds biding for fancybox script with class selector&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;script&amp;gt;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;JS_BIDING_CONTENT&lt;/span&gt;
    &lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;/script&amp;gt;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;binding&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Source code of plugin-itself&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fancybox_plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Fanxybox plugin - temporary code placement&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add_dependency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;
        &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add_binding_fancyboxscript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt;
        &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;What needs to be done (a follow-up article about that :) )&lt;/h1&gt;
&lt;p&gt;In short - functions needs to be change into methods, links to js/css needs to be adjusted. Some additional tests needs to be added.&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;Final result can be checked &lt;a href="https://github.com/anselmos/pelican-fancybox/tree/tdd-approach"&gt;at this branch&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/b173f03"&gt;Refactors code. Fixes issue with not adding img inside of a-tag&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/3e086d7"&gt;Refactors js/css dependency code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/156421c"&gt;Adds add_biding_fancyboxscript source code.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/4f8024c"&gt;Adds failing test for add_binding_fancyboxscript function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/54fd726"&gt;Adds passing test for add dependency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/7fb06c4"&gt;Adds failing test for add_dependency function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/193f900"&gt;Refactors code with assert_replace function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/1cc5344"&gt;Adds test for multiple fancybox elements in article&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/4af53a7"&gt;Refactors code - replace name for better name-convention&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/02efd7d"&gt;Refactors code.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/292fbac"&gt;Fixes source code using BeautifulSoup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/9ddefd0"&gt;Fixes test assert. Adds replace failing function.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/ea45223"&gt;Fixes a bit source code.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/d075e8c"&gt;Adds failing test for replace function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/2e6b25c"&gt;Refactors code - adds constant instead of hardcoded value.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Make &lt;em&gt;ALMOST&lt;/em&gt; final commits for source-code of fancybox plugin&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Make final commit for source-code of fancybox plugin&lt;/h4&gt;
&lt;h4&gt;2. Start working on plugin for asciinema player.&lt;/h4&gt;
&lt;h4&gt;3. See &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/issues"&gt;ISSUES&lt;/a&gt; task-list for this 'mini' growing project :)&lt;/h4&gt;</content><category term="anselmos-pelican-blog-source"></category><category term="mini-project"></category><category term="pelican"></category><category term="fancy-box"></category><category term="fancybox-plugin"></category><category term="image-viewer-plugin"></category><category term="tdd"></category><category term="tdd-approach"></category><category term="pelican-plugin"></category></entry><entry><title>Biking Endorphines - REST-API within Django</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-rest-api-within-django.html" rel="alternate"></link><published>2017-04-26T00:00:00+02:00</published><updated>2017-04-26T00:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-26:/blog/biking-endorphines-rest-api-within-django.html</id><summary type="html">&lt;h1&gt;What frameworks exists that supports REST-API within python ?&lt;/h1&gt;
&lt;h3&gt;1. &lt;a href="http://www.django-rest-framework.org/"&gt;Django REST Framework&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Quoting information from site:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Some reasons you might want to use REST framework:

- The Web browsable API is a huge usability win for your developers.
- Authentication policies including packages for OAuth1a and OAuth2.
- Serialization that supports both ORM …&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;h1&gt;What frameworks exists that supports REST-API within python ?&lt;/h1&gt;
&lt;h3&gt;1. &lt;a href="http://www.django-rest-framework.org/"&gt;Django REST Framework&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Quoting information from site:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Some reasons you might want to use REST framework:

- The Web browsable API is a huge usability win for your developers.
- Authentication policies including packages for OAuth1a and OAuth2.
- Serialization that supports both ORM and non-ORM data sources.
- Customizable all the way down - just use regular function-based views if you don&amp;#39;t need the more powerful features.
- Extensive documentation, and great community support.
- Used and trusted by internationally recognised companies including Mozilla, Red Hat, Heroku, and Eventbrite.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;2. Flask and Bottle&lt;/h3&gt;
&lt;p&gt;Quoting information from site about Bottle:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Bottle is a fast, simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module and has no dependencies other than the Python Standard Library.

- Routing: Requests to function-call mapping with support for clean and dynamic URLs.
- Templates: Fast and pythonic built-in template engine and support for mako, jinja2 and cheetah templates.
- Utilities: Convenient access to form data, file uploads, cookies, headers and other HTTP-related metadata.
- Server: Built-in HTTP development server and support for paste, fapws3, bjoern, gae, cherrypy or any other WSGI capable HTTP server.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;3. &lt;a href="https://flask-restful.readthedocs.io/en/0.3.5/"&gt;Flask-restful&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Quoting information from site :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Flask-RESTful is an extension for Flask that adds support for quickly building REST APIs. 
It is a lightweight abstraction that works with your existing ORM/libraries. 
Flask-RESTful encourages best practices with minimal setup. 
If you are familiar with Flask, Flask-RESTful should be easy to pick up.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;4. &lt;a href="http://eve.readthedocs.io/en/stable/foreword.html"&gt;Python-Eve&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Quoting information from site :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Eve is an open source Python REST API framework designed for human beings.
It allows to effortlessly build and deploy highly customizable, fully featured RESTful Web Services.

Eve is powered by Flask, Cerberus, Events and MongoDB.
Support for SQL-Alchemy, Elasticsearch and Neo4js as alternate backends is provided by community extensions.

The codebase is thoroughly tested under Python 2.6, 2.7, 3.3, 3.4, 3.5, 3.6 and PyPy.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;5. &lt;a href="http://falconframework.org/"&gt;Falcon&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Quoting information from site :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Falcon is a very fast, very minimal Python web framework for building microservices, app backends, and higher-level frameworks.
It is used by a growing number of organizations around the world, including Cronitor, EMC, Hurricane Electric, OpenStack, Opera Software, Wargaming, and Rackspace.

The Falcon web framework encourages the REST architectural style, meaning (among other things) that you think in terms of resources and state transitions, which map to HTTP methods.

A number of Falcon add-ons, templates, and complimentary packages are available for use in your projects.
We&amp;#39;ve listed several of these on the Falcon wiki as a starting point, but you may also wish to search PyPI for additional resources.

Falcon can be deployed in a variety of ways, depending on your needs.
The framework speaks WSGI, and works great with CPython 2.6 and 2.7, PyPy, and CPython 3.3+.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;6. &lt;a href="http://cornice.readthedocs.io/en/latest/"&gt;Cornice&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Quoting information from site :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Cornice provides helpers to build &amp;amp; document REST-ish Web Services with Pyramid, with decent default behaviors.
It takes care of following the HTTP specification in an automated way where possible.

We designed and implemented cornice in a really simple way, so it is easy to use and you can get started in a matter of minutes.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;7. &lt;a href="https://django-tastypie.readthedocs.io/en/latest/"&gt;Tastypie&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Quoting information from site :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Tastypie is a webservice API framework for Django.
It provides a convenient, yet powerful and highly customizable, abstraction for creating REST-style interfaces.
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;8. &lt;a href="https://www.quora.com/What-is-a-good-Python-framework-for-building-a-RESTful-API"&gt;Others maybe included here&lt;/a&gt;&lt;/h3&gt;
&lt;h1&gt;What framework our Biking-Endorphines will use?&lt;/h1&gt;
&lt;h3&gt;1. My selection criteria:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;1.A) REST API creation
1.B) TDD support
1.C) Different type of data formats i.e. json and xml (best - out of the box)
1.D) Documentation (best - out of the box)
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;2. What framework looks like supports all my criteria out of the box?&lt;/h3&gt;
&lt;p&gt;Well that's not a surprise - &lt;code&gt;the Django Rest Framwork&lt;/code&gt; &lt;em&gt;passes&lt;/em&gt; all my criteria.&lt;/p&gt;
&lt;h1&gt;How to use Django Rest Framework?&lt;/h1&gt;
&lt;h3&gt;1. Serializers.&lt;/h3&gt;
&lt;p&gt;First you need to have any type of Serializer for your objects.&lt;/p&gt;
&lt;p&gt;In our projects example I'll use the "User" class definition for creating serializer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    User serializer&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="c1"&gt;#pylint: disable=invalid-name&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read_only&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="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="o"&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;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allow_blank&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="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="o"&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;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allow_blank&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="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&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;create&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;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Create and return a new `User` instance, given the validated data.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;validated_data&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;update&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;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Update and return an existing `User` instance, given the validated data.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&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;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;surname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;weight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;height&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&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;instance&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;But wait.... what about tests ?  - Good point.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Tests for API&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;api.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserSerializer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;web.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;



&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestUserSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;UserSerializer tests&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_user_serialize_to_json&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="s2"&gt;&amp;quot;test if serializing to JSON works&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;mocked&lt;/span&gt; &lt;span class="o"&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;mocked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;mocked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Somlesna&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;mocked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
        &lt;span class="n"&gt;mocked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;175&lt;/span&gt;

        &lt;span class="n"&gt;user_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mocked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_serialized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;height&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;surname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Somlesna&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;weight&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Anselmos&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;2. Views for API.&lt;/h3&gt;
&lt;p&gt;Now lets create a View for our Serializer and then add it to our urls.py&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Views&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;APIView&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework.response&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;api.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserSerializer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;web.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    List all User&amp;#39;s, or create a new snippet&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&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;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;serializer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;many&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;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Test:(yeah it's not enough for a test, but still simplest one:)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestUserList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;UserList tests&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_user_get_return_json&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="s2"&gt;&amp;quot;test if using get returns json data&amp;quot;&lt;/span&gt;

        &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRequestFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/api/user/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;force_authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;3. Urls for proper handling on outside:&lt;/h3&gt;
&lt;p&gt;In &lt;code&gt;urls.py&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^api/user/$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;Final result is available at &lt;a href="https://github.com/anselmos/Biking-Endorphines/tree/restapi_django-rest-framework"&gt;this branch&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/f0baea1"&gt;Adds Test for UserList and get API.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/bfb2a44"&gt;Adds initial rest-api for User&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.toptal.com/bottle/building-a-rest-api-with-bottle-framework"&gt;Building a Rest API with the Bottle Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fullstackpython.com/api-creation.html"&gt;API Creation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt; 1. REST-API for Test-Database.&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Making API documentation - research for best API documentation!&lt;/h4&gt;
&lt;h4&gt;2. How to secure biking-endorphines REST-API.&lt;/h4&gt;
&lt;h4&gt;3. Badge Gathering source-code and tests.&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="REST"></category><category term="python-rest-frameworks"></category><category term="rest-frameworks"></category><category term="best-rest-api-framework"></category><category term="django"></category><category term="flask"></category><category term="bottle"></category><category term="eve"></category><category term="falcon"></category><category term="cornice"></category><category term="tastypie"></category></entry><entry><title>Biking Endorphines - Test Database and REST API</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-rest-api.html" rel="alternate"></link><published>2017-04-22T23:50:00+02:00</published><updated>2017-04-22T23:50:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-22:/blog/biking-endorphines-rest-api.html</id><summary type="html">&lt;h1&gt;Prerequisites&lt;/h1&gt;
&lt;h3&gt;1. REST API vs SOAP API&lt;/h3&gt;
&lt;p&gt;So you are here to know what are the difference between API webservices?&lt;/p&gt;
&lt;p&gt;Let's go with simple what are cons/pros of each solution!&lt;/p&gt;
&lt;h4&gt;1.A REST API Pros and Cons&lt;/h4&gt;
&lt;h5&gt;PROS:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Lower amount of data needed to deliver actual  content&lt;/li&gt;
&lt;li&gt;Available two …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;h1&gt;Prerequisites&lt;/h1&gt;
&lt;h3&gt;1. REST API vs SOAP API&lt;/h3&gt;
&lt;p&gt;So you are here to know what are the difference between API webservices?&lt;/p&gt;
&lt;p&gt;Let's go with simple what are cons/pros of each solution!&lt;/p&gt;
&lt;h4&gt;1.A REST API Pros and Cons&lt;/h4&gt;
&lt;h5&gt;PROS:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Lower amount of data needed to deliver actual  content&lt;/li&gt;
&lt;li&gt;Available two types of data formats (at least that's what I know of : JSON and XML)&lt;/li&gt;
&lt;li&gt;Thanks to usage of JSON data format - simplified access to data within i.e. javascript/Android Applications etc.&lt;/li&gt;
&lt;li&gt;Supports CRUD operations (Create, Read, Update, Delete) - that are correlated with HTTP convension (Create -&amp;gt; PUT/POST, Read -&amp;gt; Get, Update -&amp;gt; PUT/POST/PATCH, Delete-&amp;gt; DELETE)&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;CONS:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;REST API formally does not have any type of WSDL and therefore you don't have any formal endpoints definition (only as description i.e. using other services)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;1.B SOAP API Pros and Cons&lt;/h4&gt;
&lt;h5&gt;PROS:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Contains formal scheme defining endpoints within WSDL&lt;/li&gt;
&lt;li&gt;Output of endpoints data is formalized in WSDL and therefore you can check for expected output from that endpoints.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;CONS:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Only XML with WSDL scheme&lt;/li&gt;
&lt;li&gt;Lack or small amount of support for SOAP-XML at Android Community&lt;/li&gt;
&lt;li&gt;Large amount of data to deliver actual content&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Why do you want to use REST API ?&lt;/h3&gt;
&lt;p&gt;REST API is used from Client's perspective rather for faster data access with low amount of data delivered.&lt;/p&gt;
&lt;p&gt;In my humble opinion that's why Android Community does not give such great support for SOAP.&lt;/p&gt;
&lt;p&gt;Also that's your answer: If you are planning to use this webservice as an Endpoint for other Clients (Mobile Device, other web-applications i.e. based on javascript engine), than REST API is webservice for you!&lt;/p&gt;
&lt;p&gt;But If you don't mind more amount of data and a little bit more complex data binding (parsing/sending/reading) but better formalization of data, than you obviously choose SOAP API.&lt;/p&gt;
&lt;p&gt;One of the most important elements that makes SOAP API great is it's WSDL which helps to correlate how endpoints looks like, what data ought to be inside of them - which in later phase - helps you to more properly bind data and be sure that only this type of data should come out them.&lt;/p&gt;
&lt;h1&gt;Initial Database for REST API in Biking Endorphines project.&lt;/h1&gt;
&lt;h3&gt;1. Test Database assumptions.&lt;/h3&gt;
&lt;p&gt;What I love about django is it's ORM(Object-Relational-Mapping). It offers you usage of old-school traditional database-in-file SQLite, but also other Database engines like i.e. Postgres.&lt;/p&gt;
&lt;p&gt;You can easily switch between them, only thing that needs to be moved is data itself. But since it's a ORM you can manipulate database and create Test-data.&lt;/p&gt;
&lt;p&gt;For our Biking Endorphines project, expected is to create tables with data like below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;User - just usual stuff like: &lt;/p&gt;
&lt;p&gt;(some already exists as part of &lt;code&gt;bmi-checker&lt;/code&gt; functionality.)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt;, &lt;/li&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;surname&lt;/code&gt;, &lt;/li&gt;
&lt;li&gt;&lt;code&gt;weight&lt;/code&gt;, &lt;/li&gt;
&lt;li&gt;&lt;code&gt;height&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Biking Route with Points :&lt;/p&gt;
&lt;p&gt;Route:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;route_name&lt;/code&gt;,(for easier search)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;avg_route&lt;/code&gt; (predefined avg for this route, not related to user&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;User-Route:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id_user&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;id_route&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Point:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;id_route&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;point&lt;/code&gt;, (&lt;code&gt;lat&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;elevation&lt;/code&gt;,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Type of database.&lt;/h3&gt;
&lt;p&gt;For now I'll use SQLite - a default database delivered with django instance.&lt;/p&gt;
&lt;p&gt;I will probably move to my favourite database - PostgreSQL in future.&lt;/p&gt;
&lt;p&gt;There is also a plan to create article about PostgreSQL in docker - So keep in touch :)&lt;/p&gt;
&lt;h3&gt;3. Database scheme.&lt;/h3&gt;
&lt;p&gt;So I've created a class-based ORM scheme within django. Here is how it looks like after &lt;code&gt;python manage.py dbshell &amp;gt;.schema&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_migrations&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;app&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;name&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;applied&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;name&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group_permissions&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;group_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;permission_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_permission&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_groups&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;group_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_user_permissions&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;permission_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_permission&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group_permissions_group_id_0cd325b0_uniq&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group_permissions&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;group_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;permission_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group_permissions_0e939a4f&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group_permissions&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;group_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group_permissions_8373b171&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_group_permissions&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;permission_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_groups_user_id_94350c0c_uniq&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_groups&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;group_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_groups_e8701ad4&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_groups&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_groups_0e939a4f&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_groups&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;group_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_user_permissions_user_id_14a6b632_uniq&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_user_permissions&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;permission_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_user_permissions_e8701ad4&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_user_permissions&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_user_permissions_8373b171&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user_user_permissions&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;permission_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_admin_log&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;object_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;object_repr&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;action_flag&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;smallint&lt;/span&gt; &lt;span class="n"&gt;unsigned&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;change_message&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;content_type_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_content_type&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;action_time&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_admin_log_417f1b1c&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_admin_log&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;content_type_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_admin_log_e8701ad4&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_admin_log&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_content_type&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;app_label&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;model&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_content_type_app_label_76bd3d3b_uniq&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_content_type&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;app_label&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;model&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_permission&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;content_type_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_content_type&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;codename&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;name&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_permission_content_type_id_01ab375a_uniq&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_permission&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;content_type_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;codename&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_permission_417f1b1c&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_permission&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;content_type_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;auth_user&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;password&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;last_login&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;is_superuser&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;email&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;254&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;is_staff&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;is_active&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;date_joined&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;username&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_session&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;session_key&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;session_data&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;expire_date&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_session_de54fa62&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;django_session&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;expire_date&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_point&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;lat&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;real&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;lon&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;real&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;elevation&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;real&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_route&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;route_name&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;avg_route&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;real&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_routepoint&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;id_point_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_point&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;id_route_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_route&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_user&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;name&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;height&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;weight&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;surname&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_routepoint_aa34cbab&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_routepoint&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id_point_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_routepoint_c5012f0d&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_routepoint&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id_route_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_userroute&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;id_route_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_route&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;id_user_id&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_user&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_userroute_c5012f0d&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_userroute&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id_route_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_userroute_3002e0f2&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;web_userroute&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;id_user_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Initial plans for REST API for Biking Endorphines.&lt;/h1&gt;
&lt;p&gt;I'm planning to create REST-API. Below you can see what 2 endpoints will be created:&lt;/p&gt;
&lt;h3&gt;1. Gather user data with /user/get&lt;/h3&gt;
&lt;h3&gt;2. Gather Biking routes and points with /route/{id}  and /point/{id}&lt;/h3&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    User model for obtaining personal information about biking riders&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;surname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Returns User information when using str/printing&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bmi&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Body Mass Index calculator simplified to number&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Route model. Defines Route by name, avg_route.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;route_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;avg_route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FloatField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="s2"&gt;&amp;quot;Returns Route name &amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route_name&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    User&amp;#39;s routes&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;id_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&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;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;id_route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="s2"&gt;&amp;quot;Returns User id&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_user&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Points similar to gpx-data&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;lat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FloatField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;lon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FloatField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;elevation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FloatField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="s2"&gt;&amp;quot;Returns Point unicode&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RoutePoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Route Points relations&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;id_route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;id_point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="s2"&gt;&amp;quot;Returns Route-Point relationship unicode&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_route&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/f88a655"&gt;Adds Test-Database models for REST-API schema.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/1.11/ref/contrib/gis/model-api/"&gt;GeoDjango Model API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/1.9/intro/tutorial02/#database-setup"&gt;Database Setup for Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/6437907/generate-database-schema-using-python"&gt;Generate Database schema using Python -at StackOverFlow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/1.11/topics/db/examples/many_to_one/"&gt;Many-to-one relationships for Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/1.11/ref/models/fields/"&gt;Django model-fields documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Python backend - initial REST-API.&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. REST-API for Test-Database.&lt;/h4&gt;
&lt;h4&gt;2. Making API documentation - research for best API documentation!&lt;/h4&gt;
&lt;h4&gt;3. How to secure biking-endorphines REST-API.&lt;/h4&gt;
&lt;h4&gt;4. Badge Gathering source-code and tests.&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="biking-endorphines-database"></category><category term="API"></category><category term="REST"></category><category term="SOAP"></category><category term="webservice"></category><category term="ORM"></category></entry><entry><title>FancyBox Plugin Finding Fancybox elements in articles</title><link href="http://witkowskibartosz.com/blog/fancybox-plugin-finding-fancybox-elements-in-articles.html" rel="alternate"></link><published>2017-04-19T21:30:00+02:00</published><updated>2017-04-19T21:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-19:/blog/fancybox-plugin-finding-fancybox-elements-in-articles.html</id><summary type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Lately I've started working on this pelican-plugin that will use special command in markdown article to "magically" change it's content into a fancybox-alike.&lt;/p&gt;
&lt;p&gt;I've started it with badly without TDD and that approach failed to leave me with successful plugin created.&lt;/p&gt;
&lt;p&gt;My failure was also in copy-pasting others plugins …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Lately I've started working on this pelican-plugin that will use special command in markdown article to "magically" change it's content into a fancybox-alike.&lt;/p&gt;
&lt;p&gt;I've started it with badly without TDD and that approach failed to leave me with successful plugin created.&lt;/p&gt;
&lt;p&gt;My failure was also in copy-pasting others plugins content and trying to re-use it for my own purpose, but it didn't work properly.&lt;/p&gt;
&lt;p&gt;This time using TDD and slower movement of source-code I'm working on describing and finding elements of "fancybox" in article.&lt;/p&gt;
&lt;p&gt;So no more chit-chat, let's move to the actual source-code and content of this article! :)&lt;/p&gt;
&lt;h1&gt;Finding Fancybox elements&lt;/h1&gt;
&lt;h3&gt;1. Describing fancybox elements&lt;/h3&gt;
&lt;p&gt;So I've been thinking how to easily add fancybox element in markdown so it will be easily added to markdown and then also easily readed at plugin for further manipulation of article content.&lt;/p&gt;
&lt;p&gt;I've figure I'll start with something, that may be good for beginning and then If I find it will not suit my needs , I'll change it to something else.&lt;/p&gt;
&lt;p&gt;That's why for sake of simplicity I'm going to use for now this element:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;fancybox&amp;gt;URL&amp;lt;/fancybox&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Let's check how it will work for now! :)&lt;/p&gt;
&lt;h3&gt;2. Creating testing markdown article and adding it to tests.&lt;/h3&gt;
&lt;p&gt;I've created an example Article instance with "content" that had the &lt;code&gt;&amp;lt;fancybox&amp;gt;URL&amp;lt;/fancybox&amp;gt;&lt;/code&gt; element inside.
Also I've figure out that I should also check if using pelican it-self will be of great benefit, so I've added a Markdown file in content for pelican.&lt;/p&gt;
&lt;p&gt;And sure thing - it did! I found that my plugin function that was registered didn't have proper arguments.&lt;/p&gt;
&lt;p&gt;Also I moved finally source-code of my plugin to &lt;code&gt;fancybox.py&lt;/code&gt; instead of &lt;code&gt;test_fancybox.py&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;3. Adding testing article with fancybox elements&lt;/h3&gt;
&lt;p&gt;Test function looks like below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_given_article_with_fancybox_find_fancybox_element&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Checks for finding fancybox element in article&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Data data data&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt; &amp;lt;fancybox&amp;gt;TEST&amp;lt;/fancybox&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;data data data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;find_fancybox_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;4. Testing and creating source code.&lt;/h3&gt;
&lt;p&gt;Source code for now looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pelican&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;A simple Article class&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&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;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_fancybox_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;content_line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;fancybox&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content_line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content_line&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fancybox_plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Fanxybox plugin - temporary code placement&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;find_fancybox_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Registers plugin&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fancybox_plugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And yes, I know that I'm currently using checking for first element and it may raise with &lt;code&gt;IndexError&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I'll fix this properly - for sure.&lt;/p&gt;
&lt;h1&gt;Final result for testing fancybox plugin&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;FancyBox unittests&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pelican&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fancybox&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fancybox&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fancybox&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;find_fancybox_element&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fancybox&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fancybox_plugin&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mock_article_generator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Article generator&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;Article&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;assert_receiver_registered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;receiver_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;Checks if receiver is registered to signals generator&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_receivers_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;receiver_name&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;test_plugin_registers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Check if plugin registers to article_generator_finalized&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;assert_receiver_registered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fancybox_plugin&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;test_article_generator_return_article&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Checks if generator return article&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_article_generator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Article&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;test_given_article_generator_check_article_content_exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Checks if article content field exists in article&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mock_article_generator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;content&amp;#39;&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;test_given_article_with_fancybox_find_fancybox_element&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Checks for finding fancybox element in article&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Data data data&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt; &amp;lt;fancybox&amp;gt;TEST&amp;lt;/fancybox&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;data data data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;find_fancybox_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/367b0ad"&gt;Refactors code a little bit for more readability.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/7d47e2f"&gt;Adds Makefile to simplify testing with make test.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/d3434be"&gt;Moves source of plugin to plugin file.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/f13395b"&gt;Adds a non-failing test for find-fancybox_element&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/5cb49e9"&gt;Adds failing test for find_fancybox_element.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Make more tests and source-code of fancybox plugin&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Make final commit for source-code of fancybox plugin&lt;/h4&gt;
&lt;h4&gt;2. Start working on plugin for asciinema player.&lt;/h4&gt;
&lt;h4&gt;3. See &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/issues"&gt;ISSUES&lt;/a&gt; task-list for this 'mini' growing project :)&lt;/h4&gt;</content><category term="anselmos-pelican-blog-source"></category><category term="mini-project"></category><category term="pelican"></category><category term="fancy-box"></category><category term="fancybox-plugin"></category><category term="image-viewer-plugin"></category><category term="tdd"></category><category term="tdd-approach"></category><category term="pelican-plugin"></category></entry><entry><title>GPXReader - initial Endorphine Algorithm</title><link href="http://witkowskibartosz.com/blog/gpxreader-endorphine-algorithm.html" rel="alternate"></link><published>2017-04-19T11:00:00+02:00</published><updated>2017-04-19T11:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-19:/blog/gpxreader-endorphine-algorithm.html</id><summary type="html">&lt;h1&gt;Prerequisites&lt;/h1&gt;
&lt;p&gt;I've initially looked at my source code and Github and found that I've got few things a bit wrongly implemented (not using properly &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY principle&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;I've found also that &lt;code&gt;gpxreader_test&lt;/code&gt; branch should be finally merged to master.&lt;/p&gt;
&lt;p&gt;I've found also that android-initial startup as module that as not been …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Prerequisites&lt;/h1&gt;
&lt;p&gt;I've initially looked at my source code and Github and found that I've got few things a bit wrongly implemented (not using properly &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY principle&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;I've found also that &lt;code&gt;gpxreader_test&lt;/code&gt; branch should be finally merged to master.&lt;/p&gt;
&lt;p&gt;I've found also that android-initial startup as module that as not been yet merged to master.&lt;/p&gt;
&lt;p&gt;That why initially I needed to make prerequisites like:&lt;/p&gt;
&lt;h3&gt;1. Merging &lt;code&gt;gpxreader_test&lt;/code&gt; branch to master&lt;/h3&gt;
&lt;h3&gt;2. Merging &lt;code&gt;androidapp_submodule&lt;/code&gt; branch to master&lt;/h3&gt;
&lt;h3&gt;3. Fixing problem breaking DRY principle.&lt;/h3&gt;
&lt;p&gt;As you may check in &lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/99fb41a2b923913acd98c475562c45c6ec545526"&gt;this commit&lt;/a&gt;. Unfortunatelly this fix was in-between working with endorphine-algorithm. My only excuse is that I've followed TDD 3 principles - Make failing test, fix code for test, refactor - to be more precise I've used the "refactor" part.&lt;/p&gt;
&lt;h3&gt;4. Fixing problem with not using properly unittest module&lt;/h3&gt;
&lt;p&gt;Instead of using &lt;code&gt;self.assert*&lt;/code&gt; I've been using old-school pytest &lt;code&gt;assert&lt;/code&gt;. Thanks to this &lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/44aa50cee02fc88e856a265c394c4ce09550bf34"&gt;commit&lt;/a&gt; I've finally get rid of this old-school assertions.&lt;/p&gt;
&lt;h1&gt;First Endorphine Algorithm with TDD in mind.&lt;/h1&gt;
&lt;h3&gt;1. Algorithm itself.&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Lowest Point You've Been&lt;/code&gt; algorithm is all about finding the lowest point in the gpx track that User have been.&lt;/p&gt;
&lt;p&gt;If gpx track does not have lowest point, does not have points or those points are of the same elevation, then method should return None.&lt;/p&gt;
&lt;p&gt;More comprehensive documentation is in the method documentation.&lt;/p&gt;
&lt;h3&gt;2. Test Flow for Endorphine-Algorithm for gathering 'Lowest Point You've Been'&lt;/h3&gt;
&lt;p&gt;So I've been using the TDD for this article.
It was a very successful session. I've tried to practice TDD with best intentions and motivation I've found in &lt;a href="https://www.youtube.com/watch?v=qmS4ojQ1Pa8"&gt;"Uncle Bob" video about TDD&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First I've started with a failing tests, then created source-code and then refactored code for better quality and readability.&lt;/p&gt;
&lt;p&gt;Initially I've started with this code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="nd"&gt;@parameterized.expand&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_empty_points.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&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;test_get_lowest_elevation&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;gpxfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_GPXFILE_SAMPLE&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests for get_lowest_elevation&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpxfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_elevations&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_lowest_elevation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then I've added file called &lt;code&gt;fast_example_empty_points.gpx&lt;/code&gt; without any points in it -based on &lt;code&gt;fast_example_trackpoints.gpx&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;After that I've added source code that fixed failing code with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_lowest_elevation&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="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_elevations&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Added some small refactoring and repeated process. I didn't do all the commits for the flow, but I tried to make them as much as I could.&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;h3&gt;1. Tests.&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assert_lowest_elevation_equals&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;expected&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot; Assertion for Equality of get_lowest_elevation with Expected&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_lowest_elevation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;#pylint: disable=invalid-name&lt;/span&gt;
    &lt;span class="nd"&gt;@parameterized.expand&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_TESTS_EXAMPLES_PATH&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fast_example_empty_points.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_TESTS_EXAMPLES_PATH&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fast_example_points_no_elevation.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&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;test_given_none_or_empty_elevation_return_none&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;gpxfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_GPXFILE_SAMPLE&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests for get_lowest_elevation&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpxfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_lowest_elevation_equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&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;test_given_one_available_elevation_return_none&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests for get_lowest_elevation&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;DEFAULT_TESTS_EXAMPLES_PATH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; \
            &lt;span class="s2"&gt;&amp;quot;get_lowest_elevation_one_elevation_available.gpx&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_lowest_elevation_equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&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;test_given_two_different_points_return_lowest&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests for get_lowest_elevation&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;DEFAULT_TESTS_EXAMPLES_PATH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; \
            &lt;span class="s2"&gt;&amp;quot;get_lowest_elevation_two_different_points.gpx&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_lowest_elevation_equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;102.0&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;test_given_two_the_same_points_return_none&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests for get_lowest_elevation&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;DEFAULT_TESTS_EXAMPLES_PATH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; \
            &lt;span class="s2"&gt;&amp;quot;get_lowest_elevation_two_the_same_points.gpx&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_lowest_elevation_equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&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;test_given_more_then_two_the_same_points_return_none&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests for get_lowest_elevation&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;DEFAULT_TESTS_EXAMPLES_PATH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; \
            &lt;span class="s2"&gt;&amp;quot;get_lowest_elevation_more_then_two_the_same_points.gpx&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_lowest_elevation_equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&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;test_given_none_and_diff_points_return_minimal_value&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests for get_lowest_elevation&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;DEFAULT_TESTS_EXAMPLES_PATH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; \
            &lt;span class="s2"&gt;&amp;quot;get_lowest_elevation_none_and_diff_points_return_minimal_value.gpx&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_lowest_elevation_equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;105.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;2. Source-code of method.&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_lowest_elevation&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;group_elevation&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;elevation&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_elevations&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;elevation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;group_elevation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;elevation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elevation&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_elevation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_elevation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_elevation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/12c01de"&gt;Fixes test for integration test of none diff point.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/2f8ffe7"&gt;Adds failing test for integration test.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/eb1d0b7"&gt;Adds fix for more then two the same points.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/3631d11"&gt;Adds failing test for more_then_two_same_points.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/a8369c6"&gt;Fixes test for two the same points returning None.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/44fa3f0"&gt;Fixes test of two diff-points&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/01c70ed"&gt;Adds failing two-diff-points test.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/8a254c0"&gt;Refactors. Adds assert_lowest_elevation_equals.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/7a1bbfe"&gt;Adds one available elevation test.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/3e5876a"&gt;Refactors code for path of example file.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/27eba15"&gt;Fixes pylint errors and warnings.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/99fb41a"&gt;Refactor code for more simplicity.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/f3c8dd6"&gt;Adds None and Empty elevations tests for get_lowest_elevation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/a079719"&gt;Fixes getlowest_elevations test.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/44aa50c"&gt;Fixes method can be function with self.assert*.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/191932c"&gt;Adds fix for travis issue. (#18)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/d0e0bb6"&gt;Adds androidapp as submodule (#17)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/3ad9f6c"&gt;Gpxreader tests (#16)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/dotfiles"&gt;anselmos/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/linux-utils"&gt;anselmos/linux-utils&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. Deploy_gh_pages travis job fails on "cannot stat.."&lt;/h3&gt;
&lt;p&gt;Issue that I've found was about travis not deploying pyreverse GitHub Page that should automatically be updated.&lt;/p&gt;
&lt;p&gt;What I've found out, was a silly problem with make-tasks that I've recently changed for gpxreader_test branch.&lt;/p&gt;
&lt;p&gt;Today I've finally cleaned-up this branch and merged(squashed) it to master. Then I've found out that gh_pages travis task is not working properly.&lt;/p&gt;
&lt;p&gt;The issue itself was a bit cryptic at first hand:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;cp: cannot stat &lt;span class="sb"&gt;`&lt;/span&gt;../../generated_pyreverse/*&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;: No such file or directory
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can check this issue at &lt;a href="https://travis-ci.org/anselmos/Biking-Endorphines/jobs/223218399"&gt;Travis for this project&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;I've initially thought that I forgot about adding directory of name &lt;code&gt;generated_pyreverse&lt;/code&gt;, but no. Thanks to simplicity of this tool and make-task I needed only few seconds to find out why this happen and what should be done.&lt;/p&gt;
&lt;p&gt;I needed to change name of the make task used in travis to "MAKE_GH_PAGE_TASK=deploy_gh_pages_all" instead of "MAKE_GH_PAGE_TASK=deploy_gh_pages"&lt;/p&gt;
&lt;p&gt;A kindly reminder for all users of Travis - be sure that if you have any "automatically" deployment, you do test it before running. And all changes in your deployment environment are checked before deploying :)&lt;/p&gt;
&lt;p&gt;So , is it working now you may ask ? &lt;a href="https://travis-ci.org/anselmos/Biking-Endorphines/jobs/223225313"&gt;You may check if you ask :)&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Tips &amp;amp; Tricks&lt;/h1&gt;
&lt;h3&gt;1. Move all issues from #TODO in source code to github issues.&lt;/h3&gt;
&lt;p&gt;At first glance I've used github issues to make all "new" features/issues.
Then my habits made their point and I've started using the "TODO" comments in code.&lt;/p&gt;
&lt;p&gt;It's not a bad thing, but since I can use github issues I've found it will be useless and makes me create additional &lt;code&gt;#pylint: disable=fixme&lt;/code&gt; line that just hides information in code instead of showing it to me.&lt;/p&gt;
&lt;p&gt;So I'm moving to github issues. Please if you find any type of &lt;code&gt;#TODO&lt;/code&gt; in my code - let me know :)&lt;/p&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Add test-cases for business logic to GPXReader - endorphines-algorithms :)&lt;/s&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;s&gt;2. Add Endorphine algorithm for 'Lowest Point You Have Been' &lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Python backend - initial REST-API.&lt;/h4&gt;
&lt;h4&gt;2. Making API documentation - research for best API documentation!&lt;/h4&gt;
&lt;h4&gt;3. Badge Gathering source-code and tests.&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="pytest"></category><category term="tdd"></category><category term="endorphines-algorithms"></category><category term="tips-tricks"></category><category term="tdd-approach"></category></entry><entry><title>GPXReader - Trackpoints Routepoints Waypoints</title><link href="http://witkowskibartosz.com/blog/gpxreader-trackpoints-routepoints-waypoints.html" rel="alternate"></link><published>2017-04-16T12:30:00+02:00</published><updated>2017-04-16T12:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-16:/blog/gpxreader-trackpoints-routepoints-waypoints.html</id><summary type="html">&lt;h1&gt;Trackpoints Routepoints and Waypoints&lt;/h1&gt;
&lt;p&gt;Before today's change, in my source code for tests I had only trackpoints. This worked pretty well, but then I've figure out, I need to be able to check if someone's going to use different type of *points. And obviously I added this to my steps-to-make …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Trackpoints Routepoints and Waypoints&lt;/h1&gt;
&lt;p&gt;Before today's change, in my source code for tests I had only trackpoints. This worked pretty well, but then I've figure out, I need to be able to check if someone's going to use different type of *points. And obviously I added this to my steps-to-make.&lt;/p&gt;
&lt;p&gt;I've created different type of gpx file encodings(TrackPoints/WayPoints/RoutePoints) for tests.&lt;/p&gt;
&lt;p&gt;I've added Routepoints and Waypoints. And this made to a tests failure once I've added them to test as parameters.&lt;/p&gt;
&lt;p&gt;As I've figure out before, one of the "content" type had different encoding of data and I needed to fix few things in source code.&lt;/p&gt;
&lt;p&gt;Finally code has 3 types of different  *points.&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;Here is final result of test-source-code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseGPXReaderTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    A Prof Of Concept for creating one generalized GPXReader test class.&lt;/span&gt;
&lt;span class="sd"&gt;    It will then be inherited by other classes that will use TrackPoints example data,&lt;/span&gt;
&lt;span class="sd"&gt;    Route Points data and Way Points data using pytest-fixtures.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="nd"&gt;@parameterized.expand&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_trackpoints.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_waypoints.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_routepoints.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&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;test_get_points&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;gpxfile&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if there will be data output from get_points.&lt;/span&gt;

&lt;span class="sd"&gt;        Test if:&lt;/span&gt;
&lt;span class="sd"&gt;        - points exists for different types.&lt;/span&gt;
&lt;span class="sd"&gt;        - what will happen if types exists, but no data?&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpxfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;points&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;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_points&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="nd"&gt;@parameterized.expand&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_trackpoints.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_waypoints.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_routepoints.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&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;test_get_elevations&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;gpxfile&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if all elevations will be returned from input element.&lt;/span&gt;
&lt;span class="sd"&gt;        Test should check if elements are TrackPoints Route Points or Way Points.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpxfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;elevations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_elevations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elevations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="nd"&gt;@parameterized.expand&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_trackpoints.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_waypoints.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;web/tests/example_data/fast_example_routepoints.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;),&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;test_get_elevations_len&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;gpxfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elevations_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Test if proper amount of elevations are read by get_elevations method.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpxfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;elevations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_elevations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elevations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;elevations_len&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;What I don't like about this source-code?&lt;/h1&gt;
&lt;p&gt;I don't like that there is a lot of repeated code (if parameters are a repeated code ? ) that leads to break the &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY Principle&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I'll need to think if this is actually a "repeated" code or if some of this functions does not need so much of parameter types.&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/60c5455"&gt;Fixes few pylint errors.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/1c74095"&gt;Fixes waypoints &amp;amp; routepoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/d6c4090"&gt;Adds route-track-way points example with nose parameterized&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;VIM + Plugins (&lt;a href="https://github.com/tpope/vim-fugitive"&gt;Fugitive&lt;/a&gt;, &lt;a href="https://github.com/plasticboy/vim-markdown"&gt;Vim-Markdown&lt;/a&gt; and &lt;a href="https://github.com/benmills/vimux"&gt;Vimux&lt;/a&gt; )&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Add test-cases for business logic to GPXReader - endorphines-algorithms :)&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Python backend - initial REST-API.&lt;/h4&gt;
&lt;h4&gt;2. Making API documentation - research for best API documentation!&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="pytest"></category><category term="tdd"></category><category term="trackpoints"></category><category term="waypoints"></category><category term="routepoints"></category></entry><entry><title>GPXReader - Clearing TDD Tests</title><link href="http://witkowskibartosz.com/blog/gpxreader-clearing-tdd-tests.html" rel="alternate"></link><published>2017-04-15T18:00:00+02:00</published><updated>2017-04-15T18:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-15:/blog/gpxreader-clearing-tdd-tests.html</id><summary type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;As you might probably read at &lt;a href="fancybox-plugin-and-test-driven-development-flow.md"&gt;yesterdays article&lt;/a&gt; I've finally found how I shoud follow TDD principle and "flow".&lt;/p&gt;
&lt;p&gt;It basically means, I will not create a bunch of tests, but instead I'll create a bunch of not-implemented methods/functions that are documented about their responsibilities but has no …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;As you might probably read at &lt;a href="fancybox-plugin-and-test-driven-development-flow.md"&gt;yesterdays article&lt;/a&gt; I've finally found how I shoud follow TDD principle and "flow".&lt;/p&gt;
&lt;p&gt;It basically means, I will not create a bunch of tests, but instead I'll create a bunch of not-implemented methods/functions that are documented about their responsibilities but has no code inside of them.&lt;/p&gt;
&lt;p&gt;After that I'll start working on those methods with a TDD.&lt;/p&gt;
&lt;h1&gt;Prerequisites - Clearing up pre-existing tests.&lt;/h1&gt;
&lt;h3&gt;1. Why your unittests should be fast?&lt;/h3&gt;
&lt;p&gt;I'll make an example of how my testing failed in real-life example. I was working on a python project. In that project I didn't follow the TDD rules, but instead, once the "feature" has been created I created tests that "covered" expected behaviour of source-code.&lt;/p&gt;
&lt;p&gt;These tests were not time-optimized, they used real-time data and needed access to internet service.&lt;/p&gt;
&lt;p&gt;That made them a lot time consuming. It also pushed me to not run all of the "unit-tests" but only those that I was working currently, and then before "pushing" work of the tests, check if other tests are working properly.&lt;/p&gt;
&lt;p&gt;Now as I recall it was not such a bad thing, since I didn't use TDD properly and source-code of other features was not changed in some new "features".&lt;/p&gt;
&lt;p&gt;But in some occasional cases I needed to change behaviour of features that had already test-coverage, and then I needed to run all tests that took a bit of time.&lt;/p&gt;
&lt;p&gt;Then, instead of working on tests I was waiting actually until tests will complete with success or failure. To make a more expressive example, please check following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Each run of all tests took around 120 seconds (2 minutes) (yeah .... SECONDS... :(  )  - in earlier phase of project, at the end of project it was close to 300 seconds (5 minutes... )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Each feature per day might took at least 5 runs of tests-checking to find if any regression is not on source-code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This takes 120 * 5  = 600 seconds =  10 minutes of (waste? ) time (in early phase of project)&lt;/p&gt;
&lt;p&gt;In the end it took: 300 * 5 = 1500 seconds = 25 minutes of overall interrupted idle-waiting periods.&lt;/p&gt;
&lt;p&gt;Of course I took this time to re-read source-code, but either way I was in a "waiting" stage.&lt;/p&gt;
&lt;p&gt;It's an optimistic prognosis. What If your 8h work day makes about 20-25 changes and each change you need to run all tests ?&lt;/p&gt;
&lt;p&gt;Easy to measure :  25 * 300 = 125 minutes! = more then 2 hours of (wasted?) time.&lt;/p&gt;
&lt;h3&gt;2. What I've found out in code?&lt;/h3&gt;
&lt;p&gt;In my GPXReader Tests I've found a bunch of tests that were not implemented. Those were just information for myself to speed-up development with TDD and pomodoro-technique.&lt;/p&gt;
&lt;p&gt;I've figure-out that this information is more-less self-explanatory and It's more a documentation for source-code than test-documetation.&lt;/p&gt;
&lt;p&gt;Check below how it look like before changes :&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/blob/1f38372d88114dccd0b35538090a34adcf68cb1c/bikingendorphines/tests/web/utils/test_gpx_reader.py"&gt;Link to full source-code at github&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseGPXReaderTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    A Prof Of Concept for creating one generalized GPXReader test class.&lt;/span&gt;
&lt;span class="sd"&gt;    It will then be inherited by other classes that will use TrackPoints example data,&lt;/span&gt;
&lt;span class="sd"&gt;    Route Points data and Way Points data using pytest-fixtures.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_get_points&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if there will be data output from get_points.&lt;/span&gt;

&lt;span class="sd"&gt;        Test if:&lt;/span&gt;
&lt;span class="sd"&gt;        - points exists for different types.&lt;/span&gt;
&lt;span class="sd"&gt;        - what will happen if types exists, but no data?&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;test_get_elevations&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if all elevations will be returned from input element.&lt;/span&gt;
&lt;span class="sd"&gt;        Test should check if elements are TrackPoints Route Points or Way Points.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;test_get_elevations_len&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;elevations_len&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Test if proper amount of elevations are read by get_elevations method.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;test_get_track_points&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Test if all track points are gathered&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;test_get_route_points&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Test if all route points are gathered&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;test_get_way_points&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Test if all way points are gathered&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;test_get_lowest_elevation&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Checks method for:&lt;/span&gt;
&lt;span class="sd"&gt;        - If no elevations in route, method should return None.&lt;/span&gt;
&lt;span class="sd"&gt;        - If elevations are equal or only one available, return None.&lt;/span&gt;
&lt;span class="sd"&gt;        - If more then one elevation (different) available, return lowest.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;test_get_highest_elevation&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Checks method for:&lt;/span&gt;
&lt;span class="sd"&gt;        - If no elevations in route, method should return None.&lt;/span&gt;
&lt;span class="sd"&gt;        - If elevations are equal or only one available, return None.&lt;/span&gt;
&lt;span class="sd"&gt;        - If more then one elevation (different) available, return highest.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;test_animal_figure_route&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if method named &amp;quot;animal_figure_route&amp;quot; will return proper name of animal&lt;/span&gt;
&lt;span class="sd"&gt;        for proper biking route.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractGPXReaderTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseGPXReaderTest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Abstract Implementation of Base GPX Reader Test&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_get_points&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if there will be data output from get_points.&lt;/span&gt;

&lt;span class="sd"&gt;        Test if:&lt;/span&gt;
&lt;span class="sd"&gt;        - points exists for different types.&lt;/span&gt;
&lt;span class="sd"&gt;        - what will happen if types exists, but no data?&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;points&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;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_points&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_get_elevations&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if all elevations will be returned from input element.&lt;/span&gt;
&lt;span class="sd"&gt;        Test should check if elements are TrackPoints Route Points or Way Points.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;elevations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_elevations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elevations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elevations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_get_elevations_len&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;elevations_len&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Test if proper amount of elevations are read by get_elevations method.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;elevations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_elevations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elevations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;elevations_len&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_animal_figure_route&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Test implementation for animal figure route&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.mark.usefixtures&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;gpxreader&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestTrackPointGPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractGPXReaderTest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Specific version of Abstract test-class that uses mainly TrackPoints gpx file for tests.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;3. What changes I've made to make this more clear?&lt;/h3&gt;
&lt;p&gt;So I've change this source-code and ripped it apart.&lt;/p&gt;
&lt;p&gt;I've changed the &lt;code&gt;BaseGPXReaderTest&lt;/code&gt; with functions into a Abstract class for GPXReader with functions that needs to be implemented:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/blob/gpxreader_tests/bikingendorphines/web/utils.py"&gt;Link to full source-code of this file at github&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractGPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    AbstractGPXReader - An Abstract Class containing most of methods that needs to be implemented.&lt;/span&gt;

&lt;span class="sd"&gt;    I.e.&lt;/span&gt;
&lt;span class="sd"&gt;    get_track_points(self, item_nb=0):&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_track_points&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;item_nb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Track points are gathered&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;get_route_points&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;item_nb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Route points are gathered&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;get_way_points&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;item_nb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Way points are gathered&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;get_lowest_elevation&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Returns information about lowest elevation from route&lt;/span&gt;
&lt;span class="sd"&gt;        Returns None if not found any elevations!&lt;/span&gt;

&lt;span class="sd"&gt;        Checks method for:&lt;/span&gt;
&lt;span class="sd"&gt;        - If no elevations in route, method should return None.&lt;/span&gt;
&lt;span class="sd"&gt;        - If elevations are equal or only one available, return None.&lt;/span&gt;
&lt;span class="sd"&gt;        - If more then one elevation (different) available, return lowest.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;get_highest_elevation&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Checks method for:&lt;/span&gt;
&lt;span class="sd"&gt;        - If no elevations in route, method should return None.&lt;/span&gt;
&lt;span class="sd"&gt;        - If elevations are equal or only one available, return None.&lt;/span&gt;
&lt;span class="sd"&gt;        - If more then one elevation (different) available, return highest.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&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;animal_figure_route&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Uses Points to compare route with animal shapes.&lt;/span&gt;
&lt;span class="sd"&gt;        Returns information if this route looks similar to some animal or not.&lt;/span&gt;
&lt;span class="sd"&gt;        Returns Name of animal from enumeration or None if none animal found.&lt;/span&gt;

&lt;span class="sd"&gt;        Tests if method named &amp;quot;animal_figure_route&amp;quot; will return proper name of animal&lt;/span&gt;
&lt;span class="sd"&gt;        for proper biking route.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="ne"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;For now final result does not look "much" better. Instead it's a fast implementation! :)&lt;/p&gt;
&lt;p&gt;It follows TDD technique in at least point of "fast-unit-tests". &lt;/p&gt;
&lt;p&gt;To make unit-tests faster for now, I"ve changed the .gpx example file smaller and faster to run.&lt;/p&gt;
&lt;p&gt;I've also find that the Makefile is not best optimized in terms of timing.&lt;/p&gt;
&lt;p&gt;Makefile contained &lt;code&gt;pip install -r requirements&lt;/code&gt; additionally at the "make unittest" flow , that is not needed at all if you already have pip-installed all dependency.&lt;/p&gt;
&lt;p&gt;So changes I've made in Makefile:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;unittest_all: prepare_db unittest

unittest:
    &lt;span class="nb"&gt;cd&lt;/span&gt; bikingendorphines &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; python manage.py &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now all I have to do is follow TDD technique and make tests for our GPXReader.&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/2cdb05f"&gt;Removes system-deps to check if this will fix gh-pages task problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/622ef00"&gt;Fixes finally problem with travis before-install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/dc7cded"&gt;Fixes problem with sudo on travis before-install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/fcc3376"&gt;Optimized travis &amp;amp; Makefile to make-tasks faster run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/0241387"&gt;Changes steps of travis to make things faster.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/e1b2c7e"&gt;Clears up tests code and makes them run faster.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/1f38372"&gt;Another attempt to clear tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/66005fe"&gt;Adds a Super-is-Super testing method for GPXReader&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;VIM + Plugins (&lt;a href="https://github.com/tpope/vim-fugitive"&gt;Fugitive&lt;/a&gt;, &lt;a href="https://github.com/plasticboy/vim-markdown"&gt;Vim-Markdown&lt;/a&gt; and &lt;a href="https://github.com/benmills/vimux"&gt;Vimux&lt;/a&gt; )&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.tomatoid.com/pomodoro"&gt;Tomatoid&lt;/a&gt; - a Pomodoro-Technique web-based(and not only) web-service.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Add even more tests to GPXReader.&lt;/s&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;s&gt; Created additional markdown_commits script that transforms git-log into Markdown links :) check &lt;a href="https://github.com/anselmos/linux-utils/blob/master/markdown_commits"&gt;HERE&lt;/a&gt; &lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;2. Add test-cases for business logic to GPXReader - endorphines-algorithms :)&lt;/h4&gt;
&lt;h4&gt;3. Python backend - initial REST-API.&lt;/h4&gt;
&lt;h4&gt;4. Making API documentation - research for best API documentation!&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="pytest"></category><category term="tdd"></category><category term="endorphines-algorithms"></category></entry><entry><title>FancyBox Plugin and Test Driven Development Flow</title><link href="http://witkowskibartosz.com/blog/fancyBox-plugin-and-test-driven-development-flow.html" rel="alternate"></link><published>2017-04-12T15:30:00+02:00</published><updated>2017-04-12T15:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-12:/blog/fancyBox-plugin-and-test-driven-development-flow.html</id><summary type="html">&lt;h1&gt;Test Driven Development Flow&lt;/h1&gt;
&lt;p&gt;So lastly I've introduced to myself a Test Driven Development, but unfortunatelly I didn't examine the flow and approach as much as I should.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href="https://sites.google.com/site/unclebobconsultingllc/"&gt;Uncle Bob&lt;/a&gt; I've realized what exactly TDD flow looks like.&lt;/p&gt;
&lt;h3&gt;1. Make a test that (should) fail.&lt;/h3&gt;
&lt;p&gt;The idea is …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Test Driven Development Flow&lt;/h1&gt;
&lt;p&gt;So lastly I've introduced to myself a Test Driven Development, but unfortunatelly I didn't examine the flow and approach as much as I should.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href="https://sites.google.com/site/unclebobconsultingllc/"&gt;Uncle Bob&lt;/a&gt; I've realized what exactly TDD flow looks like.&lt;/p&gt;
&lt;h3&gt;1. Make a test that (should) fail.&lt;/h3&gt;
&lt;p&gt;The idea is not to make any type of source code before test-code, but instead, create a test that probably will fail if you haven't got any source-code.&lt;/p&gt;
&lt;h3&gt;2. Pass your failing test&lt;/h3&gt;
&lt;p&gt;Make your initial test not failing by creating just enought source-code for this particular test.&lt;/p&gt;
&lt;h3&gt;3. Refactor your source code.&lt;/h3&gt;
&lt;p&gt;Then finally refactor your code to look better.&lt;/p&gt;
&lt;h3&gt;4. Repeat steps 1-3 untill your source-code does what you expect it from.&lt;/h3&gt;
&lt;h3&gt;Check this awesome image that will help me with TDD approach in this initial days of working in this system:&lt;/h3&gt;
&lt;p&gt;&lt;a href="images/tdd_global_lifecycle.png"&gt;TDD Global Lifecycle by Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What I did wrong this time ? :)&lt;/h1&gt;
&lt;p&gt;Well... this time I've figure out that I'll make a bunch of tests for all bunch of functions that will help me focus on small elements in a short period of time (pomodoro technique-remember?)&lt;/p&gt;
&lt;p&gt;Then I ofcourse would normally start working on this tests to make a TDD approach.&lt;/p&gt;
&lt;p&gt;But let's follow TDD in a different way.&lt;/p&gt;
&lt;p&gt;Let's use this information I've gathered as more "documentation" of what should be done, then how this code should look like.&lt;/p&gt;
&lt;h1&gt;Initial test.&lt;/h1&gt;
&lt;p&gt;Lets first create a test for our plugin: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_plugin_registers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Check if plugin registers to article_generator_finalized&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;assert_receiver_registered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fancybox_plugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And then make source-code that will pass test (that's a refactored code):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Registers plugin&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fancybox_plugin&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;assert_receiver_registered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;receiver_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;Checks if receiver is registered to signals generator&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_receivers_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;receiver_name&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;test_plugin_registers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Check if plugin registers to article_generator_finalized&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;assert_receiver_registered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fancybox_plugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;I've made thus far 3 tests that checks few simple but needed things.&lt;/p&gt;
&lt;p&gt;For now final result looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;FancyBox unittests&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pelican&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;A simple Article class&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;article_generator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Article generator&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;Article&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;fancybox_plugin&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Fanxybox plugin - temporary code placement&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Registers plugin&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fancybox_plugin&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;assert_receiver_registered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;receiver_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;Checks if receiver is registered to signals generator&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;article_generator_finalized&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_receivers_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;receiver_name&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;test_plugin_registers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Check if plugin registers to article_generator_finalized&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;assert_receiver_registered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fancybox_plugin&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;test_article_generator_return_article&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Checks if generator return article&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article_generator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Article&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;test_given_article_generator_check_article_content_exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Checks if article content field exists in article&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;article_generator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;content&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/pelican-fancybox/commit/1183c6c"&gt;Changes name of function to assert_*&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/pelican-fancybox/commit/46df51a"&gt;Cleans code for return_article.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/pelican-fancybox/commit/02ab7ec"&gt;Adds article_generator with simple Article class&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/pelican-fancybox/commit/fc3ecf1"&gt;Cleans code for test_plugin_registers&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/pelican-fancybox/commit/2c1bf5c"&gt;Adds first test if plugin is connected to signals.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/pelican-fancybox/commit/c093bd9"&gt;Replaces old test into documentation.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;vi/vim&lt;/li&gt;
&lt;li&gt;pytest&lt;/li&gt;
&lt;li&gt;docker&lt;/li&gt;
&lt;li&gt;tmux&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Make tests for fancybox plugin&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Make more tests and source-code of fancybox plugin&lt;/h4&gt;
&lt;h4&gt;2. Start working on plugin for asciinema player.&lt;/h4&gt;
&lt;h4&gt;3. See &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/issues"&gt;ISSUES&lt;/a&gt; task-list for this 'mini' growing project :)&lt;/h4&gt;</content><category term="anselmos-pelican-blog-source"></category><category term="mini-project"></category><category term="pelican"></category><category term="fancy-box"></category><category term="fancybox-plugin"></category><category term="image-viewer-plugin"></category><category term="tdd"></category><category term="tdd-approach"></category><category term="tips-tricks"></category><category term="pelican-plugin"></category></entry><entry><title>GPXReader - Business Logic and Tests</title><link href="http://witkowskibartosz.com/blog/gpxreader-business-logic-and-tests.html" rel="alternate"></link><published>2017-04-09T20:00:00+02:00</published><updated>2017-04-09T20:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-09:/blog/gpxreader-business-logic-and-tests.html</id><summary type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I've informed you I'll be doing Business Logic for Biking Endorphines.&lt;/p&gt;
&lt;p&gt;To make best of my time I've considered to go with TDD and that's why I'll first implement Tests for Business Logic.&lt;/p&gt;
&lt;p&gt;This will propably shape all business logic, but I'll have already tests with myself for future …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I've informed you I'll be doing Business Logic for Biking Endorphines.&lt;/p&gt;
&lt;p&gt;To make best of my time I've considered to go with TDD and that's why I'll first implement Tests for Business Logic.&lt;/p&gt;
&lt;p&gt;This will propably shape all business logic, but I'll have already tests with myself for future.&lt;/p&gt;
&lt;h1&gt;Prerequisites - Business Logic&lt;/h1&gt;
&lt;h3&gt;1. Business logic for Biking-Endorphines.&lt;/h3&gt;
&lt;p&gt;So the Business Logic for Biking Endorphines is going to be Endorphines badges algorithms themselves.&lt;/p&gt;
&lt;p&gt;Just as I've revealed in &lt;a href="behind-closed-doors-b-e-idea.html"&gt;behind-closed-doors&lt;/a&gt;, type of algorithms for endorphines badges will be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adventure style - Calculate how you could change your route to (shorten/lenghen/alternate) your ride-path&lt;/li&gt;
&lt;li&gt;Training style - to keep up with every-day motivation for training - i.e. showing how your timing can change by training today.&lt;/li&gt;
&lt;li&gt;Family style - to find exciting places that you didn't know about and to share this experience with family.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And others that I currently haven't figure-out yet.&lt;/p&gt;
&lt;h3&gt;2. Why I will start my implementation of B-Logic with tests?&lt;/h3&gt;
&lt;p&gt;So first of all, the TDD approach in my opinion is something beautiful in it's core. You first create tests for functions/methods/classes that will make your b-logic.&lt;/p&gt;
&lt;p&gt;This tests will fail at beginning. But they will also keep you motivated to keep-up with code and give you path by which you should follow when creating code-itself.&lt;/p&gt;
&lt;p&gt;Lately I've watched &lt;a href="https://www.youtube.com/watch?v=EiOglTERPEo"&gt;YT talk about Super is Super - by Raymond Hettinger&lt;/a&gt; That I was really impressed about!&lt;/p&gt;
&lt;p&gt;I might think about using TDD and the &lt;code&gt;Super is Super&lt;/code&gt; in my implementation.&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;My limited resources made me create only simplest tests for pre-existing code and some "NotImplemented" tests that will need to be created in future.&lt;/p&gt;
&lt;p&gt;I've found out that if you put "NotImplementedError" as return in tests, this test-function than does not fail!&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/a973bccabff4e5d223f6fd7a75e4d2fba997bbab"&gt;Adds few new tests for gpxreader&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/d1b72bc647bfec72f7f8797c3662296ebbefcb44"&gt;Adds elevation tests for gpxreader&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;VIM + Plugins (&lt;a href="https://github.com/tpope/vim-fugitive"&gt;Fugitive&lt;/a&gt;, &lt;a href="https://github.com/plasticboy/vim-markdown"&gt;Vim-Markdown&lt;/a&gt; and &lt;a href="https://github.com/benmills/vimux"&gt;Vimux&lt;/a&gt; )&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Add more tests to GPXReader test cases.&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Add even more tests to GPXReader.&lt;/h4&gt;
&lt;h4&gt;2. Add test-cases for business logic to GPXReader - endorphines-algorithms :)&lt;/h4&gt;
&lt;h4&gt;3. Python backend - initial REST-API.&lt;/h4&gt;
&lt;h4&gt;4. Making API documentation - research for best API documentation!&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="pytest"></category><category term="business-logic"></category><category term="tdd"></category><category term="endorphines-algorithms"></category></entry><entry><title>Biking Endorphines - Introduction to Android sub-project</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-introduction-to-android-sub-project.html" rel="alternate"></link><published>2017-04-06T00:00:00+02:00</published><updated>2017-04-06T00:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-06:/blog/biking-endorphines-introduction-to-android-sub-project.html</id><summary type="html">&lt;h1&gt;Introduction - What's this Android application doing in python project??&lt;/h1&gt;
&lt;p&gt;You may wonder why use Android application in python project??&lt;/p&gt;
&lt;p&gt;Python project was from the beginning only one part of product that I wanted to create.&lt;/p&gt;
&lt;p&gt;Second part was always the Android application that will gather data from GPS and show …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction - What's this Android application doing in python project??&lt;/h1&gt;
&lt;p&gt;You may wonder why use Android application in python project??&lt;/p&gt;
&lt;p&gt;Python project was from the beginning only one part of product that I wanted to create.&lt;/p&gt;
&lt;p&gt;Second part was always the Android application that will gather data from GPS and show information about Endorphines Badges.&lt;/p&gt;
&lt;h1&gt;Prerequisites - Android-Studio&lt;/h1&gt;
&lt;h3&gt;1. How to install Android Studio  (on Ubuntu)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Please download the &lt;a href="https://dl.google.com/dl/android/studio/ide-zips/2.3.1.0/android-studio-ide-162.3871768-linux.zip"&gt;Android Studio 2.3 (~429MB)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Unpack files with &lt;code&gt;unzip android-studio-ide-162.3871768-linux.zip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Install JRE if you have not yet done it by &lt;code&gt;sudo apt-get install -y default-jre &amp;amp;&amp;amp; sudo apt-get install -y default-jdk&lt;/code&gt;&lt;ul&gt;
&lt;li&gt;If for some reason your default-jdk is below Android-Studio requirements, try to use this:&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo add-apt-repository ppa:webupd8team/java -y
sudo apt-get update
sudo apt-get install oracle-java8-installer

sudo apt-get install oracle-java8-set-default
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Check version:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;java -version
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;If you have already installed Java Runtime Environment (JRE) then after typing "sh android-studio/bin/studio.sh" you should see IDE start running.&lt;/li&gt;
&lt;li&gt;If after installing JRE you see error that says &lt;code&gt;No JDK found. Please validate either STUDIO_JDK, JDK_HOME or JAVA_HOME environment variable points to valid JDK installation&lt;/code&gt;, don't panic.&lt;ul&gt;
&lt;li&gt;Try changing &lt;code&gt;JDK_HOME system variable&lt;/code&gt; to proper path of jdk i.e. &lt;code&gt;JDK_HOME=/usr/java/jdk1.7.0.21/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Android introduction - how to start your first project&lt;/h3&gt;
&lt;p&gt;Take few minutes of your time and explore &lt;a href="https://developer.android.com/training/basics/firstapp/creating-project.html"&gt;"Create an Android Projects"&lt;/a&gt; - This will give you the most basic information about how to startup first project with Android Studio.&lt;/p&gt;
&lt;h3&gt;3. What should be in your git-repository?&lt;/h3&gt;
&lt;p&gt;All your files that are project resources. &lt;/p&gt;
&lt;p&gt;GitIgnore can be generated with &lt;a href="https://www.gitignore.io/"&gt;gitignore.io&lt;/a&gt; i.e. for &lt;a href="https://www.gitignore.io/api/android%2Cintellij%2Candroidstudio"&gt;android, android-studio and intellij&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you accidentally pushed build files, first do :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Gradle build:clean task - this will remove this files so you know what files are not-needed in &lt;code&gt;git status&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;use bfg repo cleaner as described &lt;a href="https://rtyley.github.io/bfg-repo-cleaner/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;commit and push cleaned commits to your remote repository&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. Why not use vi/vim and terminal for all your android-development ?&lt;/h3&gt;
&lt;p&gt;Well... you can certainly use vim for development, but vim-itself is not perfect IDE for the job. You should at least get yourself around some vim-plugins that could simulate some of the AndroidStudio behaviour, i.e. Gradle usage:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/hsanson/vim-android"&gt;Vim-Android Plugin by hsanson&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;h3&gt;1. What I've created as initial?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Separated git repository available &lt;a href="https://github.com/anselmos/Biking-Endorphines-Android-App"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adding android application repository to main repository as a module&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If you want to know how to do that, please follow &lt;a href="https://chrisjean.com/git-submodules-adding-using-removing-and-updating/"&gt;this link&lt;/a&gt; - for those impatient, use &lt;code&gt;git submodule add GIT-LINK [optional directory to which clone repo]&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;i.e. &lt;code&gt;git submodule add https://github.com/anselmos/Biking-Endorphines-Android-App androidapp&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Initialized clean empty project for androidapp with minimum API 16(Android 4.1 - JellyBean) - since I've got one device that I'll use for tests and according to Google Play Store information about 95% of devices uses this minimum version of API.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Setup en Empty Activity for startup.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. What are the plans for this android-sub-project?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Layout :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;information about gps  -is it on, active and properly initialized &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;starting and stopping/pausing button for biking activity&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;statistics mocked for this time, but eventually gathered from rest-api.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start/Stop gathering data from gps as a GPX file format&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make Login-page that will login android-device in backend as a device-id, timestamp, user-id&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gather all information about statistics with endorphines-badges!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Presentation of Endorphines Badges with fun icons.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Divination - Tea-Leaf Reading for your biking-endorphines-badges - what you could do to gather more badges ! - based on analysis of bike-rides. - a pseudo AI for badges gathering&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines-Android-App/commit/bd1d7113356b18b0746b65f5877ca88922d7c200"&gt;Initialized Android Projects with GitIgnore&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/696789d8d634bab4f52a3ed4ebd90cba7824f248"&gt;Adds androidapp as submodule&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Android Studio&lt;/li&gt;
&lt;li&gt;VIM + Plugins (&lt;a href="https://github.com/tpope/vim-fugitive"&gt;Fugitive&lt;/a&gt;, &lt;a href="https://github.com/plasticboy/vim-markdown"&gt;Vim-Markdown&lt;/a&gt; and &lt;a href="https://github.com/benmills/vimux"&gt;Vimux&lt;/a&gt; )&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. I've added git submodule in a bad way.&lt;/h3&gt;
&lt;p&gt;Initially I've added android application to project repository in a bad way - I've forgot to add directory path to which submodule should be cloned.&lt;/p&gt;
&lt;p&gt;So I've decided to run &lt;code&gt;rm -rf&lt;/code&gt; on git-submodule files and the &lt;code&gt;gitsubmodule&lt;/code&gt; config file.&lt;/p&gt;
&lt;p&gt;Unfortunatelly when I tried to use &lt;code&gt;git add submodule&lt;/code&gt; again, I've crossed at error like this :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;A git directory &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;[HERE GOES NAME OF DIRECTORY]&amp;#39;&lt;/span&gt; is found locally with remote&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The problem was almost identical as described &lt;a href="http://stackoverflow.com/questions/20929336/git-submodule-add-a-git-directory-is-found-locally-issue"&gt;at stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;I needed to remove &lt;code&gt;.git/submodule/[Directory-containing-submodule]&lt;/code&gt; to make git forget about my first attempt to clone submodule.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://developer.android.com/studio/index.html"&gt;Android Studio&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://developer.android.com/training/basics/firstapp/creating-project.html"&gt;Create an Android Projects&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://developer.android.com/studio/build/index.html"&gt;Configure Your Build&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://chrisjean.com/git-submodules-adding-using-removing-and-updating/"&gt;Git Submodules: Adding, Using, Removing, Updating&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Android initials - how to start-up with Android Projects - and that sort of things.&lt;/s&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;s&gt;2. Android Sub-project - plans and draft of application.&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Add more tests to GPXReader test cases.&lt;/h4&gt;
&lt;h4&gt;2. Add more business logic to GPXReader - endorphines-algorithms :)&lt;/h4&gt;
&lt;h4&gt;3. Python backend - initial REST-API.&lt;/h4&gt;
&lt;h4&gt;4. Making API documentation - research for best API documentation!&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="android-introduction"></category><category term="gitignore"></category><category term="android-studio"></category><category term="vim-android"></category></entry><entry><title>Pelican Blog with Fancy Box image viewer</title><link href="http://witkowskibartosz.com/blog/pelican-blog-with-fancy-box-image-viewer.html" rel="alternate"></link><published>2017-04-05T00:00:00+02:00</published><updated>2017-04-05T00:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-04-05:/blog/pelican-blog-with-fancy-box-image-viewer.html</id><summary type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;As I've informed you at post &lt;a href="pelican-blog-with-pelican-bootstrap3-theme"&gt;Pelican Blog with Pelican-Bootstrap3 theme&lt;/a&gt;, I've started working on fancy-box image viewer and adjusting it's usage for pelican blogging engine.&lt;/p&gt;
&lt;h1&gt;FancyBox - What it is and how it works&lt;/h1&gt;
&lt;p&gt;Quoting product site:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FancyBox is a tool for displaying images, html content and multi-media in …&lt;/code&gt;&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;As I've informed you at post &lt;a href="pelican-blog-with-pelican-bootstrap3-theme"&gt;Pelican Blog with Pelican-Bootstrap3 theme&lt;/a&gt;, I've started working on fancy-box image viewer and adjusting it's usage for pelican blogging engine.&lt;/p&gt;
&lt;h1&gt;FancyBox - What it is and how it works&lt;/h1&gt;
&lt;p&gt;Quoting product site:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FancyBox is a tool for displaying images, html content and multi-media in a Mac-style "lightbox" that floats overtop of web page.
It was built using the jQuery library. Licensed under both MIT and GPL licenses&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Product page &lt;a href="http://fancybox.net/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;FancyBox - How to use it?&lt;/h1&gt;
&lt;p&gt;FancyBox uses jQuery as main dependency. For using Fancybox you have to add it to your head/body of web-page.&lt;/p&gt;
&lt;p&gt;Here is a simple code-block you can use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Also you have to add Javascript Fancybox script (CDN recommended to download before):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/fancybox/jquery.fancybox-1.3.4.pack.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;CDN for fancybox you can find here:
&lt;code&gt;https://cdnjs.com/libraries/fancybox&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And finally the CSS style file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/fancybox/jquery.fancybox-1.3.4.css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;media&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;screen&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;What are pelican-plugins and how to use it?&lt;/h1&gt;
&lt;p&gt;Pelican Plugins are just a regular python files, but added in &lt;code&gt;pelicanconf&lt;/code&gt; file as a "PLUGINS". They extend functionality of original Pelican engine by using the &lt;code&gt;signals&lt;/code&gt; - so registering on a signal type - for more information about that please &lt;a href="http://docs.getpelican.com/en/stable/plugins.html"&gt;check pelican plugin site&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;FancyBox - why create a plugin out-of-it ??&lt;/h1&gt;
&lt;p&gt;First of all - because I haven't done any plugins at all yet - sounds like fun and a lot of try-and-error :)&lt;/p&gt;
&lt;p&gt;Besides - I don't want to have my script incorporated in Markdown file each time I want to add image to it.&lt;/p&gt;
&lt;p&gt;Plugin will make that work for me ! (&lt;a href="http://threevirtues.com/"&gt;laziness is for virtues programmers&lt;/a&gt; )&lt;/p&gt;
&lt;h1&gt;Fancybox plugin - I've created a separated github-project for that!&lt;/h1&gt;
&lt;p&gt;I've decided to move FancyBox plugin to separated github-project for convenience - in that situation no dependency between version of pelican and plugin will exist.&lt;/p&gt;
&lt;h1&gt;Fancybox initial approach&lt;/h1&gt;
&lt;p&gt;As usually I've started coding without re-thinking. And taking into account my time-limits it was a bit of failure.&lt;/p&gt;
&lt;p&gt;I've almost found solution and it almost worked, but it was a lot of copy-paste that I don't really like and apprieciate.&lt;/p&gt;
&lt;p&gt;So I've figure-out to change my approach after I've seen polish programmer/blogger Maciej Anisewicz's vlog at Youtube about &lt;a href="https://www.youtube.com/watch?v=s-MdgvKL5bM"&gt;"programming flow is a bullsh*t"&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It's a polish programming talk that to summarize - says about TDD as better approach for programming then having all information about program-flow in your mind, and about making notes for all your ideas.&lt;/p&gt;
&lt;h1&gt;Fancybox final approach&lt;/h1&gt;
&lt;p&gt;I've decided to go additional way in my programming approach - to make best out of the &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That's why I'll first create tests for code and then create code itself. It'll be a longer way, but in that solution I'll use pomodoro-technique much more efficient.&lt;/p&gt;
&lt;p&gt;I've created a stubs for my tests that have a "NotImplementedError" raised. Once I'll finish with tests I'll then start coding.&lt;/p&gt;
&lt;p&gt;Let's finally find-out if the so called "TDD" is worth using or not :)&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;A Github project for plugin:
&lt;a href="https://github.com/anselmos/pelican-fancybox"&gt;Pelican-Fancybox&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Commits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/pelican-fancybox/commit/0e92625f8821f6c15021360e47383f5e817689b6"&gt;Adds initial tdd tests that are not-yet-implemented&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/pelican-fancybox/commit/7430c54e25fba81996e87312911033bdac77af46"&gt;Adds initial solution -not yet working&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Pelican-Blog Pull Requests&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Made pull-request for theme - &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/pull/5"&gt;#5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tips &amp;amp; Tricks&lt;/h1&gt;
&lt;h4&gt;1. TDD approach&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Make tests that will fail&lt;/li&gt;
&lt;li&gt;Make code and fix code so that tests will pass&lt;/li&gt;
&lt;li&gt;Commit your fully TDD certified code!! :)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/vIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;1. &lt;s&gt;I'll continue working on pelican-theme with using &lt;code&gt;fancybox&lt;/code&gt;&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://fancybox.net/howto"&gt;Fancybox HowTo&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/kaizer666/pelican-fancybox"&gt;Fancybox Plugin by kaizer666&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.gitignore.io/api/python"&gt;GitIgnore.io for python&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://pythonhosted.org/Markdown/extensions/api.html"&gt;Markdown extensions in python.org&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://code.tutsplus.com/tutorials/beginning-test-driven-development-in-python--net-30137"&gt;Beginning Test-Driven Development in Python&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;Test-driven development&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://tomato-timer.com/"&gt;Tomoto Timer web-app&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Make tests for fancybox plugin&lt;/h4&gt;
&lt;h4&gt;2. Start working on plugin for asciinema player.&lt;/h4&gt;
&lt;h4&gt;3. See &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/issues"&gt;ISSUES&lt;/a&gt; task-list for this 'mini' growing project :)&lt;/h4&gt;</content><category term="anselmos-pelican-blog-source"></category><category term="mini-project"></category><category term="pelican"></category><category term="fancy-box"></category><category term="fancybox-plugin"></category><category term="image-viewer-plugin"></category><category term="tdd"></category><category term="tdd-approach"></category><category term="tips-tricks"></category><category term="pelican-plugin"></category></entry><entry><title>Pytests Unit Testcase for Biking Endorphines</title><link href="http://witkowskibartosz.com/blog/pytests_unit_testcase_for_biking_endorphines.html" rel="alternate"></link><published>2017-03-31T00:00:00+02:00</published><updated>2017-03-31T00:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-31:/blog/pytests_unit_testcase_for_biking_endorphines.html</id><summary type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;So my first initial change for Parameterizing test-cases was a bit of failure - you can check this &lt;a href="parameterized-django-testcases-at-biking-endorphines"&gt;Parameterized Django Testcases At Biking Endorphines&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let's change that :)&lt;/p&gt;
&lt;h1&gt;Prerequisites - How to use Pytests&lt;/h1&gt;
&lt;h3&gt;1. Install pytests with pip :&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install pytest
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;2. Import Pytest in your file containing tests:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytest …&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;So my first initial change for Parameterizing test-cases was a bit of failure - you can check this &lt;a href="parameterized-django-testcases-at-biking-endorphines"&gt;Parameterized Django Testcases At Biking Endorphines&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let's change that :)&lt;/p&gt;
&lt;h1&gt;Prerequisites - How to use Pytests&lt;/h1&gt;
&lt;h3&gt;1. Install pytests with pip :&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install pytest
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;2. Import Pytest in your file containing tests:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytest&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;3. But how do you actually use it ?&lt;/h3&gt;
&lt;p&gt;That's a good question.&lt;/p&gt;
&lt;p&gt;First create a file with different name then &lt;code&gt;pytest.py&lt;/code&gt; i.e. &lt;code&gt;first_test.py&lt;/code&gt; and put similar content as I've created :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Pytests example&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytest&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Simple adding function for pytest showcase&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_answer_fail&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Test for checking func with negative values&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_answer_success&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Test for checking func with possitive values&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then use following bash command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pytest -rs first_test.py
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That should make following output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pytest -rs first_pytest.py 
&lt;span class="o"&gt;============================================================================================================&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; session &lt;span class="nv"&gt;starts&lt;/span&gt; &lt;span class="o"&gt;============================================================================================================&lt;/span&gt;
platform linux2 -- Python &lt;span class="m"&gt;2&lt;/span&gt;.7.6, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
rootdir: /home/bawi/projects/deployed/anselmos_blog/data/content/examples/pytest, inifile:
collected &lt;span class="m"&gt;2&lt;/span&gt; items 

first_pytest.py ..

&lt;span class="o"&gt;=========================================================================================================&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; passed in &lt;span class="m"&gt;0&lt;/span&gt;.02 &lt;span class="nv"&gt;seconds&lt;/span&gt; &lt;span class="o"&gt;==========================================================================================================&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;What changes I've made in code  - a diff between code-commits using asciinema and vim-diff tool?&lt;/h1&gt;
&lt;h3&gt;1. I've followed &lt;a href="https://docs.pytest.org/en/latest/goodpractices.html#test-discovery"&gt;Good Integration Practices&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;What that means ? I've figure-out that this tests that I intent to create are out-side of django scope, so why not just put them literally out-side?&lt;/p&gt;
&lt;p&gt;That's why I've created tests directory at directory bikingendorphines/tests and put all my test-files in there.&lt;/p&gt;
&lt;h3&gt;2. Test-Case itself.&lt;/h3&gt;
&lt;p&gt;Now I've change code so it looks like this :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Tests for GPXReader class&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytest&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;web.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;module&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;bikingendorphines/example_data/15212277.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;bikingendorphines/example_data/15212277.gpx&amp;#39;&lt;/span&gt;
    &lt;span class="p"&gt;]&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;gpxreader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Creates GPXReader instance with predefined gpx file&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# pylint: disable=redefined-outer-name&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_get_points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Tests if there will be data output from get_points.&lt;/span&gt;

&lt;span class="sd"&gt;    Test if:&lt;/span&gt;
&lt;span class="sd"&gt;    - points exists for different types.&lt;/span&gt;
&lt;span class="sd"&gt;    - what will happen if types exists, but no data?&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;points&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;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_points&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;Check how much my code changed in this commit that shows all diffs:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pull/13/commits/8a5fee5bfabaea490c94b0014f73b5c7d96492de"&gt;Adds pytest. Adds GPXReader pytest-alike test&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;That's the same commit that changes GPXReader:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pull/13/commits/8a5fee5bfabaea490c94b0014f73b5c7d96492de"&gt;Adds pytest. Adds GPXReader pytest-alike test&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And I've finally Squashed and Merged the gpx-solution as a initial solution.&lt;/p&gt;
&lt;p&gt;Now I hope Travis will make my day better and confirm pylint&amp;amp;unittest as a good-to-go and create Pyreverse GH PAGE :)&lt;/p&gt;
&lt;p&gt;&lt;a href="https://travis-ci.org/anselmos/Biking-Endorphines/builds/217314530"&gt;Check results of Travis here &lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Update : Yes :) Travis accepted my changes and created pyreverse output in gh-pages, see &lt;a href="https://anselmos.github.io/Biking-Endorphines/pyreverse.html"&gt;GH_PAGE&lt;/a&gt;, &lt;a href="https://anselmos.github.io/Biking-Endorphines/classes_Biking-Endorphines-Web.png"&gt;Classes as PNG File&lt;/a&gt;&lt;/h3&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;VIM + Plugins (&lt;a href="https://github.com/tpope/vim-fugitive"&gt;Fugitive&lt;/a&gt;, &lt;a href="https://github.com/plasticboy/vim-markdown"&gt;Vim-Markdown&lt;/a&gt; and &lt;a href="https://github.com/benmills/vimux"&gt;Vimux&lt;/a&gt; )&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. Don't try to name your file with test-cases a &lt;code&gt;pytest.py&lt;/code&gt; ! :)&lt;/h3&gt;
&lt;p&gt;If your filename will have name &lt;code&gt;pytest.py&lt;/code&gt; as I did for my example of usage pytest, I've found python mismatched pytest and was confused.&lt;/p&gt;
&lt;p&gt;Error like this popup:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;________________________________________________________________________________________________________ ERROR collecting pytest.py _________________________________________________________________________________________________________
import file mismatch:
imported module &lt;span class="s1"&gt;&amp;#39;pytest&amp;#39;&lt;/span&gt; has this __file__ attribute:
    /home/bawi/projects/deployed/anselmos_blog/data/content/examples/pytest/.env/local/lib/python2.7/site-packages/pytest.py
which is not the same as the &lt;span class="nb"&gt;test&lt;/span&gt; file we want to collect:
    /home/bawi/projects/deployed/anselmos_blog/data/content/examples/pytest/pytest.py
HINT: remove __pycache__ / .pyc files and/or use a unique basename &lt;span class="k"&gt;for&lt;/span&gt; your &lt;span class="nb"&gt;test&lt;/span&gt; file modules
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;You may overcome this issue change your name to something different than name of the library itself :)&lt;/p&gt;
&lt;h3&gt;2. Create plan and stick to it&lt;/h3&gt;
&lt;p&gt;That's more a Tips&amp;amp;Tricks then Lessons Learned, but it may also count as LL.
I've figure-out finally how to manage the planning - I'll try my method and let you know if it will actually work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a .md file for article &lt;/li&gt;
&lt;li&gt;Make only main parts information of article that will briefly describe a kind-of-todo&lt;/li&gt;
&lt;li&gt;Make all of this parts and describe them more deeply.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://blog.ionelmc.ro/2014/05/25/python-packaging/#the-structure"&gt;Packaging a python library&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.pytest.org/en/latest/goodpractices.html#test-discovery"&gt;Pytest-Good Integration Practices&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.pytest.org/en/latest/getting-started.html#our-first-test-run"&gt;Pytest-Installation and Getting Started&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.pytest.org/en/latest/fixture.html#fixture-parametrize"&gt;pytest fixtures: explicit, modular, scalable&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://pytest-django.readthedocs.io/en/latest/tutorial.html"&gt;Getting started with pytest and pytest-django&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Accomplished:&lt;/h1&gt;
&lt;h4&gt;&lt;s&gt;1. Change behaviour of GPXReaderTestCase to more pytest alike and add some more test code&lt;/s&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;s&gt;2. Push finally first version of GPX Reader to master via pull-request.&lt;/s&gt;&lt;/h4&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Add more tests to GPXReader test cases.&lt;/h4&gt;
&lt;h4&gt;2. Add more business logic to GPXReader - endorphines-algorithms :)&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="django.testcase"></category><category term="pytest"></category><category term="unittest"></category></entry><entry><title>Parameterized Django Testcases At Biking Endorphines</title><link href="http://witkowskibartosz.com/blog/parameterized-django-testcases-at-biking-endorphines.html" rel="alternate"></link><published>2017-03-30T00:00:00+02:00</published><updated>2017-03-30T00:00:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-30:/blog/parameterized-django-testcases-at-biking-endorphines.html</id><summary type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;After reviewing what is at the &lt;a href="https://github.com/anselmos/Biking-Endorphines/tree/gpx_reader"&gt;gpx_reader branch&lt;/a&gt; I've found #TODO that said about making mocks, but it was not best name for what I've intended to do. I've wanted to parameterized the TestCase, so I could use different type of test-source data for one and the same test …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;After reviewing what is at the &lt;a href="https://github.com/anselmos/Biking-Endorphines/tree/gpx_reader"&gt;gpx_reader branch&lt;/a&gt; I've found #TODO that said about making mocks, but it was not best name for what I've intended to do. I've wanted to parameterized the TestCase, so I could use different type of test-source data for one and the same test source-code.&lt;/p&gt;
&lt;p&gt;In my professional work I've already done something similar, so figuring this out was not hard, hence I've found the &lt;a href="https://github.com/wolever/parameterized"&gt;parameterized library&lt;/a&gt; and used it.&lt;/p&gt;
&lt;h1&gt;Prerequisites - How to use Parameterized&lt;/h1&gt;
&lt;p&gt;Parameterized is a python library that usage is pretty simple.&lt;/p&gt;
&lt;h4&gt;1. Install Parameterized with pip:&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install parameterized
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;2. Import Parameterized in your tests*.py files:&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;parameterized&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parameterized&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;3. Usage - here we go!&lt;/h4&gt;
&lt;p&gt;So how to use it?&lt;/p&gt;
&lt;p&gt;Well taking into account I'm working with django.TestCase that is a deriviation of unittest.TestCase I found information in Parameterized of usage that said:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;parameterized&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parameterized&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nd"&gt;@parameterized.expand&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2 and 3&amp;quot;&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;3 and 5&amp;quot;&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&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;test_add&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;For other usages you may find Parameterized Projects in Github as a documentation.&lt;/p&gt;
&lt;h1&gt;What I've done with code:&lt;/h1&gt;
&lt;p&gt;In my case I've wanted to include parameters for gpx_file at setUp, but it was to hard and time-consuming to find out how to make it work.&lt;/p&gt;
&lt;p&gt;A semi solution I've found that is not pretty, but works is as presented below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GPXReaderTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Tests all GPXReader class cases for methods access.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="nd"&gt;@parameterized.expand&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bikingendorphines/example_data/15212277.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&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;test_get_points&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;gpx_file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if there will be data output from get_points.&lt;/span&gt;

&lt;span class="sd"&gt;        Test if:&lt;/span&gt;
&lt;span class="sd"&gt;        - points exists for different types.&lt;/span&gt;
&lt;span class="sd"&gt;        - what will happen if types exists, but no data?&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPXReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpx_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;points&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;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpxreader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_points&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertGreater&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Why this code is not pretty??&lt;/h1&gt;
&lt;p&gt;Well, you find yourself in situation, when for each test you will have to add information about &lt;em&gt;GPXReader&lt;/em&gt;. Using &lt;em&gt;setUp&lt;/em&gt; with this field would make creating code a little bit easier to maintain and read.&lt;/p&gt;
&lt;p&gt;I'll probably go back to this code and use the cleaner &lt;a href="https://docs.pytest.org/en/latest/fixture.html"&gt;pytest base &lt;/a&gt; which may clear this small issue.&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/9ec07b062b1c3463f951fda0d1e228c6d0282bd6"&gt;Adds mocking of gpx file using parameterized.&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;VIM + Plugins (&lt;a href="https://github.com/tpope/vim-fugitive"&gt;Fugitive&lt;/a&gt;, &lt;a href="https://github.com/plasticboy/vim-markdown"&gt;Vim-Markdown&lt;/a&gt; and &lt;a href="https://github.com/benmills/vimux"&gt;Vimux&lt;/a&gt; )&lt;/li&gt;
&lt;li&gt;Pelican&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. Pick tools for what they are intented for.&lt;/h3&gt;
&lt;p&gt;I've forgot that default django.TestCase are for testing Django-framework itself behaviours like ORM inside of django and other.&lt;/p&gt;
&lt;p&gt;They are not ideal for unit-testing and for that you should use something different.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;For unit-testing better to use one of those :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/2/library/unittest.html"&gt;unittest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.pytest.org/en/latest/contents.html"&gt;pytest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/1676269/writing-a-re-usable-parametrized-unittest-testcase-method"&gt;Writing a re-usable (parametrized) unittest.TestCase method&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://eli.thegreenplace.net/2011/08/02/python-unit-testing-parametrized-test-cases"&gt;Python unit testing: parametrized test cases&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://gavin.brokentrain.net/projects/vimtips/vimtips.pdf"&gt;VimTips&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/wolever/parameterized"&gt;Parameterized library&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Change behaviour of GPXReaderTestCase to more pytest alike and add some more test code&lt;/h4&gt;
&lt;h4&gt;2. Push finally first version of GPX Reader to master via pull-request.&lt;/h4&gt;
&lt;h4&gt;3. Check &lt;a href="https://github.com/anselmos/biking-endorphines/issues"&gt;Issues&lt;/a&gt; of this project.&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="django.testcase"></category><category term="parameterized"></category><category term="pytest"></category><category term="unittest"></category><category term="vim"></category><category term="vim-plugins"></category></entry><entry><title>Pelican Blog with Pelican-Bootstrap3 theme</title><link href="http://witkowskibartosz.com/blog/pelican-blog-with-pelican-bootstrap3-theme.html" rel="alternate"></link><published>2017-03-29T21:30:00+02:00</published><updated>2017-03-29T21:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-29:/blog/pelican-blog-with-pelican-bootstrap3-theme.html</id><summary type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;As I've informed you at post &lt;a href="pelican-blog-with-fabric-and-ftp-deployment-part2-on-2"&gt;Pelican blog with Fabric and FTP deployment part 2/2&lt;/a&gt; I've started working on &lt;a href="https://github.com/getpelican/pelican-themes/tree/master/pelican-bootstrap3"&gt;Pelican Bootstrap3 Theme&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;it's a MIT licensed theme that supports categories, github project's information, social information and few others that I'm currently not interested in.&lt;/p&gt;
&lt;h1&gt;How to use pelican-bootstrap3 …&lt;/h1&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;As I've informed you at post &lt;a href="pelican-blog-with-fabric-and-ftp-deployment-part2-on-2"&gt;Pelican blog with Fabric and FTP deployment part 2/2&lt;/a&gt; I've started working on &lt;a href="https://github.com/getpelican/pelican-themes/tree/master/pelican-bootstrap3"&gt;Pelican Bootstrap3 Theme&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;it's a MIT licensed theme that supports categories, github project's information, social information and few others that I'm currently not interested in.&lt;/p&gt;
&lt;h1&gt;How to use pelican-bootstrap3 theme&lt;/h1&gt;
&lt;p&gt;To use this theme, first thing you need is to &lt;code&gt;git clone&lt;/code&gt; this repository:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git clone https://github.com/getpelican/pelican-themes/ themes
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then add information about path for your selected theme in &lt;code&gt;pelicanconf.py&lt;/code&gt; as presented below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;PLUGIN_PATHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;plugins&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;PLUGINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;i18n_subsites&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;THEME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;themes/pelican-bootstrap3&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;JINJA_ENVIRONMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;extensions&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;jinja2.ext.i18n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then please install i18n plugin from here, using below mini-script (unfortunatelly they all are in one repository, not as git sub-modules.)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git clone https://github.com/getpelican/pelican-plugins plugins
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You may want to remove all other plugins besides &lt;code&gt;i18n_subsites&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; plugins &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mv i18n_subsites ../ &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf . &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mv ../i18n_subsites .
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And it will start working.&lt;/p&gt;
&lt;h1&gt;What tips and tricks I've checked with this theme:&lt;/h1&gt;
&lt;h4&gt;1. Github Repositories.&lt;/h4&gt;
&lt;p&gt;Great idea that you can use your github account and just use without additional plugins gh-repos visible at right banner.&lt;/p&gt;
&lt;p&gt;You may want to trick it to only view your own &lt;code&gt;source&lt;/code&gt; projects with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;GITHUB_USER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;anselmos&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;GITHUB_SKIP_FORK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;2. About me banner information.&lt;/h4&gt;
&lt;p&gt;There is an information for something similar to About-Page, but available all-the-time in right-banner, it's "ABOUT_ME".&lt;/p&gt;
&lt;p&gt;Just add in your &lt;code&gt;pelicanconf.py&lt;/code&gt; variable &lt;code&gt;ABOUT_ME&lt;/code&gt; that will contain all information you want to say about yourself. This variable will also properly decode all html-type metadata.&lt;/p&gt;
&lt;h4&gt;3. Your code-blocks are customizable!!!&lt;/h4&gt;
&lt;p&gt;You can change your code-blocks style to different if you want. There are a lot of them because it's using Pygments.&lt;/p&gt;
&lt;p&gt;To check what type of Pygments style you can use, check &lt;a href="https://github.com/getpelican/pelican-themes/tree/master/pelican-bootstrap3#pygments"&gt;pelican-bootstrap3-theme-page&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;4. Many many other options&lt;/h4&gt;
&lt;p&gt;This options can be setup, by reading first information about theme that is available &lt;a href="https://github.com/getpelican/pelican-themes/tree/master/pelican-bootstrap3"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/anselmos_pelican_blog/pull/5/commits/51d9f33"&gt;Adds initial pelican-bootstrap3 theme with needed plugin&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/anselmos_pelican_blog/pull/5/commits/74dbda2"&gt;Adds few possible changes to pelican for theme&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/anselmos_pelican_blog/pull/5/commits/c5afe25"&gt;Adds possible Display Categories for site&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/vIM&lt;/li&gt;
&lt;li&gt;pelican&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h5&gt;1. I'll continue working on pelican-theme with using &lt;code&gt;fancybox&lt;/code&gt;&lt;/h5&gt;
&lt;h5&gt;2. See &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/issues"&gt;ISSUES&lt;/a&gt; task-list for this 'mini' growing project :)&lt;/h5&gt;</content><category term="anselmos-pelican-blog-source"></category><category term="pelican-bootstrap3"></category><category term="mini-project"></category><category term="theme"></category><category term="pelican"></category></entry><entry><title>GPX Initial Solution</title><link href="http://witkowskibartosz.com/blog/gpx-initial-solution.html" rel="alternate"></link><published>2017-03-26T22:30:00+02:00</published><updated>2017-03-26T22:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-26:/blog/gpx-initial-solution.html</id><summary type="html">&lt;h1&gt;Plan for this solution&lt;/h1&gt;
&lt;p&gt;This time I had a plan.&lt;/p&gt;
&lt;p&gt;The plan assumed that I'll create initial solution for GPX reading information.&lt;/p&gt;
&lt;p&gt;Reading basic information like points and just create initial test-cases for this.&lt;/p&gt;
&lt;p&gt;I've even created a sub-class of GPXReader for Endomondo Specific format data, but thus far endomondo's …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Plan for this solution&lt;/h1&gt;
&lt;p&gt;This time I had a plan.&lt;/p&gt;
&lt;p&gt;The plan assumed that I'll create initial solution for GPX reading information.&lt;/p&gt;
&lt;p&gt;Reading basic information like points and just create initial test-cases for this.&lt;/p&gt;
&lt;p&gt;I've even created a sub-class of GPXReader for Endomondo Specific format data, but thus far endomondo's format data is almost identical with my example data.&lt;/p&gt;
&lt;h1&gt;Initial Solution - ideas behind the curtain&lt;/h1&gt;
&lt;p&gt;Solution is simple - reading points from what-ever data is in gpx file i.e. &lt;em&gt;routepoints&lt;/em&gt;, &lt;em&gt;trackpoints&lt;/em&gt;, &lt;em&gt;waypoints&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Solution is far from perfect, but this time I made it in my timeframe I've given to myself - YEAH!!&lt;/p&gt;
&lt;p&gt;Check this source code which is the &lt;strong&gt;core&lt;/strong&gt; for gathering points: (for today - it may vary at the end)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_track_points&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;item_nb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Returns only first track points&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tracks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tracks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;item_nb&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;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tracks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item_nb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
                &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&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;points&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_route_points&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;item_nb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Returns route points&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__routes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__routes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;item_nb&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;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&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;points&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_way_points&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;item_nb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Returns way points&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__waypoints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__waypoints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;item_nb&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;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__waypoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&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;points&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_points&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;item_nb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Returns Points from either route/track or waypoints.&lt;/span&gt;
&lt;span class="sd"&gt;        If there is more then one type then uses Track&amp;#39;s as a default.&lt;/span&gt;

&lt;span class="sd"&gt;        Make assumption that there will be only one of each data_type&lt;/span&gt;
&lt;span class="sd"&gt;        i.e. only one track/route/waypoint.&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tracks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tracks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item_nb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_points_no&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_track_points&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__routes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__routes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item_nb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_points_no&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_route_points&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__waypoints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__waypoints&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item_nb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_points_no&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_way_points&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;Commits in PR for GPX Reader, and it will not yet be pulled.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pull/13/commits/816fad1"&gt;Adds initial Utils.pY&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pull/13/commits/61052c5"&gt;Adds more information on gpx reader at utils&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pull/13/commits/24c4b8e"&gt;Initial GPXReader with Test-Cases&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pull/13/commits/7996650"&gt;Adds fix for unused import of gpx&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;vIM&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;pylint/django tests&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;make&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Docker&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Github pull-request&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. I've created test-cases before checking if code even works :)&lt;/h3&gt;
&lt;p&gt;You may find yourself creating tests for code, before you even run it manually,  as I did.&lt;/p&gt;
&lt;p&gt;Then unfortunatelly debugging inside of test-cases is not ideal.&lt;/p&gt;
&lt;p&gt;For now with limited time, I didn't find solution that could use django tests with code and debugging code within tests.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;First test if your solution works - manually, then create test-case. When creating test-case source-code may or may not be changed, but you can check it with your manual testbed.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://cycleseven.org/gps-waypoints-routes-and-tracks-the-difference"&gt;GPS Waypoints, Routes, and Tracks – the difference&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pull/13"&gt;Pull Request I've created today for GPX Reader&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. I'll continue working on GPX Reader to improve code for better maintainance and test-coverage.&lt;/h4&gt;
&lt;h4&gt;2. Probably move again to travis builds to make pyreverse builds per commit visible at github gh-pages &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/12"&gt;#12&lt;/a&gt;.&lt;/h4&gt;
&lt;h4&gt;3. As always - check my &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues"&gt;Issues for the project&lt;/a&gt;&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="gpxpy"></category><category term="gps"></category><category term="coordinates"></category></entry><entry><title>GPX File Reader</title><link href="http://witkowskibartosz.com/blog/gpx-file-reader.html" rel="alternate"></link><published>2017-03-26T10:30:00+02:00</published><updated>2017-03-26T10:30:00+02:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-26:/blog/gpx-file-reader.html</id><summary type="html">&lt;h1&gt;GPX File Reader - initial requirements.&lt;/h1&gt;
&lt;p&gt;Yeah so as I've announced at &lt;a href="github-pages-and-travis-auto-deployment"&gt;Github Pages and Travis auto Deployment&lt;/a&gt;, I'm starting work on GPX File reader.&lt;/p&gt;
&lt;p&gt;Let's first create a requirements on this task.&lt;/p&gt;
&lt;p&gt;What's our assumptions ?&lt;/p&gt;
&lt;h4&gt;1. We will not invent wheel again&lt;/h4&gt;
&lt;p&gt;I'm not going to create another library that …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;GPX File Reader - initial requirements.&lt;/h1&gt;
&lt;p&gt;Yeah so as I've announced at &lt;a href="github-pages-and-travis-auto-deployment"&gt;Github Pages and Travis auto Deployment&lt;/a&gt;, I'm starting work on GPX File reader.&lt;/p&gt;
&lt;p&gt;Let's first create a requirements on this task.&lt;/p&gt;
&lt;p&gt;What's our assumptions ?&lt;/p&gt;
&lt;h4&gt;1. We will not invent wheel again&lt;/h4&gt;
&lt;p&gt;I'm not going to create another library that handles reading gpx files them-selves, since It's not the main activity for the project.&lt;/p&gt;
&lt;p&gt;I'll focus on reading information that maybe of great interest for this particular project.&lt;/p&gt;
&lt;h4&gt;2. GPX Reader will support different gpx-formats&lt;/h4&gt;
&lt;p&gt;Reader will need to support different type of gpx-file formats. Starting from &lt;a href="https://www.endomondo.com/"&gt;Endomondo&lt;/a&gt;/&lt;a href="https://www.strava.com/"&gt;Strava&lt;/a&gt;/ and &lt;a href="http://alternativeto.net/software/endomondo/"&gt;alternatives-to-endomondo&lt;/a&gt; stopping at (if needed) my own gpx-format created by Android-sub project.&lt;/p&gt;
&lt;p&gt;I do hope, that library it-self will support it, but taking into account that gpx files are just an xml files, I have high-hopes.&lt;/p&gt;
&lt;h4&gt;3. GPX Reader needs to be extensible via plugins-engine&lt;/h4&gt;
&lt;p&gt;Project assumes that this reader will not be "universal", and being so- I'll maybe need to use it someday (even in different type of project) and then I'll just create a plugin to already working solution.&lt;/p&gt;
&lt;p&gt;Besides I haven't yet done something like plugin-engine extensions - and it looks like something very interesting.&lt;/p&gt;
&lt;h4&gt;4. What data this project needs ?&lt;/h4&gt;
&lt;p&gt;For this project I'll read information like gpx locations, timings between each location, routes as a bunch of locations. That data will be very important and can be used for statistics analysis and - story-telling - for gathering endorphine-badges.&lt;/p&gt;
&lt;h1&gt;What are the engines to read gpx files?&lt;/h1&gt;
&lt;h4&gt;1. Manual reading information from xml&lt;/h4&gt;
&lt;p&gt;GPX files in it's core are just xml files, hence you can read them as usual xml files.&lt;/p&gt;
&lt;p&gt;Check this libraries that handles xml read:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/2/library/xml.etree.elementtree.html#module-xml.etree.ElementTree"&gt;XML-eltree&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://lxml.de/"&gt;LXML&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.crummy.com/software/BeautifulSoup/"&gt;BeautifulSoup&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://pypi.python.org/pypi/xmltodict"&gt;xmltodict&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;and many other similar xml-reading libraries.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But BE-AWARE! - this maybe harmfull to your neuronic-system and cause some neurotic issues :) since you'll need to scrap all valid information i.e. like all coordinates for route by yourself manually with just xml library.&lt;/p&gt;
&lt;h4&gt;2. GPXPY library&lt;/h4&gt;
&lt;p&gt;Some of the features ( i.e. gathering routes not by using XPATH search )that this particular library contains, makes it almost perfect match for this particular job.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/tkrajina/gpxpy"&gt;GPXPY&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So I'll stick to it. As I do recall properly I've been using this library for tests in my previous &lt;a href="github.com/anselmos/bikingstats"&gt;'abandoned' project&lt;/a&gt; - the &lt;a href="https://github.com/anselmos/bikingstats/blob/test_gpx/workouts/testgpx.py"&gt;test file&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Prerequisites - How to use GPXPY ?&lt;/h1&gt;
&lt;h4&gt;1. Installation of gpxpy&lt;/h4&gt;
&lt;p&gt;First of all you need to install python library:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install gpxpy
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then &lt;a href="https://www.youtube.com/watch?v=9dcVOmEQzKA"&gt;JUST USE IT &lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Oups sorry, I've meant &lt;a href="https://nbviewer.ipython.org/url/ocefpaf.github.com/python4oceanographers/downloads/notebooks/2014-08-18-gpx.ipynb"&gt;this link - with example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;as a Filipe Fernandes uses it.&lt;/p&gt;
&lt;h4&gt;2. Find gpx file examples to work with - or train with endomondo and create your-own.&lt;/h4&gt;
&lt;p&gt;I've searched web and finally I've found nice site that gives some gpx files with routes other users went that you also could upload to your Endomondo/Strava application and "go with this route".&lt;/p&gt;
&lt;p&gt;Using &lt;a href="https://ridewithgps.com/routes/15212277.gpx"&gt;this GPX file&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;3. Example code to check functionality of gpxpy.&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gpxpy&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gpxpy.gpx&lt;/span&gt;
&lt;span class="n"&gt;gpx_file&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="s1"&gt;&amp;#39;15212277.gpx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# Parsing an existing file:&lt;/span&gt;
&lt;span class="c1"&gt;# -------------------------&lt;/span&gt;

&lt;span class="n"&gt;gpx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gpxpy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpx_file&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;track&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;gpx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracks&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;segment&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;segments&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;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;segment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Point at ({0},{1}) -&amp;gt; {2}&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;elevation&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;waypoint&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;gpx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waypoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;waypoint {0} -&amp;gt; ({1},{2})&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;waypoint&lt;/span&gt;&lt;span class="o"&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;waypoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;waypoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;longitude&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;route&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;gpx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Route:&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Point at ({0},{1}) -&amp;gt; {2}&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;elevation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# gpx_parsed = gpxpy.parse(open(gpx_file)) # This will fail with error of coercing which means that you already have file opened for reading and trying to open it again, those failing.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;a href="examples/gpxpy/gpxpy_example.py"&gt;Source-Code.Py&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="examples/gpxpy/15212277.gpx"&gt;GPX-example-file&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;4. Where to put your business logic code for importing data from gpx files at Django Framework?&lt;/h4&gt;
&lt;p&gt;That was the hardest question I could not find clear answer - Then I've finally found out why - there is no good &lt;a href="https://www.youtube.com/watch?v=_Ut8HupAxVY"&gt;"answer for all business logics"&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It all depends on what your business logic will do. If it has any type of connections with Model and will reuse of model-api than you should put your business logic there. The same applies to Views.&lt;/p&gt;
&lt;p&gt;The only &lt;strong&gt;Rule of Thumb&lt;/strong&gt; you should follow is not to overload model/view or controller.&lt;/p&gt;
&lt;p&gt;Since our importing methods will only read data from gpx files, I've decided to move to &lt;code&gt;utils.py&lt;/code&gt; file as suggested &lt;a href="http://stackoverflow.com/questions/21378653/business-logic-in-django"&gt;here -&amp;gt; business-logic-in-django-at-stackoverflow&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Geo-Location and other possibilities out-there.&lt;/h1&gt;
&lt;p&gt;While investigating python gpx libraries I've found library that I might use for GeoCoding.&lt;/p&gt;
&lt;p&gt;It's a &lt;a href="https://github.com/geopy/geopy"&gt;GeoPy&lt;/a&gt; - &lt;code&gt;a Geocoding Library for Python&lt;/code&gt; - quoting authors.&lt;/p&gt;
&lt;p&gt;I've also found that there is an Geo-framework for Django called &lt;a href="https://docs.djangoproject.com/en/1.10/ref/contrib/gis/"&gt;GeoDjango&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;Unfortunatelly None. I didn't have proper time to sit and code with gpxpy.
That's why I introduce &lt;em&gt;"Things I've found worth looking into"&lt;/em&gt; :)&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/Vim&lt;/li&gt;
&lt;li&gt;VimFX plugin for firefox&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Things I've found worth looking into.&lt;/h1&gt;
&lt;h3&gt;1. PyTrainer&lt;/h3&gt;
&lt;p&gt;Wow I've just found some interesting project called &lt;a href="https://github.com/pytrainer/pytrainer"&gt;PyTrainer&lt;/a&gt; - quoting official github repo info: &lt;code&gt;Pytrainer is a tool to log all your sport excursion coming from GPS devices (with a focus on ForeRunner) or GPX (http://www.topografix.com) files. Pytrainer supports GPS track files and displays it in graphs, maps...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So that's definatelly something to look deeply into someday :)&lt;/p&gt;
&lt;h3&gt;2. IPython Notebook Viewer.&lt;/h3&gt;
&lt;p&gt;I've known about this "jupyter" python thing for awhile, but I've forgot about it, and &lt;a href="http://ocefpaf.github.io/homepage/"&gt;Filipe Fernandes&lt;/a&gt; helped me to remind myself about this cool feature! &lt;/p&gt;
&lt;h4&gt;BTW I think you should definitely check his blog.&lt;/h4&gt;
&lt;h3&gt;3. IPython Notebook are available at github natively.&lt;/h3&gt;
&lt;p&gt;Basically you can since December 2015 use IPython Notebooks with native github UI, that will render your ipybn files.&lt;/p&gt;
&lt;p&gt;Check this &lt;a href="https://github.com/benlaken/Comment_BadruddinAslam2014/blob/master/Monsoon_analysis.ipynb"&gt;cool stuff about Monsoon and cosmic-ray&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. Trying to read gpx files twice will fail with coercing issue.&lt;/h3&gt;
&lt;p&gt;As I've described it in a sample file with comment, if you try to do something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;file_to_open&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="s2"&gt;&amp;quot;file.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# bla bla bla you do something with it&lt;/span&gt;

&lt;span class="c1"&gt;# and then again:&lt;/span&gt;

&lt;span class="n"&gt;reading_file&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="n"&gt;file_to_open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;But this time it will not be the same "coercing" issue error in traceback, but still it's the same principle of reusing an open'ed connector to file, to reopen file with it.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;Find line in which you have the failure and change it to this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;file_to_open&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="s2"&gt;&amp;quot;file.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# bla bla bla you do something with it&lt;/span&gt;

&lt;span class="c1"&gt;# and then again:&lt;/span&gt;

&lt;span class="n"&gt;reading_file&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="s2"&gt;&amp;quot;file.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;2. Did not make my commitments&lt;/h3&gt;
&lt;p&gt;Why I've failed to accomplish creating code ? Well... I'm in a learning curve on working alone in project and still failing at planning part.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;Start new post-blogs with plan and then stick with it.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/1912434/how-do-i-parse-xml-in-python"&gt;How do I parse xml in python at stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pytrainer/pytrainer"&gt;Pytrainer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://andykee.com/visualizing-strava-tracks-with-python.html"&gt;Visualizing Strava Tracks with python&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/vimfx/"&gt;VimFX - vim plugin for firefox&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Implementation of GPX Reader with plugin-engine.&lt;/h4&gt;
&lt;h4&gt;2. Check my &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues"&gt;Issue list&lt;/a&gt; for Biking Endorphines project.&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="gpxpy"></category><category term="gps"></category><category term="coordinates"></category><category term="xml"></category><category term="geopy"></category><category term="vimfx"></category></entry><entry><title>Pelican blog with Fabric and FTP deployment part 2/2</title><link href="http://witkowskibartosz.com/blog/pelican-blog-with-fabric-and-ftp-deployment-part2-on-2.html" rel="alternate"></link><published>2017-03-22T19:30:00+01:00</published><updated>2017-03-22T19:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-22:/blog/pelican-blog-with-fabric-and-ftp-deployment-part2-on-2.html</id><summary type="html">&lt;h1&gt;FTP Deployment using ftputil for Pelican Blog.&lt;/h1&gt;
&lt;p&gt;Process of creating Fabric Deployment with FTP included:&lt;/p&gt;
&lt;h5&gt;1. Using Quickstarter for creating default pelican blog example.&lt;/h5&gt;
&lt;h5&gt;2. Setting-up FTP Server for testing.&lt;/h5&gt;
&lt;h5&gt;3. Adding ftp_upload task at Fabric default fabfile.py.&lt;/h5&gt;
&lt;h5&gt;4. Exploring and development of ftp_upload task using &lt;a href="http://ftputil.sschwarzer.net/trac"&gt;ftputil&lt;/a&gt; and &lt;a href="https://docs.python.org/2/library/netrc.html"&gt;netrc …&lt;/a&gt;&lt;/h5&gt;</summary><content type="html">&lt;h1&gt;FTP Deployment using ftputil for Pelican Blog.&lt;/h1&gt;
&lt;p&gt;Process of creating Fabric Deployment with FTP included:&lt;/p&gt;
&lt;h5&gt;1. Using Quickstarter for creating default pelican blog example.&lt;/h5&gt;
&lt;h5&gt;2. Setting-up FTP Server for testing.&lt;/h5&gt;
&lt;h5&gt;3. Adding ftp_upload task at Fabric default fabfile.py.&lt;/h5&gt;
&lt;h5&gt;4. Exploring and development of ftp_upload task using &lt;a href="http://ftputil.sschwarzer.net/trac"&gt;ftputil&lt;/a&gt; and &lt;a href="https://docs.python.org/2/library/netrc.html"&gt;netrc&lt;/a&gt; as I've briefly predicted in &lt;a href="pelican-blog-with-fabric-and-ftp-deployment-part1-on-2"&gt;post on 'Pelican blog with Fabric and FTP part1'&lt;/a&gt;&lt;/h5&gt;
&lt;h1&gt;Development of FTP Fabric deployment&lt;/h1&gt;
&lt;p&gt;I've firstly tried to fight-out problem with ftp-server, but hence time limits, I had to bury investigating ftp-server itself (which meant to be a testbed only, not actual post).&lt;/p&gt;
&lt;p&gt;Finally when I've found solution, I've researched how other's solutions looks like, but non of them were satisfying my needs - &lt;a href="http://stackoverflow.com/questions/5663787/upload-folders-from-local-system-to-ftp-using-python-script"&gt;check stackoverflow link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I almost copy-pasted last solution, but made my tweaks to it that actually extends this with not only source but also target directory.&lt;/p&gt;
&lt;p&gt;Finally solution looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ftp_upload&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;netrc_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;netrc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;netrc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;netrc_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;authenticator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;netrc_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authenticators&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ftp_host&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;upload_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;ftp_host&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&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;dir_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dir_fiels&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

            &lt;span class="n"&gt;local&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;curdir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;local_strip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;local_for_remote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local_strip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&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;ftp_host&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;local_for_remote&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;ftp_host&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;local_for_remote&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;file_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_strip&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;source_upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file_&lt;/span&gt;
                &lt;span class="n"&gt;target_upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;local_for_remote&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file_&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_upload&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;uploads {},  {}&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_upload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_upload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="n"&gt;ftp_host&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_upload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_upload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;ftputil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FTPHost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ftp_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authenticator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;authenticator&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="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ftp_host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;upload_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deploy_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ftp_target_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This solution uses netrc file as you see at the second line.&lt;/p&gt;
&lt;p&gt;An example of netrc file that KEEP-IN-MIND needs to have a &lt;code&gt;chmod 0600 .netrc&lt;/code&gt; mode, looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;machine ftp.freebsd.org
    login anonymous
    password edwin@mavetju.org
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You may use this solution with fabric as described below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;fab --set &lt;span class="nv"&gt;ftp_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;IP_ADDRESS_OR_DNS_NAME_OF_FTP,ftp_target_dir&lt;span class="o"&gt;=&lt;/span&gt;/DIRECTORY_AT_FTP_SERVER_TO_WHICH_FILES_WILL_BE_UPLOADED/,netrc_file&lt;span class="o"&gt;=&lt;/span&gt;/YOUR_ABSOLUTE_PATH_LOCAL_NETRC_FILE ftp_upload
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;i.e.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;fab --set &lt;span class="nv"&gt;ftp_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.1,ftp_target_dir&lt;span class="o"&gt;=&lt;/span&gt;/var/www/,netrc_file&lt;span class="o"&gt;=&lt;/span&gt;/root/.netrc ftp_upload
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/anselmos_pelican_blog/commit/3c26f71"&gt;Adds simplest version of fab-ftp using lftp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/anselmos_pelican_blog/commit/d638453"&gt;Adds ftp_upload task&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Docker (for ftp-server and for pelican-deployment tests)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vi/VIM as my main editor&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tmux &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. Using docker and ftp service introduce networking problem.&lt;/h3&gt;
&lt;p&gt;Using ftp service called "pureftpd" as docker container was not a perfect solution as I've found out in a painfull manner.&lt;/p&gt;
&lt;p&gt;I've tried to test my &lt;code&gt;ftp_upload&lt;/code&gt; fabric task, but I could not even connect with simple ftp on second docker image nor via host itself.&lt;/p&gt;
&lt;p&gt;I've stumbled upon error: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="m"&gt;500&lt;/span&gt; I won&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;t open a connection to &lt;span class="m"&gt;172&lt;/span&gt;.17.0.155 &lt;span class="o"&gt;(&lt;/span&gt;only to &lt;span class="m"&gt;172&lt;/span&gt;.17.42.1&lt;span class="o"&gt;)&lt;/span&gt;
ftp: bind: Address already in use
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;I needed to change network settings of docker container to share all network with host - with adding at &lt;code&gt;docker run&lt;/code&gt; parameter &lt;code&gt;--net=host&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;2. Using pureftpd as testing ftp-service introduce too-much-connections-per-user error.&lt;/h3&gt;
&lt;p&gt;I was testing putting files to ftp-server, and I could not use ftputil nor lftp command to put files.
I could only use simplest ftp command to put files to server.&lt;/p&gt;
&lt;p&gt;Error I've got:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Traceback &lt;span class="o"&gt;(&lt;/span&gt;most recent call last&lt;span class="o"&gt;)&lt;/span&gt;:
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/fabric/main.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;756&lt;/span&gt;, in main
        *args, **kwargs
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/fabric/tasks.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;426&lt;/span&gt;, in execute
        results&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;lt;local-only&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; task.run&lt;span class="o"&gt;(&lt;/span&gt;*args, **new_kwargs&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/fabric/tasks.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;173&lt;/span&gt;, in run
        &lt;span class="k"&gt;return&lt;/span&gt; self.wrapped&lt;span class="o"&gt;(&lt;/span&gt;*args, **kwargs&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/app/fabfile.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;120&lt;/span&gt;, in ftp_upload
        upload_dir&lt;span class="o"&gt;(&lt;/span&gt;env.deploy_path, env.ftp_target_dir&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/app/fabfile.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;117&lt;/span&gt;, in upload_dir
        ftp_host.upload&lt;span class="o"&gt;(&lt;/span&gt;source_upload, target_upload&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/ftputil/host.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;475&lt;/span&gt;, in upload
        &lt;span class="nv"&gt;conditional&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;False, &lt;span class="nv"&gt;callback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;callback&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/ftputil/file_transfer.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;184&lt;/span&gt;, in copy_file
        &lt;span class="nv"&gt;target_fobj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; target_file.fobj&lt;span class="o"&gt;()&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/ftputil/file_transfer.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;94&lt;/span&gt;, in fobj
        &lt;span class="k"&gt;return&lt;/span&gt; self._host.open&lt;span class="o"&gt;(&lt;/span&gt;self.name, self.mode&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/ftputil/host.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;205&lt;/span&gt;, in open
        &lt;span class="nv"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self._copy&lt;span class="o"&gt;()&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/ftputil/host.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;144&lt;/span&gt;, in _copy
        &lt;span class="k"&gt;return&lt;/span&gt; self.__class__&lt;span class="o"&gt;(&lt;/span&gt;*self._args, **self._kwargs&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/ftputil/host.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;71&lt;/span&gt;, in __init__
        self._session &lt;span class="o"&gt;=&lt;/span&gt; self._make_session&lt;span class="o"&gt;()&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/ftputil/host.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;131&lt;/span&gt;, in _make_session
        &lt;span class="nv"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; factory&lt;span class="o"&gt;(&lt;/span&gt;*args, **kwargs&lt;span class="o"&gt;)&lt;/span&gt;
    File &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.7/dist-packages/ftputil/error.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;134&lt;/span&gt;, in __exit__
        raise TemporaryError&lt;span class="o"&gt;(&lt;/span&gt;*exc_value.args, &lt;span class="nv"&gt;original_exception&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exc_value&lt;span class="o"&gt;)&lt;/span&gt;
ftputil.error.TemporaryError: &lt;span class="m"&gt;421&lt;/span&gt; I can&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;t accept more than &lt;span class="m"&gt;1&lt;/span&gt; connections as the same user
Debugging info: ftputil &lt;span class="m"&gt;3&lt;/span&gt;.3.1, Python &lt;span class="m"&gt;2&lt;/span&gt;.7.6 &lt;span class="o"&gt;(&lt;/span&gt;linux2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;I tried to change configuration, set PerUserLimit's and other, but it didn't work.&lt;/p&gt;
&lt;p&gt;Finally in my desperation and a little bit too much time spend on tracking this issue then actual development I've dropped this thing for now and changed ftp server to much less "secure" - to proftpd with predefined docker image on x64 bit - called &lt;a href="https://github.com/hauptmedia/docker-proftpd"&gt;hauptmedia/proftpd&lt;/a&gt;  - I recommend you to check his github account projects :). &lt;/p&gt;
&lt;p&gt;This container works properly and for now is my testbed.&lt;/p&gt;
&lt;p&gt;When I've got more time I'll investigate problem with pureftpd and it's "security-by-obscurity" so-to-speak problem.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://ftputil.sschwarzer.net/trac/wiki/Documentation"&gt;FTPUtil Documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.activestate.com/recipes/576777-simple-ftp-mirror/"&gt;Simple FTP Mirror - By Thimo Kraemer&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h5&gt;1. Using pelican-bootstrap3 theme (or other), extend possibilities with adding &lt;code&gt;fancybox&lt;/code&gt; as image viewer.&lt;/h5&gt;
&lt;h5&gt;2. See &lt;a href="https://github.com/anselmos/anselmos_pelican_blog/issues"&gt;ISSSUES&lt;/a&gt; task-list for this 'mini' growing project :)&lt;/h5&gt;
&lt;p&gt;See you at next Wednesday :)&lt;/p&gt;</content><category term="anselmos-pelican-blog-source"></category><category term="fabric"></category><category term="ftp"></category><category term="deployment"></category><category term="mini-project"></category><category term="ftputil"></category><category term="netrc"></category></entry><entry><title>Github Pages and Travis auto Deployment</title><link href="http://witkowskibartosz.com/blog/github-pages-and-travis-auto-deployment.html" rel="alternate"></link><published>2017-03-19T18:30:00+01:00</published><updated>2017-03-19T18:30:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-19:/blog/github-pages-and-travis-auto-deployment.html</id><summary type="html">&lt;h1&gt;Auto Deployment of Pyreverse output to Github Pages!&lt;/h1&gt;
&lt;p&gt;That's our today's goal - to achieve it there is a lot of middle steps to take-over.&lt;/p&gt;
&lt;p&gt;I've found a best tutorial I could - &lt;a href="http://www.steveklabnik.com/automatically_update_github_pages_with_travis_example/"&gt;Automatically Update Github Pages with Travis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I've follow it with successful auto-updating github page.&lt;/p&gt;
&lt;p&gt;Ofcourse I've tweaked it to …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Auto Deployment of Pyreverse output to Github Pages!&lt;/h1&gt;
&lt;p&gt;That's our today's goal - to achieve it there is a lot of middle steps to take-over.&lt;/p&gt;
&lt;p&gt;I've found a best tutorial I could - &lt;a href="http://www.steveklabnik.com/automatically_update_github_pages_with_travis_example/"&gt;Automatically Update Github Pages with Travis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I've follow it with successful auto-updating github page.&lt;/p&gt;
&lt;p&gt;Ofcourse I've tweaked it to my preferences and behaviour I wanted it to be doing - generate pyreverse and push it to gh-pages.&lt;/p&gt;
&lt;h1&gt;Prerequisites&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://help.github.com/articles/what-is-github-pages/"&gt;Github Pages&lt;/a&gt; is a Github place for keeping project's documentation . It's supports Jekyll (Ruby-Based) static page generator - in addition to regular HTML content.&lt;/p&gt;
&lt;p&gt;Pyreverse will generate png files with class-structure and package-structure(lined), we will add this to gh-pages of our project as a Jekyll markdown md file.&lt;/p&gt;
&lt;h1&gt;How to setup your own auto-generator.&lt;/h1&gt;
&lt;p&gt;Following steps are almost identical with those presented in tutorial at the beginning of the post.&lt;/p&gt;
&lt;h4&gt;1. You need to configure source of gh-pages for your github repository&lt;/h4&gt;
&lt;p&gt;That can be done within "Github Pages" section of repository settings. Template to link with settings is below:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://github.com/{NAME_OF_USER}/{NAME_OF_REPOSITORY}/settings/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There at the &lt;code&gt;Source&lt;/code&gt; you have drop-down list from which you can select your branch.&lt;/p&gt;
&lt;h5&gt;Be-aware - &lt;code&gt;gh-pages&lt;/code&gt; branch is not created by default, by default &lt;code&gt;master&lt;/code&gt; branch is used. You will need to create it manually as I did.&lt;/h5&gt;
&lt;h4&gt;2. Create Github Token for travis to use it.&lt;/h4&gt;
&lt;p&gt;Generate token at &lt;a href="https://github.com/settings/tokens/new"&gt;THIS PAGE&lt;/a&gt; - You will need to re-authorize yourself again for this page.&lt;/p&gt;
&lt;p&gt;You add name of your token and set scope for the token - I've used only for REPO - to not overuse this token in other situations, and be sure that only repositories can be harmed if it will be compromized.&lt;/p&gt;
&lt;h5&gt;Save your generated token - it will only be visible NOW&lt;/h5&gt;
&lt;h4&gt;3. Setting up Travis&lt;/h4&gt;
&lt;p&gt;Once you've saved your token, you'll need it to generate secure-token for your &lt;code&gt;.travis.yml&lt;/code&gt; configuration file.&lt;/p&gt;
&lt;p&gt;For this part I needed to use ruby-based docker image - but this time taking into account time-pressure, I've used x64 bit for spending less time (not that I didn't tried first building x32 image for ruby ... but that's for another post).&lt;/p&gt;
&lt;p&gt;Ruby image with docker has a &lt;code&gt;gem&lt;/code&gt; installer that will help us install &lt;code&gt;travis&lt;/code&gt; commandliner that we need to create secure tokens.&lt;/p&gt;
&lt;p&gt;In image (or if you have already installled ruby with gem) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;gem install travis
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That's it - super easy. Now use travis command - best to use in your project source-code that have already .travis.yml file - cause it will change the file adding secure-token to it automatically:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt; travis encrypt -r username/reponame &lt;span class="nv"&gt;GH_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;the token you created before&lt;span class="o"&gt;]&lt;/span&gt; --add
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;4. Now let's make a bash script that will generate and deploy to gh-pages.&lt;/h4&gt;
&lt;p&gt;Here I've more-then-less used code presented in tutorial at beginning of post. Here is how it looks like now:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;rev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;git rev-parse --short HEAD&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$TRAVIS_BRANCH&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;master&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;This commit was made against the &lt;/span&gt;&lt;span class="nv"&gt;$TRAVIS_BRANCH&lt;/span&gt;&lt;span class="s2"&gt; and not the master! No deploy!&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

mkdir -p deployed_gh_pages/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rev&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; deployed_gh_pages/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rev&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

git init
git config user.name &lt;span class="s2"&gt;&amp;quot;Anselmos&amp;quot;&lt;/span&gt;
git config user.email &lt;span class="s2"&gt;&amp;quot;Github.com/Anselmos&amp;quot;&lt;/span&gt;

git remote add upstream &lt;span class="s2"&gt;&amp;quot;https://&lt;/span&gt;&lt;span class="nv"&gt;$GH_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;@github.com/anselmos/Biking-Endorphines.git&amp;quot;&lt;/span&gt;
git fetch upstream
git reset upstream/gh-pages

cp ../../generated_pyreverse/* .  &lt;span class="c1"&gt;# you put here your files from whatever place you generated before this script&lt;/span&gt;

git add -A . &lt;span class="c1"&gt;# this will add all your files to staging mode&lt;/span&gt;
git commit -m &lt;span class="s2"&gt;&amp;quot;rebuild pages at &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rev&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;  &lt;span class="c1"&gt;# this will commit all the files put in stage mode with information about commit-id - That&amp;#39;s what I also wanted :) - you can track which commit made pyreverse&lt;/span&gt;
git push -q upstream HEAD:gh-pages  &lt;span class="c1"&gt;# push to github gh-pages branch.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Final results:&lt;/h1&gt;
&lt;p&gt;Each time new push to master will be done, travis will not only check as usually pylint/unit-test, but also will create pyrevesed output that is automatically moved to gh-page seen here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://anselmos.github.io/Biking-Endorphines/pyreverse.html"&gt;Pyreverse Generated GH Page per each master push&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A lot of try-error commits :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/5ed29e2"&gt;Adds shebang to deploy_gh_pages.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/09f07cb"&gt;Adds check if travis build is from master branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/0a7a384"&gt;Fix typo on generated dir name&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/efd88f1"&gt;Adds deploy and generation pyreverse script&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/2dc370b"&gt;Adds graphviz sys-lib to travis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/31afdf2"&gt;Adds gh-page task to travis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/6904519"&gt;Adds safelist of branches to travis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/64d990d"&gt;Remove task from .travis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/3aba19f"&gt;Adds initial test for pyreverse on travis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;My first Github Pull Request that I'm proud of :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/pull/11"&gt;Pyreverse to gh pages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;vi/vim&lt;/li&gt;
&lt;li&gt;ruby gem installer&lt;/li&gt;
&lt;li&gt;travis commandliner&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;pyreverse&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. Using separated branch for testing on travis - goes with error.&lt;/h3&gt;
&lt;p&gt;At first travis used separated branch and worked properly. When I've setup Github Pages at projects account Travis probably found that project is using GH-Pages and stopped all tasks on this branch.&lt;/p&gt;
&lt;p&gt;When I've done second attempt to push to branch called &lt;code&gt;pyreverse-to-gh-pages&lt;/code&gt; it didn't even start.&lt;/p&gt;
&lt;p&gt;Then I was a little bit worried, what happen. I've started my research to find out why travis didn't even start to build the branch.&lt;/p&gt;
&lt;p&gt;On the "menu options" at travis-ci page I've found &lt;a href="https://travis-ci.org/anselmos/Biking-Endorphines/requests"&gt;"requests"&lt;/a&gt; page where I could see if request to start job on travis is actually working.&lt;/p&gt;
&lt;p&gt;There I've found this beautiful error that at first glance meant nothing to me:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Github Pages branch not included via configuration&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then I've started to check if there is any type of error in my .travis.yml file as it was before by trying to add secure-tokens. But no luck with that.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;I've finally found out that Travis will revoke any branches that contains "gh-pages" name by default(at least that's my thinking about it). Check information here &lt;a href="https://docs.travis-ci.com/user/customizing-the-build/#Safelisting-or-blocklisting-branches"&gt;Safelisting or blocklisting branches&lt;/a&gt; - to overcome this issue I've changed &lt;code&gt;.travis.yml&lt;/code&gt; settings and add following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ss"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="ss"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;gh&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pages&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="sr"&gt;/.*/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That seem to made a trick.&lt;/p&gt;
&lt;h3&gt;2. Forgot about dependencies used when pyreverse generates outputs.&lt;/h3&gt;
&lt;p&gt;Pyreverse for proper usage needs "Graphviz" installed at system level. Since it's a system dependency, it's not included at requirements.txt level.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;Add installation of Graphviz at travis configuration.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/domenic/ec8b0fc8ab45f39403dd"&gt;Auto-deploying built products to gh-pages with Travis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.teamtreehouse.com/using-github-pages-to-host-your-website"&gt;Using Github Pages to host your website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.steveklabnik.com/automatically_update_github_pages_with_travis_example/"&gt;Update Github Pages with Travis tutorial&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. I'll finally start coding on GPX File reader - see at &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues/7"&gt;Issue #7&lt;/a&gt;&lt;/h4&gt;
&lt;h4&gt;2. Check my &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues"&gt;TODO-LIST/Issues at Github&lt;/a&gt;&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="github-pages"></category><category term="travis-ci"></category><category term="pyreverse"></category></entry><entry><title>Modelling tools for software - Pyreverse for Biking Endorphines</title><link href="http://witkowskibartosz.com/blog/modelling-tools-for-software-pyreverse-for-bikingendorpines.html" rel="alternate"></link><published>2017-03-18T00:00:00+01:00</published><updated>2017-03-18T00:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-18:/blog/modelling-tools-for-software-pyreverse-for-bikingendorpines.html</id><summary type="html">&lt;h1&gt;Modelling tools and their capabilities&lt;/h1&gt;
&lt;p&gt;Why would you even bother using modelling tools and technologies? :&lt;/p&gt;
&lt;h4&gt;1. Using modelling tools keeps track of how your classes/flow/environment will look like and how they will work with each-other.&lt;/h4&gt;
&lt;p&gt;Check information from University of Cambridge about &lt;a href="https://www.cl.cam.ac.uk/teaching/1112/SWDesign/materials.html"&gt;Software Design - course materials.&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;2. Designing …&lt;/h4&gt;</summary><content type="html">&lt;h1&gt;Modelling tools and their capabilities&lt;/h1&gt;
&lt;p&gt;Why would you even bother using modelling tools and technologies? :&lt;/p&gt;
&lt;h4&gt;1. Using modelling tools keeps track of how your classes/flow/environment will look like and how they will work with each-other.&lt;/h4&gt;
&lt;p&gt;Check information from University of Cambridge about &lt;a href="https://www.cl.cam.ac.uk/teaching/1112/SWDesign/materials.html"&gt;Software Design - course materials.&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;2. Designing software will push you to think-through about specific components in project.&lt;/h4&gt;
&lt;p&gt;You will probably think about elements in project, but human-beings have more visual-memory developed, hence I'll present you something:&lt;/p&gt;
&lt;h4&gt;3. Creating complex software-engineering system needs some documentation and proper design.&lt;/h4&gt;
&lt;p&gt;Think about NASA - if they would not design and keep documentation, how would they be able to comunicate with engineers in space and help them with problems they are facing day-by-day ?&lt;/p&gt;
&lt;p&gt;Plan for the spacecraft that was designed at 21 May 1959:
&lt;img alt="Projects Mercury Spacecraft Interior Arrangement" src="images/mercury_spacecraft_interior_arrangement.gif"&gt;&lt;/p&gt;
&lt;h4&gt;4. You can reverse process and instead of using UML only for modelling, use it for creating source code.&lt;/h4&gt;
&lt;p&gt;In my professional experience I've used DIA some time ago. You can even read content of the dia diagrams - because they are simple xml files.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://dia-installer.de/"&gt;DIA&lt;/a&gt; is the modelling tool that with extension called &lt;a href="http://dia2code.sourceforge.net/index.html"&gt;dia2code&lt;/a&gt;( &lt;a href="http://dia2code.sourceforge.net/index.html"&gt;dia2code on github&lt;/a&gt;) can be used to generate code based on UML design.&lt;/p&gt;
&lt;p&gt;Ofcourse you may be sure that dia2code will only reshape your diagrams into simplest classes with methods, but you will need to fill it with some &lt;a href="https://www.youtube.com/watch?v=6ZKGUo9YmCA"&gt;juice-source-code&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Why use reverse-engineering tool like pyreverse ?&lt;/h1&gt;
&lt;h4&gt;1. You need to investigate a source code that you haven't created and code has more then 10 classes and relationships between them.&lt;/h4&gt;
&lt;p&gt;I.e. You get involved in new project. Projects has already some code that is hard to read and understand in first hand. You may find yourself reading and analysing source code and creating flow blocks how code works, that reverse-engineering tool could do for you in almost snap-of-a-finger.&lt;/p&gt;
&lt;p&gt;Making example in real-life - you want to know what are &lt;a href="https://github.com/getpelican/pelican"&gt;pelican source-code&lt;/a&gt; relations to better understand how it works:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;git clone https://github.com/getpelican/pelican
pyreverse -o png -ASmy pelican/pelican/
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Output is big - it contains all classes , it's methods and relationships, hence it's approximately 2MB.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://s000.tinyupload.com/download.php?file_id=08504611644485281450&amp;amp;t=0850461164448528145080974"&gt;Pyreverse on Pelican - PNG File ~2MB&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let's make a more sliced up example, previous version contained test classes that let's say for this example don't have particular usage.&lt;/p&gt;
&lt;p&gt;So how to ignore this files ?&lt;/p&gt;
&lt;p&gt;Check asciinema video:&lt;/p&gt;
&lt;p&gt;&lt;link rel="stylesheet" type="text/css" href="css/asciinema-player.css" /&gt;
&lt;asciinema-player src="asciinema/pelican-pyreverse.json"&gt;&lt;/asciinema-player&gt;
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;Tests are located at directory pelican/pelican/tests, hence to ignore them, we needed to add &lt;code&gt;--ignore tests&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can use &lt;code&gt;--ignore&lt;/code&gt; multiple times. Take only into account that you need to use relative path  - instead of i.e. &lt;code&gt;pelican/pelican/tests&lt;/code&gt; - simply &lt;code&gt;tests&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Pyreverse on Pelican without Tests" src="images/classes_Pelican_ignoring_tests_classes.png"&gt;&lt;/p&gt;
&lt;h4&gt;2. Want to have visual presentation of what has been already created.&lt;/h4&gt;
&lt;p&gt;You want to see how your classes and methods looks like outside of programming language context ??&lt;/p&gt;
&lt;p&gt;Check reverse engineering tools to read your classes from source-code.&lt;/p&gt;
&lt;h1&gt;Prerequisites&lt;/h1&gt;
&lt;p&gt;First we need to add dependencies to our run environment to make pyreverse work properly.&lt;/p&gt;
&lt;p&gt;Pyreverse has been integrated to pylint from 0.5.1  version.&lt;/p&gt;
&lt;p&gt;Biking-Endorphines already has pylint integrated in requirements.txt, hence for this project I will not need to install it.&lt;/p&gt;
&lt;p&gt;If you would need to integrate pyreverse to your project, here are instructions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;apt-get install -y graphviz 
apt-get install -y python-pip
pip install pylint
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Pyreverse on Biking Endorphines.&lt;/h1&gt;
&lt;h4&gt;1. Normal usage, see example at asciinema!&lt;/h4&gt;
&lt;p&gt;&lt;link rel="stylesheet" type="text/css" href="css/asciinema-player.css" /&gt;
&lt;asciinema-player src="asciinema/biking_endorphines_pyreverse.json"&gt;&lt;/asciinema-player&gt;&lt;/p&gt;
&lt;p&gt;Result (for web-project):&lt;/p&gt;
&lt;p&gt;&lt;img alt="Biking Endorphines Web project classes" src="images/classes_Biking-Endorphines-web.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Biking Endorphines Web project packages" src="images/packages_Biking-Endorphines-web.png"&gt;&lt;/p&gt;
&lt;h4&gt;2. Specific class only:&lt;/h4&gt;
&lt;p&gt;But you can also do a specific class research:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pyreverse -c User -o png bikingendorphines/web/models.py
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Result?&lt;/p&gt;
&lt;p&gt;&lt;img alt="Biking Endorphines User Model class" src="images/User.png"&gt;&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;Since I still haven't figure out where to place pyreverse outputs and want to have them generated whenever travis will succeed - no commits for this post.&lt;/p&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vi/VIM&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Pyreverse&lt;/li&gt;
&lt;li&gt;Asciinema&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. Different versions of Pyreverse at Internet.&lt;/h3&gt;
&lt;p&gt;This is like the first time I actually use pyreverse - I've only heard about it or use it like once couple of years ago.&lt;/p&gt;
&lt;p&gt;Now as it turns out there are unmaintained version of pyreverse of 0.5.1 version, and the integrated with pylint version.&lt;/p&gt;
&lt;p&gt;There is no such thing like proper documentation in the Internet. There is only man-page documentation and the helper-info from pyreverse command itself.&lt;/p&gt;
&lt;p&gt;You may also search for usage of this tool by others.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;Read carefully manual page or helper info from &lt;code&gt;pyreverse --help&lt;/code&gt;, ask me (not that I'm experienced with it or something :) ) or search for solution among other developers/technicians.&lt;/p&gt;
&lt;h3&gt;2. Pyreverse --ignore was a total nightmare.&lt;/h3&gt;
&lt;p&gt;I've thought I'll use either an absolute path or relative path (but i.e. of pelican : pelican/pelican/tests) - No luck with that.&lt;/p&gt;
&lt;p&gt;Finally I've found out &lt;a href="https://www.logilab.org/blogentry/6883"&gt;HERE&lt;/a&gt;, that the path is relative, but starts from where you add source-code to look for (ahh should be more carefull about that ).&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://pythonhosted.org/theape/documentation/developer/explorations/explore_graphs/explore_pyreverse.html"&gt;Exploring Pyreverse at pythonhosted.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/1190854/automatically-generated-python-code-from-an-uml-diagram"&gt;Generate Python code using UML at StackOverflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/260165/whats-the-best-way-to-generate-a-uml-diagram-from-python-source-code"&gt;Generate UML for python source-code at StackOverflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/List_of_Unified_Modeling_Language_tools"&gt;List of UML Tools at wiki&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/PlantUML"&gt;PlantUML&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Visual_memory"&gt;Visual Memory&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.nasa.gov/news/releases/latest/index.html"&gt;NASA news&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.quora.com/How-could-I-get-a-spaceship-designed-by-NASA"&gt;Quora- How Could I get a spaceship designed by NASA&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.nasa.gov/sites/default/files/atoms/files/nasa_graphics_manual_nhb_1430-2_jan_1976.pdf"&gt;Nasa Graphics Manual January 1976&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h4&gt;1. Find a way to make travis push pyreverse output on successful master build - either at my blog or at github - maybe github-pages?&lt;/h4&gt;
&lt;h4&gt;2. Check my &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues"&gt;TODO-LIST/Issues at Github&lt;/a&gt;&lt;/h4&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="modelling-tools"></category><category term="uml"></category><category term="pyreverse"></category><category term="reverse-engineering"></category></entry><entry><title>Pelican blog with Fabric and FTP deployment part 1/2</title><link href="http://witkowskibartosz.com/blog/pelican-blog-with-fabric-and-ftp-deployment-part1-on-2.html" rel="alternate"></link><published>2017-03-15T23:00:00+01:00</published><updated>2017-03-15T23:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-15:/blog/pelican-blog-with-fabric-and-ftp-deployment-part1-on-2.html</id><summary type="html">&lt;h1&gt;FTP at Fabric - Mini Project - Requirements&lt;/h1&gt;
&lt;p&gt;There are few other attempts to create ftp connection using fabric. I've found most of them interesting. The most closest to my version can be found 
&lt;a href="http://adampresley.github.io/2013/04/20/how-i-deployed-a-php-app-via-ftp-using-fabric-and-git.html"&gt;How I Deployed a PHP App via FTP using Fabric and Git&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What Ftp libraries for python there …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;FTP at Fabric - Mini Project - Requirements&lt;/h1&gt;
&lt;p&gt;There are few other attempts to create ftp connection using fabric. I've found most of them interesting. The most closest to my version can be found 
&lt;a href="http://adampresley.github.io/2013/04/20/how-i-deployed-a-php-app-via-ftp-using-fabric-and-git.html"&gt;How I Deployed a PHP App via FTP using Fabric and Git&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What Ftp libraries for python there are ?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://ftputil.sschwarzer.net/trac"&gt;ftputil&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/2/library/ftplib.html"&gt;ftplib&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://pycurl.io"&gt;PyCurl&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Main thing that I'm interested in is support of netrc file - where I put credentials.&lt;/p&gt;
&lt;p&gt;I've found examples that can be used for .netrc file with pycurl:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.programcreek.com/python/example/53121/pycurl.NETRC"&gt;ProgramCreek Pycurl.netrc file&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/2/library/netrc.html"&gt;Python.org Netrc file access&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I know that using PyCurl can be a good option in this situation, but for now I'm dropping this solution.&lt;/p&gt;
&lt;h1&gt;FTP pre-solution&lt;/h1&gt;
&lt;p&gt;I didn't have enough time to make best source-code for this problem, so at least I've spend that time for investigation of solutions that are available.&lt;/p&gt;
&lt;p&gt;But a quick-dirty solution - also called "duct taping" can be found below:&lt;/p&gt;
&lt;p&gt;Simplest and the less-time consuming would be for now either use &lt;code&gt;make ftp_upload&lt;/code&gt; or a python-fabric-replicator that uses the same thing as in make:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ftp_upload&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# simplest solution for now.&lt;/span&gt;
    &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lftp ftp://{ftp_user}@{ftp_host} -e &amp;quot;mirror -R {deploy_path} {ftp_target_dir}; quit&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To use this part of code at Fabric execution, use this command (uses .netrc password):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;fab --set &lt;span class="nv"&gt;ftp_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_FTP_USER,ftp_host&lt;span class="o"&gt;=&lt;/span&gt;YOUR_FTP_HOST,ftp_target_dir&lt;span class="o"&gt;=&lt;/span&gt;YOUR_FTP_TARGET_DIR ftp_upload
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Examples above presents using ftp &lt;code&gt;mirror&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;I could use the &lt;code&gt;mirror -R INPUT_DIR OUTPUT_TARGET_DIR; quit&lt;/code&gt; with ftplib &lt;code&gt;sendcmd&lt;/code&gt; - But it's almost identical solution as with lftp command itself.&lt;/p&gt;
&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Still to be revealed :) Upcomming github repository for this Mini-Project.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Tools and applications used:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Docker (local devserver showing pelican's post I'm currently working on)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vi/VIM as my main editor&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tmux act as my session-protector - even if I close by mistake window with ssh to server on which I'm writing this post right now using tmux, tmux will hold session and I can reconnect to it next time and everything will be the same as before I've closed window with ssh&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MobaXTerm for ssh connections.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. FTPLib is not your best-friend.&lt;/h3&gt;
&lt;p&gt;As I've found out Python's FTPLib is just a simple connector to ftp with simplest accessing to ftp. No fancy-pancy like "put_directory" or other "put_directory_mirror_files" or something simillar.&lt;/p&gt;
&lt;p&gt;I'm a little bit dissapointed - I had great hopes with this library.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Find better library or other libraries that are extended via this library - &lt;a href="http://ftputil.sschwarzer.net/trac"&gt;ftputil&lt;/a&gt; looks promissing&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. SFTP at the fabric source-code was a total surprice&lt;/h3&gt;
&lt;p&gt;When first I've found that there is a SFTP connector at the &lt;a href="https://github.com/fabric/fabric/blob/master/fabric/sftp.py"&gt;Fabric source-code&lt;/a&gt; - thought - THATS IT !&lt;/p&gt;
&lt;p&gt;But yeah... wait a second... It's not using ftp.... hmm why not?&lt;/p&gt;
&lt;p&gt;Right, I did forgot it's not FTP I thought - it's SSH based file transfer, not an FTP with some additional SSL/Security.&lt;/p&gt;
&lt;p&gt;So I was back to root-cause-analysis - if I may use that medical terminology :) (Hope no medical stuff will be angry at me because of that :D )&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;I will probably use the &lt;code&gt;ftputil&lt;/code&gt; library because it contains python-friendly naming convensions and extends ftplib much more than I could want for now.&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/24946974/create-remote-directory-using-fabric-operations-put"&gt;Fabric usage for remote-create-dir via ftp on StackOverflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/git-ftp/git-ftp"&gt;Git FTP at Github.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nerds.inn.org/2014/05/19/using-fabric-for-wpengine-wordpress-deployments/"&gt;Fabric for WP Engine site Deployments&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ftputil.sschwarzer.net/trac/wiki/Documentation"&gt;FTPUtil Documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.activestate.com/recipes/576777-simple-ftp-mirror/"&gt;Simple FTP Mirror - By Thimo Kraemer&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h5&gt;1. Push source code of pelican and fabric deployment with fabric code that supports ftp using some library.&lt;/h5&gt;
&lt;h5&gt;2. Add additional parameters to Fabric to be able to use different environments at the same time without having to change source-code of &lt;code&gt;fabfile.py&lt;/code&gt;&lt;/h5&gt;
&lt;p&gt;See you at next Wednesday - this time I hope to make post faster then 1 hour before end of day :)&lt;/p&gt;</content><category term="anselmos-pelican-blog-source"></category><category term="fabric"></category><category term="ftp"></category><category term="deployment"></category><category term="mini-project"></category><category term="pycurl"></category><category term="ftputil"></category><category term="ftplib"></category></entry><entry><title>Django Unit Tests at Biking Endorphines</title><link href="http://witkowskibartosz.com/blog/django-unit-tests-biking-endorphines.html" rel="alternate"></link><published>2017-03-12T00:00:00+01:00</published><updated>2017-03-12T00:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-12:/blog/django-unit-tests-biking-endorphines.html</id><summary type="html">&lt;h1&gt;Unit Tests why would you need this at all?&lt;/h1&gt;
&lt;h3&gt;1. Unit tests and regression testing!&lt;/h3&gt;
&lt;p&gt;Gives you confidence of not breaking your previous features by creating new features.&lt;/p&gt;
&lt;h3&gt;2. Program some more!&lt;/h3&gt;
&lt;p&gt;When you create unit-tests you have to think-through on the source-code to be proper applied to the tests …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Unit Tests why would you need this at all?&lt;/h1&gt;
&lt;h3&gt;1. Unit tests and regression testing!&lt;/h3&gt;
&lt;p&gt;Gives you confidence of not breaking your previous features by creating new features.&lt;/p&gt;
&lt;h3&gt;2. Program some more!&lt;/h3&gt;
&lt;p&gt;When you create unit-tests you have to think-through on the source-code to be proper applied to the tests.&lt;/p&gt;
&lt;p&gt;From my own experience I have to confess - there were times when I've changed source-code of application to support properly unit-tests.&lt;/p&gt;
&lt;h3&gt;3. Time-saver !&lt;/h3&gt;
&lt;p&gt;You code new feature, you are not sure and have no proper time to test if all of "old" features are working properly.&lt;/p&gt;
&lt;p&gt;Then you use your previously created unit-tests and find-out if at the "unit" stage, you got something broke or not.&lt;/p&gt;
&lt;h1&gt;How to use django integrated tests?&lt;/h1&gt;
&lt;p&gt;Django integrated tests uses python unittest module. This is setup with integration to django, thanks to which to run initial tests simply:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;python manage.py &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;But when you find yourself creating multiple django "applications" this will not work. You may need to add something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;python manage.py &lt;span class="nb"&gt;test&lt;/span&gt; application_directory
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;In my project I've added to Makefile :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;python bikingendorphines/manage.py &lt;span class="nb"&gt;test&lt;/span&gt; web
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;How to create unit tests that are integrated with Django Framework?&lt;/h1&gt;
&lt;p&gt;Code below show how to setup your initial first test.
This is placed in "test*.py" files.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Unit tests for web-application.&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="c1"&gt;# disabling because this import will be used in future&lt;/span&gt;
&lt;span class="c1"&gt;# pylint: disable=unused-import&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    A User-class test-case&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&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;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Bart&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Trab&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;175&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;test_user_bmi&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Tests if users has been created in db&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;bart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Bart&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;trab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&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;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Trab&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trab&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The User class itself I've defined in this way:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    User model for obtaining personal information about biking riders&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&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;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__unicode__&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Returns User information when using str/printing&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bmi&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Body Mass Index calculator simplified to number&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Code commits done for this post:&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/05096680151064eb963063826dde4c1871812029"&gt;Adds django-unit tests to Travis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/5b3a718c95236f7229224dc47b5124dee05b45cc"&gt;Adds Web Application and pylint fixes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/7b1578b310bd03f4d929585bc2fab6e28a31f967"&gt;Add Initial unit-tests with User db class&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. Allowed_Hosts problem.&lt;/h3&gt;
&lt;p&gt;I finally was at the stage when I wanted to see if at least the debug page for djagno will popup.&lt;/p&gt;
&lt;p&gt;But didn't know that django developers change default behaviour of ALLOWED_HOSTS and now does not add the "star" (as all-hosts allowed)&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;Since I'm using VM that is simply a server-based - I had to a change allowed_hosts variable at the &lt;a href="https://github.com/anselmos/Biking-Endorphines/commit/7b1578b310bd03f4d929585bc2fab6e28a31f967#diff-d8da03987e8c91bbec67662538af70ca"&gt;bikingendorphines/bikingendorphines/settings.py&lt;/a&gt; file with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;ALLOWED_HOSTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;2. Pylint errors.&lt;/h3&gt;
&lt;p&gt;Pylint was not optimized as I found out at the coding stage with some django - elements i.e. &lt;code&gt;objects&lt;/code&gt; at the Models.&lt;/p&gt;
&lt;p&gt;Pylint issue with not recognizing "migration" django scripts and finding lint-errors. I wouldn't mind if I had to manually create this files, but they were made automatically at the &lt;code&gt;python manage.py makemigrations&lt;/code&gt; phase.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;Added pylint_django python module using &lt;code&gt;pip install pylint_django&lt;/code&gt; and added &lt;code&gt;--load-plugins pylint_django&lt;/code&gt; to my Makefile task that is used by Travis to complete pylint tests.&lt;/p&gt;
&lt;p&gt;Added &lt;code&gt;migrations&lt;/code&gt; to &lt;code&gt;.pylintrc&lt;/code&gt; file within section &lt;code&gt;ignore&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;3. Pylint and Django-unit tests errors&lt;/h3&gt;
&lt;p&gt;I had some issues when integrating together Pylint and Django-Unit tests.&lt;/p&gt;
&lt;h4&gt;Solution:&lt;/h4&gt;
&lt;p&gt;For django-unit test to properly work I had to firstly remove the &lt;code&gt;__init__.py&lt;/code&gt; python file that describes directory as a module - at the root of the &lt;code&gt;bikingendorhpines&lt;/code&gt; project dir.&lt;/p&gt;
&lt;p&gt;I had to change pylint to search for particular folders to find lint-errors in web- "application"&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://docs.djangoproject.com/en/1.10/topics/testing/overview/"&gt;Django Tutorial- Writing and running tests&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.djangoproject.com/en/1.10/topics/db/models/"&gt;Django Models Tutorial &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.djangoproject.com/en/1.10/ref/applications/"&gt;Django Applications&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/2503717/pylint-ignore-by-directory"&gt;Pylint Ignore Directory at stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.landscape.io/using-pylint-on-django-projects-with-pylint-django.html"&gt;Using Pylint at Django-Based projects - landscape Blog&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's Next ??&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PyReverse to create a PNG files with all classes at Django and our project.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check what I've got to do in issues of github: &lt;a href="https://github.com/anselmos/Biking-Endorphines/issues"&gt;ISSUES&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="django"></category><category term="unit-test"></category><category term="travis-ci"></category><category term="pylint"></category></entry><entry><title>Behind closed doors - Biking Endorphines idea.</title><link href="http://witkowskibartosz.com/blog/behind-closed-doors-b-e-idea.html" rel="alternate"></link><published>2017-03-11T00:00:00+01:00</published><updated>2017-03-11T00:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-11:/blog/behind-closed-doors-b-e-idea.html</id><summary type="html">&lt;h1&gt;Biking Endorphines - story REVEALED.&lt;/h1&gt;
&lt;p&gt;Story behind the bars :)&lt;/p&gt;
&lt;p&gt;How this project came to my mind and why I've started it?&lt;/p&gt;
&lt;p&gt;This project came to my mind as an idea, that I could motivate myself to ride bike more offen than I do now.&lt;/p&gt;
&lt;p&gt;Second part besides of "motivation for riding …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Biking Endorphines - story REVEALED.&lt;/h1&gt;
&lt;p&gt;Story behind the bars :)&lt;/p&gt;
&lt;p&gt;How this project came to my mind and why I've started it?&lt;/p&gt;
&lt;p&gt;This project came to my mind as an idea, that I could motivate myself to ride bike more offen than I do now.&lt;/p&gt;
&lt;p&gt;Second part besides of "motivation for riding" is leveling up my technical experience in Python and Android.&lt;/p&gt;
&lt;p&gt;I begin to think, that there are sites like "Endomondo", "Strava", but they all share almost the same thing - keeping only how much kilometers/miles you've ride a bike.&lt;/p&gt;
&lt;p&gt;They only motivate you in particular way :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;to ride bike more offen by comparing your amount of kilometers you've rode (Endomondo).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;to ride bike and compare timing in particular ride-path with others (Strava).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The thing that I've always missed in this type of applications was motivation for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;"adventure" - i.e. finding new roads that you can shorten/lengthen/alternate your ride&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;keep-up with your training - motivation for training in particular day with particular path&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;how high you've rode your bike&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;did you ride with your beloved people.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And many others that I might not think-through yet.&lt;/p&gt;
&lt;p&gt;I thought why not use &lt;code&gt;endorphines&lt;/code&gt; as a &lt;code&gt;badge&lt;/code&gt; for each of this "motivation" types and create web-site that will encourage people to collect them by riding bike in different ways.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Calm Endorphines" src="http://witkowskibartosz.com/blog/images/endorphins_everywhere.jpg"&gt;&lt;/p&gt;
&lt;p&gt;So that's the idea, now we can go-on to more technical stuff.&lt;/p&gt;
&lt;h1&gt;Phases of project&lt;/h1&gt;
&lt;p&gt;I see at least for now 5 phases of this project.&lt;/p&gt;
&lt;h3&gt;1. Web-Application.&lt;/h3&gt;
&lt;p&gt;Main part of this project. Other components will be focused around this part. &lt;/p&gt;
&lt;p&gt;Database using standard Django ORM with all statistics data per each gps route of biking ride.&lt;/p&gt;
&lt;p&gt;Web-part itself will be created using standard Django MVC. Planning to create:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Endorphines badges per "motivation" type.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;each biking ride data will be analysed in search for "endorphines" pattern i.e. to gather "adventure" endorphine, algorithm will compare gps coordinates data located at database.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Biking routes statistics&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Calendar with all biking rides &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. REST-API.&lt;/h3&gt;
&lt;p&gt;REST API created with CRUD in mind.
Will help access Android application to data available at Web-Application.&lt;/p&gt;
&lt;p&gt;Why not SOAP Api you may ask ?  Taking into account that all data will be send/received via android phone, you have to create API that will not use a lot of data to transfer information - this disqualifies SOAP as it adds a lot of additional not-needed in this situation data.&lt;/p&gt;
&lt;h3&gt;3. Android Application.&lt;/h3&gt;
&lt;p&gt;Android Application will be focused on gathering data and some simple statistics with endorphines badges already gathered.&lt;/p&gt;
&lt;h3&gt;4. Merging phase.&lt;/h3&gt;
&lt;p&gt;This phase will be integration of all above components.&lt;/p&gt;
&lt;h3&gt;5. Maintainance.&lt;/h3&gt;
&lt;p&gt;Maintainance phase will be focused on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;tweaking endorphines gathering-data statistics manipulation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;tweaking gps data gathering (if any possible)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;correcting any bugs&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.endomondo.com/"&gt;Endomondo&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.strava.com/"&gt;Strava&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer"&gt;REST&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/SOAP"&gt;SOAP&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/19884295/soap-vs-rest-differences"&gt;REST vs SOAP on stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;h5&gt;1. Go to phase 1 and start with initial code for database&lt;/h5&gt;
&lt;h5&gt;2. Create first initial unit-tests and add Travis to perform this tests in parallel with pylint tests.&lt;/h5&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category></entry><entry><title>Blog posts deployment using Pelican and Fabric</title><link href="http://witkowskibartosz.com/blog/blog-post-deployment-with-fabric.html" rel="alternate"></link><published>2017-03-08T00:00:00+01:00</published><updated>2017-03-08T00:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-08:/blog/blog-post-deployment-with-fabric.html</id><summary type="html">&lt;h1&gt;Introduction - How I end-up with slappy SCP?&lt;/h1&gt;
&lt;p&gt;I've decided I'll use my old laptop (which is currently used as a media server for TV) as my main "server" for maintaining and creating content and building site on it.&lt;/p&gt;
&lt;p&gt;I have to confess, two posts (how-to-create-own-blog &amp;amp;&amp;amp; get-noticed ) were deployed by me …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction - How I end-up with slappy SCP?&lt;/h1&gt;
&lt;p&gt;I've decided I'll use my old laptop (which is currently used as a media server for TV) as my main "server" for maintaining and creating content and building site on it.&lt;/p&gt;
&lt;p&gt;I have to confess, two posts (how-to-create-own-blog &amp;amp;&amp;amp; get-noticed ) were deployed by me manually using SCP and "Filezilla" client.
I knew it was not best idea, but still time was ticking as I wanted to keep-up with publishing first post at 1st March.&lt;/p&gt;
&lt;p&gt;I've got into a "shortcut" mode to make it faster. And now I see it actually makes deployment slower for next-times.&lt;/p&gt;
&lt;p&gt;I've decided to level up and move with deployment to using Fabric - since Pelican's quickstart creates this 'fab' file with defaults.&lt;/p&gt;
&lt;h1&gt;Problems with x32 bit docker-images and Fabric.&lt;/h1&gt;
&lt;p&gt;On my old laptop I've got windows in 32bit version installed, so obvious reason was to install a 32bit ubuntu VM on it and then use docker from this VM.&lt;/p&gt;
&lt;p&gt;Then I've stepped on problem, that almost all type of docker images out-there, supports only 64bit docker-host - this means that images like python:2.7.11 also does not work - since they are supported only on 64 bit arch. A Prove of this concept can be seen on one of VM's I'm currently using - proudly presents using &lt;a href="https://asciinema.org"&gt;AsciiNema&lt;/a&gt; :&lt;/p&gt;
&lt;p&gt;&lt;link rel="stylesheet" type="text/css" href="css/asciinema-player.css" /&gt;
&lt;asciinema-player src="asciinema/python_32bit_support.json"&gt;&lt;/asciinema-player&gt;
&lt;script src="scripts/asciinema-player.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;Now, I could re-install windows on laptop,but since this laptop has history with battery not-keeping energy and a malfuncion of power at startup, I've decided not to go this way.&lt;/p&gt;
&lt;p&gt;Before I figure out that I could deploy second VM with 64bit ubuntu as a docker-host (since laptop supports 64bit architecture), I've decided I'll go a longer but much more satisfying way - creating my own docker images that will support 32bit hosts! &lt;/p&gt;
&lt;p&gt;My thinking was like that: I've got an even older laptop that supports only 32bit architecture and few stationary machines - this docker images will be usefull for future deployment.&lt;/p&gt;
&lt;p&gt;My adventure with building 32bit docker image that will support Fabric and Pelican and other deployment/development packages has began.&lt;/p&gt;
&lt;h1&gt;Building x32 Bit Docker image with packages for Fabric&lt;/h1&gt;
&lt;p&gt;I didn't have to start from "source" - since I already had an ubuntu-trusty 32bit image that I've created some time ago using tutorial which you can find &lt;a href="http://mwhiteley.com/linux-containers/2013/08/31/docker-on-i386.html"&gt;HERE&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I've used a anselmos/ubuntu32 image that is available at  &lt;a href="https://hub.docker.com/r/anselmos/ubuntu32/"&gt;image&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As this image is a bare-bone I had to first install a pip.&lt;/p&gt;
&lt;p&gt;Funny, but I could not download "get-pip" from image, so I've added "wget" to docker-image.
To be able to install Pip I had to install a wget by which I could download a "get-pip.py" file.&lt;/p&gt;
&lt;p&gt;Then I had to install python since there was no-python.&lt;/p&gt;
&lt;p&gt;After that I've realized that just "pip install Fabric" will not work, because there are linux library dependencies for Fabric like :
- python-dev
- libffi-dev
- libssl-dev&lt;/p&gt;
&lt;p&gt;Finally I knew Pelican python-library does not go with Markdown installed as default (reStructured is) so I had to add Markdown.&lt;/p&gt;
&lt;p&gt;Thankfully then I was able to work on docker-image and finally we can move-on to part where we actually configure our deployment for ssh/ftp&lt;/p&gt;
&lt;p&gt;Final version of ubuntu-trusty docker x32 bit docker image with Pelican installed and Fabric ready is &lt;a href="https://hub.docker.com/r/anselmos/pelican32/"&gt;pelican32&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can use &lt;code&gt;docker pull anselmos/pelican32&lt;/code&gt; and the image will appear at your host. Keep in mind that this image will only work on x32bit Host-machine for docker. For x64bit - just use official image for python and do &lt;code&gt;pip install Pelican &amp;amp;&amp;amp; pip install Fabric&lt;/code&gt;. You may also use image that I've prepared based on python:2.7.11 image available &lt;a href="https://hub.docker.com/r/anselmos/pelican/"&gt;pelican&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Configuring Deployment for Fabric using ssh/ftp.&lt;/h1&gt;
&lt;p&gt;At beginning when using pelican-quickstart script, a file called &lt;code&gt;fabfile.py&lt;/code&gt; is created with our answers. &lt;/p&gt;
&lt;p&gt;We can change them if defaults that we set-up have change or we made a mistake.&lt;/p&gt;
&lt;h2&gt;Setup FTP connection&lt;/h2&gt;
&lt;p&gt;Unfortunatelly as I found out you cannot use Fabric with it's default fabfile.py setup for FTP.&lt;/p&gt;
&lt;p&gt;At the time I'm writing this post, I'll not find time to fix this, but I see there's possibility to use make.&lt;/p&gt;
&lt;p&gt;just &lt;code&gt;make ftp_upload&lt;/code&gt; and using Makefile setup variables it will upload files &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;FTP_HOST=localhost
FTP_USER=bawi
FTP_TARGET_DIR=/var/www
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Docker image I'm using needed installation of this packages:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;apt-get install -y make
apt-get install -y lftp
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I will make an update soon for how to overcome this issue using Fabric.&lt;/p&gt;
&lt;h2&gt;Setup SSH connection&lt;/h2&gt;
&lt;p&gt;Use the &lt;code&gt;production&lt;/code&gt; variable and change to proper values, e.g. your production hostname is "localhost" and port on which ssh works is "22" and user on this host is "root" then value should  be &lt;code&gt;'root@localhost:22'&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;For my setup I had to add also ssh-client for docker-image and add ssh-keys to image by adding docker-volume attachment.&lt;/p&gt;
&lt;p&gt;Keep in mind, that using ssh method requires &lt;code&gt;rsync&lt;/code&gt; installed on your system - my docker image didn't have it so ... yeah :) I had to install it :)&lt;/p&gt;
&lt;p&gt;And also keep in mind that default directory is &lt;code&gt;/var/www&lt;/code&gt;. If you want to change that then change variable :
&lt;code&gt;dest_path = '/var/www'&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;What's next ?&lt;/h1&gt;
&lt;h5&gt;1. I will make an update on FTP fabric issue with how to overcome this.&lt;/h5&gt;
&lt;h5&gt;2. Docker usage and making your own Docker image available at hub.docker.com&lt;/h5&gt;
&lt;p&gt;What do you think about this post ? Let me know in comments below - Stay Tuned ! Soon post for Get-Noticed!&lt;/p&gt;</content><category term="python"></category><category term="pelican"></category><category term="fabric"></category><category term="docker"></category><category term="scp"></category></entry><entry><title>Biking Endorphines - Where to Begin?</title><link href="http://witkowskibartosz.com/blog/biking-endorphines-where-to-begin.html" rel="alternate"></link><published>2017-03-05T15:00:00+01:00</published><updated>2017-03-05T15:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-05:/blog/biking-endorphines-where-to-begin.html</id><summary type="html">&lt;h1&gt;What Github offers us.&lt;/h1&gt;
&lt;p&gt;Since project &lt;code&gt;Biking Endorphines&lt;/code&gt; will be maintained at open-source Github, let's check what type of tools does Github offers us.&lt;/p&gt;
&lt;p&gt;To narrow down our research, let's just find tools available as "free" - they will all be an Continuous Integration tools which purpose will be to build …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;What Github offers us.&lt;/h1&gt;
&lt;p&gt;Since project &lt;code&gt;Biking Endorphines&lt;/code&gt; will be maintained at open-source Github, let's check what type of tools does Github offers us.&lt;/p&gt;
&lt;p&gt;To narrow down our research, let's just find tools available as "free" - they will all be an Continuous Integration tools which purpose will be to build &amp;amp;&amp;amp; test.&lt;/p&gt;
&lt;h3&gt;1. Jenkins CI&lt;/h3&gt;
&lt;p&gt;This is a fork of Hudson (or a Hudson is fork of Jenkins) - how-ever the split for Hudson/Jenkins was, Jenkins has more maintainers and commits which means it is more-actively maintained.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jenkins.io/"&gt;Jenkins&lt;/a&gt; is suppported natively by github with it's available &lt;a href="https://jenkins.io/solutions/github/"&gt;services-integration-to-project&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Advantage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You can tweak the whole build &amp;amp; test process within it's internals.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Support for all languages (if you can set-it-up)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Setup process takes a while.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Need to configure most of the setup with web-ui&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Unfortunatelly It's not something new for me.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. SonarQube&lt;/h3&gt;
&lt;p&gt;Link: &lt;a href="https://github.com/integrations/sonarqube"&gt;SonarQube Integration for Github&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Summary: Open Source Platform for code inspection and code quality.&lt;/p&gt;
&lt;p&gt;This uses pull-requests and before you have code available at "master" branch, you will have to merge it with this SonarQube tool. It will automatically get pull-request and using linguistics check code quality. You may also review code and find bugs on your own.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://help.github.com/articles/about-pull-requests/"&gt;About pull-requests&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://help.github.com/articles/creating-a-pull-request/"&gt;How to create your first pull-request with Github&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Advantage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;More complex setup for code-quality.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Support for multilple languages &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A little bit to complicated and needs more time to spend for setup than I have previously.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Only for setting up code-quality tests&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I may go back to this solution in future.&lt;/p&gt;
&lt;h3&gt;3. Travis CI.&lt;/h3&gt;
&lt;p&gt;About this CI I've heard for more then 2 years from now. I've always wanted to investigate usage of this CI tool.&lt;/p&gt;
&lt;p&gt;Advantage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It's maintainance focuses only on one &lt;code&gt;.travis.yml&lt;/code&gt; file that has all scripts for running scripts in it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What ever you code in your scripts, travis will take it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It's only hosted online, if you want to deploy it on your local server/machine (correct me if I'm wrong) - if it's only for your investigation than in my opinion you could use it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Not free for private projects/commercial projects not visible for public - &lt;a href="https://docs.travis-ci.com/user/travis-pro/"&gt;Check Prices for Commercial Usage&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So for me, dispite disadvantage's - is the choice - at least for now.&lt;/p&gt;
&lt;h1&gt;Issue -bug-enhancement Tracking software integrations&lt;/h1&gt;
&lt;h3&gt;1. Issue tracking software available I've seen at project service integration setup.&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Redmine&lt;/li&gt;
&lt;li&gt;Trac&lt;/li&gt;
&lt;li&gt;Jira.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Issue tracking I'll be using.&lt;/h3&gt;
&lt;p&gt;In my commercial experience I've used all of this bug-tracking software, hence it's a learning process I'd like to skip this to Github possibilities that are for me still a new-thing.&lt;/p&gt;
&lt;p&gt;Add to this, that some of this tracking software can be setup as a private servers, and this project is a open-sourced - this collapse - hence Github &lt;code&gt;Issues&lt;/code&gt; and &lt;code&gt;Projects&lt;/code&gt; tabs are going to be used by me in this project.&lt;/p&gt;
&lt;h1&gt;Travis - be prepared - here we go!&lt;/h1&gt;
&lt;p&gt;To start with travis configuration:&lt;/p&gt;
&lt;h3&gt;1. Create .travis.yml file with appropriate configuration for your project&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;language&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;python&lt;/span&gt;
&lt;span class="l l-Scalar l-Scalar-Plain"&gt;python&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;2.7&amp;quot;&lt;/span&gt;
&lt;span class="l l-Scalar l-Scalar-Plain"&gt;install&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;pip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-r&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;requirements.txt&amp;quot;&lt;/span&gt;

&lt;span class="l l-Scalar l-Scalar-Plain"&gt;script&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; 
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;make pylint&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And the Makefile:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;requirements:
    pip install -r requirements.txt
pylint: requirements
    pylint bikingendorphines --rcfile&lt;span class="o"&gt;=&lt;/span&gt;.pylintrc
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Make task called &lt;code&gt;pylint&lt;/code&gt; will be executed only when &lt;code&gt;requirements&lt;/code&gt; task will finish properly without error - that may be unneeded since .travis has already the same command at his &lt;code&gt;install&lt;/code&gt; task, but I wanted to make sure it will work no-matter what.&lt;/p&gt;
&lt;p&gt;As you've noticed only one script is integrated for now - it's a simple pylint check.&lt;/p&gt;
&lt;h2&gt;To setup pylint with configuration file &lt;code&gt;.pylintrc&lt;/code&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install pylint

pylint --generate-rc-file &amp;gt; .pylintrc &lt;span class="c1"&gt;## this will generate a standard pylintrc configuration file!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You may need to tweak your .pylintrc file for better code-quality-check&lt;/p&gt;
&lt;h3&gt;2. Add project using TravisCI Profile Site&lt;/h3&gt;
&lt;p&gt;You need to login to your account of github.com using &lt;a href="https://travis-ci.org/profile"&gt;TravisCI Profile site&lt;/a&gt; and then select project that you want to have automatical builds.&lt;/p&gt;
&lt;h3&gt;3. Push this file to your repository&lt;/h3&gt;
&lt;p&gt;After setting up at TravisCI site project that will use auto-builds, you can now push your first .travis.yml file to your github repository.&lt;/p&gt;
&lt;h3&gt;4. See what happens at Travis-CI status page of project.&lt;/h3&gt;
&lt;p&gt;I've prepared for the worst-case scenario and that's why I've used only pylint for now to just check how the process of integration with Travis works - still had to overcome some issues with pylint for it not to break at any-point.&lt;/p&gt;
&lt;p&gt;You can check yourself how the process of pylint'ing at TravisCI works for my project here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://travis-ci.org/anselmos/Biking-Endorphines"&gt;&lt;img alt="Build Status" src="https://travis-ci.org/anselmos/Biking-Endorphines.svg?branch=master"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;LL (Lessons Learned)&lt;/h1&gt;
&lt;h3&gt;1. I have a poor time-management.&lt;/h3&gt;
&lt;p&gt;Solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Usage of &lt;a href="https://en.wikipedia.org/wiki/Pomodoro_Technique"&gt;POMODORO TECHNIQUE&lt;/a&gt;  - Special thanks for encouragement are for Krzysztof Jonczyk and his speach about &lt;a href="http://2017.boilingfrogs.pl/schedule/pair-programming-sposob-na-lepszy-kod-i-mocniejszy-zespol-2/"&gt;Pair Programming at Boiling Frogs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Configuration of Integration tools are not an &lt;a href="https://cdn.meme.am/cache/instances/folder102/500x/45422102.jpg"&gt;easy-peasy-lemon-squeezy&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It does not matter if it's a SonarQube / Trac/ TravisCI / Jenkins - all of this integration tools will take time to configure.&lt;/p&gt;
&lt;p&gt;Issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Since I'm starting this project, besides of TravisCI &lt;code&gt;.travis.yml&lt;/code&gt;  I had to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;virtualenv for pip &lt;code&gt;requirements.txt&lt;/code&gt; file using &lt;code&gt;pip freeze &amp;gt; requirements.txt&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;install pylint using pip &lt;code&gt;pip install pylint&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;install framework I'll be using for for purpose of pylint check &lt;code&gt;pip install Django&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;create initial django-project &lt;code&gt;django-admin startproject bikingendorphines&lt;/code&gt; for pylint to be able to work on files.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to &lt;a href="https://travis-ci.org/profile"&gt;TravisCI Profile Site&lt;/a&gt; and FIRST enable TravisCI builds on github project you wish to have auto-builds. Then push .travis.yml file to repository to trigger automatical build.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Estimate more time for integration tools !&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. Django initial project setup is not perfect for default values of pylint-checker configuration&lt;/h3&gt;
&lt;p&gt;Solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For each of new "directories" add &lt;code&gt;__init__.py&lt;/code&gt; - so that all directories becomes "python modules"&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Needed to use &lt;code&gt;#pylint: disable=&lt;/code&gt; for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Default django configuration variables that are not compatible with "invalid-name" check (they are seen as constants by pylint checker - and as a constants, should be upper-case, but they are not - if you are aware why, let me know in comments below )&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;urlpatters&lt;/code&gt; at urls.py&lt;/li&gt;
&lt;li&gt;&lt;code&gt;application&lt;/code&gt; at wsgi.py&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Warning of importing django and not using it at source-code at &lt;code&gt;manage.py&lt;/code&gt; in line with &lt;code&gt;import django&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pylint has a checker for locally disabling line checks at code-level. Since I've used "#pylint: disable" - pylint found this lines and throw at me with error of &lt;code&gt;locally-disabled&lt;/code&gt; - To by-pass this error - I've added &lt;code&gt;locally-disabled&lt;/code&gt; to &lt;code&gt;disable&lt;/code&gt; at &lt;code&gt;.pylintrc&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Continuous_integration"&gt;Continuous Integration Software&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Comparison_of_continuous_integration_software"&gt;Comparison of CI software&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore"&gt;Python GitIgnore file from Github&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/github/gitignore"&gt;GitIgnore Files from Github&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Linguistics"&gt;Linguistics&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://pylint.readthedocs.io/en/latest/index.html"&gt;Pylint Docs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Lessons_learned"&gt;Lessons Learned&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Jenkins_(software)"&gt;Jenkins&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Hudson_(software)"&gt;Hudson&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://travis-ci.org"&gt;TravisCI-public&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://travis-ci.com/"&gt;TravisCI-private&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.travis-ci.com/user/travis-pro/"&gt;TravisPro&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.travis-ci.com/user/languages/python/"&gt;Python TravisCI tutorial at travis-ci.com&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Pomodoro_Technique"&gt;Pomodoro Technique&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;What's next&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Integration of git-commits with Issues at Github&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Features I'll focus in this project.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tools section showing what tools I've used for purpose of each blog-post-session.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category><category term="travis-ci"></category><category term="pylint"></category></entry><entry><title>Get Noticed! - Programming Contest for making your own programming project and blogging about it!</title><link href="http://witkowskibartosz.com/blog/get-noticed.html" rel="alternate"></link><published>2017-03-02T01:00:00+01:00</published><updated>2017-03-02T01:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-02:/blog/get-noticed.html</id><summary type="html">&lt;h1&gt;Get Noticed  ??&lt;/h1&gt;
&lt;p&gt;So what's "Get Noticed" about ? It's a Polish programming Contest that covers creating your own project and making 2 posts a week.&lt;/p&gt;
&lt;p&gt;From those 2 posts, one must be with information about Contest project, the second one can be about any topic that's connected with programming/IT/technologies …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Get Noticed  ??&lt;/h1&gt;
&lt;p&gt;So what's "Get Noticed" about ? It's a Polish programming Contest that covers creating your own project and making 2 posts a week.&lt;/p&gt;
&lt;p&gt;From those 2 posts, one must be with information about Contest project, the second one can be about any topic that's connected with programming/IT/technologies or Contest project.&lt;/p&gt;
&lt;p&gt;The Contest takes a 3-months challenge for maintaining and developing open-sourced (available at github) code and making 2 posts a week.&lt;/p&gt;
&lt;h1&gt;Involvement Time!&lt;/h1&gt;
&lt;p&gt;That's just funny, but first time I've heard about "get-noticed!" I've thought - &lt;code&gt;I'm a little bit to scared to get involved in such a big-deal.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;But wait a second. Do you - I mean YOU - reader of this post - have a spare lifetime? &lt;/p&gt;
&lt;p&gt;Yeah, me neither, so instead of &lt;a href="https://www.youtube.com/watch?v=VTDCEiBeVAY"&gt;being a chicken&lt;/a&gt; I've decided to step-up. &lt;/p&gt;
&lt;p&gt;One inspiration to starting at this contest was not having a lot of coding lately neither at work nor at home.&lt;/p&gt;
&lt;p&gt;Second inspiration that pushed me to my limits of bravery is Wroclaw's Conference called &lt;a href="http://2017.boilingfrogs.pl/"&gt;BoilingFrogs&lt;/a&gt; and their lectures.&lt;/p&gt;
&lt;p&gt;Fortunatelly for me and other contest participants, registration has been extended to 12th of March &lt;a href="http://devstyle.pl/2017/03/01/daj-sie-poznac-bo-masz-kolejna-szanse/"&gt;link-to-post-in-polish&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Project Code-Name :)&lt;/h1&gt;
&lt;p&gt;Project I've decided to reactivate (or perhaps to resurrect would be a better word for it - since it was almost 2 years ago) was an old idea of Biking Statistics.&lt;/p&gt;
&lt;p&gt;Now - Biking Statistics was an idea of creating better statistics than there are for Endomondo's site, but using their input from Android application (GPX files).&lt;/p&gt;
&lt;p&gt;It worked, but I never had time to finish it up. And so it finally was a "shelf" project - You may find it at my github account somewhere -don't hope for a lot.&lt;/p&gt;
&lt;p&gt;The contest project name is different, it's .... fanfare's in background ....&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Biking Endorphines&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I'll say no more about project. Soon when idea will grow up I'll inform you :)&lt;/p&gt;
&lt;h1&gt;What's next ??&lt;/h1&gt;
&lt;p&gt;Within this 3 months I hope to give you such a nice ride that you will not dare to abandon this blog :)&lt;/p&gt;
&lt;p&gt;But seriously - In this couple of weeks I'll proudly present you :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All of my failures,&lt;/li&gt;
&lt;li&gt;All of my successes,&lt;/li&gt;
&lt;li&gt;Process of creating project (all-life-cycle),&lt;/li&gt;
&lt;li&gt;Hardware &amp;amp; Software Requirements,&lt;/li&gt;
&lt;li&gt;Testing libraries/Tools used,&lt;/li&gt;
&lt;li&gt;IDE's used,&lt;/li&gt;
&lt;li&gt;Tools (other then IDE's) used,&lt;/li&gt;
&lt;li&gt;Programming Language used,&lt;/li&gt;
&lt;li&gt;Programming Language libraries used,&lt;/li&gt;
&lt;li&gt;And much, much, more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Stay tuned :) Soon new post :)&lt;/p&gt;</content><category term="DSP2017"></category><category term="biking-endorphines"></category></entry><entry><title>How to make your own Blog using Pelican Python Static-sites generator engine.</title><link href="http://witkowskibartosz.com/blog/how-to-create-own-blog.html" rel="alternate"></link><published>2017-03-01T00:00:00+01:00</published><updated>2017-03-01T00:00:00+01:00</updated><author><name>Witkowski Bartosz</name></author><id>tag:witkowskibartosz.com,2017-03-01:/blog/how-to-create-own-blog.html</id><summary type="html">&lt;p&gt;A word of introduction before we go to 'tutorial' part.
If you want to go to the tutorial part right-away - please use &lt;a href="#make-blog-using-pelican"&gt;Making Blog using Pelican&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I've been struggling on how to begin my own blog (which post will be best) and then found out, that I'm thinking about …&lt;/p&gt;</summary><content type="html">&lt;p&gt;A word of introduction before we go to 'tutorial' part.
If you want to go to the tutorial part right-away - please use &lt;a href="#make-blog-using-pelican"&gt;Making Blog using Pelican&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I've been struggling on how to begin my own blog (which post will be best) and then found out, that I'm thinking about re-creating blog-engine or using existing.&lt;/p&gt;
&lt;p&gt;So after starting to inspect what type of engine's for blogs there are - I've got my "lightbulb" - Why not use this as a post ?&lt;/p&gt;
&lt;p&gt;I've even see this as type of "inception" - to post about posting blog :) .&lt;/p&gt;
&lt;p&gt;And so we begin our adventure.&lt;/p&gt;
&lt;h1&gt;Types of Blog-Engines and Questions to Blog-Readers.&lt;/h1&gt;
&lt;p&gt;There are two types of blog-engines - &lt;code&gt;dynamically generated&lt;/code&gt; and &lt;code&gt;static-html-generators&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Based on what purpose and your preference, you pick one of those.&lt;/p&gt;
&lt;p&gt;You have to ask your-self few questions to know which type of engine and blog-type you'll need.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Do you want to write your blog (almost) without using internet ?&lt;/p&gt;
&lt;p&gt;If you want to create your posts for blog at your "spare" time and when you have time upload them to server, then definitely you should pick the &lt;code&gt;static-html-generators&lt;/code&gt; type.&lt;/p&gt;
&lt;p&gt;After writing article for blog using ".rst" (reStructured) or ".md" (Markdown) file, you will generate html files and push them to server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do you have finance for keeping server that uses some programming language (i.e. c#, java, php, python) ?&lt;/p&gt;
&lt;p&gt;Depending on what type of language you pick, you may find yourself in a problem of too-expensive server for your usage, or you may have to use your own ISP provider with your hardware at your home. (VPS is also an option)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do you have time for maintaining own blog-engine ?&lt;/p&gt;
&lt;p&gt;Did you know, that the most popular blog-engine called "wordpress" has it's own &lt;a href="https://www.cvedetails.com/vulnerability-list/vendor_id-2337/product_id-4096/"&gt;vulnerability page&lt;/a&gt;  with different types of vulnerabilities ? It means that as soon as a patch for those vulnerabilities is available, you OUGHT TO upgrade your wordpress to this "patched" version ?
If you still going to use WP than please have a few minutes and get familiar with &lt;a href="https://hackertarget.com/attacking-wordpress/"&gt;THIS LINK&lt;/a&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do you like Markdown/reStructured/ASCIDoc/etc?&lt;/p&gt;
&lt;p&gt;Both &lt;code&gt;static-html-generators&lt;/code&gt; and &lt;code&gt;dynamically generated&lt;/code&gt; can be used for writing your posts in those languages for plain-text-formatting.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Why not to try static-generator for blog-posts ?&lt;/p&gt;
&lt;p&gt;I admit - this blog is created using only VIM, bash terminal and Pelican python static-html-generator. I've given a try and for now it's working for me.
Maybe after-while I'll change my decision ? But right-now I'm happy with how this system works. It needs some tweaks here and there, but it's more cheap-maintainable and easy-to-use then other I've used before.&lt;/p&gt;
&lt;p&gt;But as usual - that's only my opinion - yours may vary depending on preferences.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;Why Pelican ?&lt;/h1&gt;
&lt;p&gt;In case of python static-site generators, there are only few of them, that you may use. I've found Pelican best fitting my needs. Below are Dis-Advantages for Pelican:&lt;/p&gt;
&lt;p&gt;Advantages of Pelican:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Great amount of &lt;a href="https://github.com/getpelican/pelican-themes"&gt;themes&lt;/a&gt; that you can shuffle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Great amount of &lt;a href="https://github.com/getpelican/pelican-plugins"&gt;plugins&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Python expansibility.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using both Markdown, reStructured files for writing content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Quick-Starter script that helps creating initial setup for your blog.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using Fabric for deployment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add Disqus to your Posts is super-easy - just add "DISQUS_SITENAME" and set at administration of DISQUS website on which you'll use DISQUS and off-you-go :)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages of Pelican:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Some themes may be complicated and not explained enough for a "quick" shuffle  - you may occur some errors upon changing theme.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Some Extensions need to be also set at pelicanconf instead of theme-config.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div id='make-blog-using-pelican'&gt;&lt;/div&gt;

&lt;h1&gt;Making Blog using Pelican&lt;/h1&gt;
&lt;h5&gt;1. Installation of python package:&lt;/h5&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pip install pelican
pip install markdown &lt;span class="c1"&gt;# Only if you intent to use Markdown&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h5&gt;2. Setup pelican using quick-start script build-in with pelican:&lt;/h5&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pelican-quickstart
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;You'll answer questions and get a standard setup with name of blog and setup for publishing. If needed help, check at : 
&lt;a href="http://docs.getpelican.com/en/stable/install.html#kickstart-your-site"&gt;Kickstart-Your-Site&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;3. Go to directory you setup in quick-start guide. Go to directory "content" and place a file like "my_first_post.md" with following:&lt;/h5&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MyFirst&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="n"&gt;Title&lt;/span&gt;
&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2017&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pelican&lt;/span&gt;

&lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;myfirstpost&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h5&gt;4. Go back to pelican directory and :&lt;/h5&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;make devserver
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Which will use created pages in content directory and startup a development-type page at your localhost with port 8000 &lt;a href="http://localhost:8000"&gt;page&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Using Themes&lt;/h1&gt;
&lt;p&gt;To make use of themes with Pelican you need to: &lt;/p&gt;
&lt;div id="using_themes_1"&gt;&lt;/div&gt;

&lt;h5&gt;1. Clone pelican-themes repository : &lt;code&gt;git clone --recursive https://github.com/getpelican/pelican-themes /data/pelican-themes&lt;/code&gt;&lt;/h5&gt;
&lt;p&gt;&lt;div id="using_themes_2"&gt;&lt;/div&gt;&lt;/p&gt;
&lt;h5&gt;2. Clone pelican-plugins repository : &lt;code&gt;git clone --recursive https://github.com/getpelican/pelican-plugins /data/pelican-plugins&lt;/code&gt;&lt;/h5&gt;
&lt;p&gt;&lt;div id="using_themes_3"&gt;&lt;/div&gt;&lt;/p&gt;
&lt;h5&gt;3. Setup theme with it's description that should be in "README.md" or other similar file.&lt;/h5&gt;
&lt;h1&gt;How to use this blog's theme ?&lt;/h1&gt;
&lt;p&gt;In this particular blog I've used &lt;code&gt;pelican-bootstrap3&lt;/code&gt; theme. I've picked this theme, because it supports responsiveness to changing window size(you can resize your window and content will not be cut-out in some strange way).&lt;/p&gt;
&lt;p&gt;To setup this Theme I had to make few steps (necessary):&lt;/p&gt;
&lt;h5&gt;1. Clone thems &amp;amp; plugins ( as presented in &lt;a href="#using_themes_1"&gt;#1&lt;/a&gt; &amp;amp; &lt;a href="#using_themes_2"&gt;#2&lt;/a&gt; )&lt;/h5&gt;
&lt;h5&gt;2. Add to &lt;code&gt;pelicanconf.py&lt;/code&gt; :&lt;/h5&gt;
&lt;div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;PLUGIN_PATHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/data/pelican-plugins&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;PLUGINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;i18n_subsites&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;THEME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/data/pelican-themes/pelican-bootstrap3&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;JINJA_ENVIRONMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;extensions&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;jinja2.ext.i18n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/div&gt;

&lt;h5&gt;3. Re-build blog using:&lt;/h5&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;make html
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Where is my content generated ??&lt;/h1&gt;
&lt;p&gt;It's at the &lt;code&gt;OUTPUT_PATH&lt;/code&gt; which may be setup at &lt;code&gt;pelicanconf.py&lt;/code&gt; if you set different output directory than default - meaning &lt;code&gt;output/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;All Settings description can be found at &lt;a href="http://docs.getpelican.com/en/stable/settings.html"&gt;settings&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Thanks :)&lt;/h1&gt;
&lt;p&gt;That's all. Let me know in comments below what do you think about this blogging solution?&lt;/p&gt;
&lt;p&gt;Do you think static-generated sites using a Pelican or other engine is your thing ?&lt;/p&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.pydanny.com/choosing-a-new-python-based-blog-engine.html"&gt;[1]&lt;/a&gt; PyDanny's Choosing Blog Post.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/Python/comments/2hqvng/pythonbased_blogging_software/"&gt;[2]&lt;/a&gt; Reddit's post about blogging software comparison&lt;/p&gt;
&lt;p&gt;&lt;a href="https://wiki.python.org/moin/PythonBlogSoftware"&gt;[3]&lt;/a&gt; Python Blogging Software at python.org&lt;/p&gt;
&lt;p&gt;&lt;a href="http://docs.getpelican.com/en/stable/"&gt;[4]&lt;/a&gt; Pelican's Documentation Page.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.pelicanthemes.com/"&gt;[5]&lt;/a&gt; Pelican's Themes.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/getpelican/pelican"&gt;[6]&lt;/a&gt; Github Pelican Source-Code&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nafiulis.me/making-a-static-blog-with-pelican.html"&gt;[7]&lt;/a&gt; Nafiulis more-comprehensive post about making blog using Pelican.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet"&gt;[8]&lt;/a&gt; Markdown Cheat-Sheet at Github&lt;/p&gt;
&lt;h1&gt;What's next ?&lt;/h1&gt;
&lt;p&gt;Well ... you don't know what future may give you. I hope to solve few problems I've found while writing this post and creating my first blog using Pelican:&lt;/p&gt;
&lt;h5&gt;1. A code-box that can be copy-pasted using one-click of button (maybe some plugin? )&lt;/h5&gt;
&lt;h5&gt;2. Theme I've used does not support natively my native language, so I'm planning to extend this theme and maybe fork it within github.&lt;/h5&gt;
&lt;h5&gt;3. New post in next Wednesday :) Stay Tuned :)&lt;/h5&gt;</content><category term="python"></category><category term="pelican"></category></entry></feed>