<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Andrea Grandi</title>
    <description>The latest articles on Forem by Andrea Grandi (@andreagrandi).</description>
    <link>https://forem.com/andreagrandi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F69129%2F5a8bd496-2303-4ea4-a9f0-da4ad669d4a6.jpeg</url>
      <title>Forem: Andrea Grandi</title>
      <link>https://forem.com/andreagrandi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andreagrandi"/>
    <language>en</language>
    <item>
      <title>Python: it is now() time to migrate from utcnow()</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Wed, 17 Jul 2024 16:02:52 +0000</pubDate>
      <link>https://forem.com/andreagrandi/python-it-is-now-time-to-migrate-from-utcnow-519c</link>
      <guid>https://forem.com/andreagrandi/python-it-is-now-time-to-migrate-from-utcnow-519c</guid>
      <description>&lt;p&gt;This morning I randomly found this post from &lt;strong&gt;Miguel Grinberg&lt;/strong&gt;: &lt;a href="https://blog.miguelgrinberg.com/post/it-s-time-for-a-change-datetime-utcnow-is-now-deprecated" rel="noopener noreferrer"&gt;It's Time For A Change: datetime.utcnow() Is Now Deprecated&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The main point is that Python &lt;code&gt;utcnow()&lt;/code&gt; method is &lt;strong&gt;not timezone aware&lt;/strong&gt;, and &lt;strong&gt;Python 3.12 is deprecating it&lt;/strong&gt;. Therefore, you should start migrating your code to use &lt;code&gt;now()&lt;/code&gt; instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current state until Python 3.11
&lt;/h2&gt;

&lt;p&gt;Until Python 3.11, the &lt;code&gt;utcnow()&lt;/code&gt; method returns a &lt;code&gt;datetime&lt;/code&gt; object, and you would use it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;835551&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue with this method is that &lt;strong&gt;it doesn't include timezone information&lt;/strong&gt;, so you can't be certain if the time is in UTC or not.&lt;/p&gt;

&lt;p&gt;(the post continues on my blog &lt;a href="https://www.andreagrandi.it/posts/python-now-time-to-migrate-from-utcnow/" rel="noopener noreferrer"&gt;https://www.andreagrandi.it/posts/python-now-time-to-migrate-from-utcnow/&lt;/a&gt; )&lt;/p&gt;

</description>
      <category>python</category>
      <category>utc</category>
      <category>utcnow</category>
      <category>timezone</category>
    </item>
    <item>
      <title>Cryptomator: end-to-end encrypt files in any cloud</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Sat, 13 Jul 2024 15:35:26 +0000</pubDate>
      <link>https://forem.com/andreagrandi/cryptomator-end-to-end-encrypt-files-in-any-cloud-54kc</link>
      <guid>https://forem.com/andreagrandi/cryptomator-end-to-end-encrypt-files-in-any-cloud-54kc</guid>
      <description>&lt;p&gt;If you are using a cloud storage service like &lt;strong&gt;Google Drive&lt;/strong&gt;, &lt;strong&gt;Dropbox&lt;/strong&gt;, &lt;strong&gt;OneDrive&lt;/strong&gt;, etc., you should be aware that &lt;strong&gt;your files are not encrypted by default&lt;/strong&gt;. This means that the cloud provider is able to access and, in some cases, even share them with third parties. In case your cloud provider gets hacked, your files could also be exposed to the public.&lt;/p&gt;

&lt;p&gt;To prevent this from happening, you can use a tool like &lt;a href="https://cryptomator.org" rel="noopener noreferrer"&gt;&lt;strong&gt;Cryptomator&lt;/strong&gt;&lt;/a&gt; to automatically encrypt your files before uploading them to the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;Cryptomator is a &lt;strong&gt;free&lt;/strong&gt; and &lt;strong&gt;open-source&lt;/strong&gt; software that allows you to create an encrypted vault on your computer where you can store your files. Once you have added your files to the vault, Cryptomator will encrypt them using strong encryption algorithms (256 bit AES).&lt;/p&gt;

&lt;p&gt;To be more clear, &lt;strong&gt;Cryptomator doesn't upload your files&lt;/strong&gt;. Your cloud provider application does:&lt;/p&gt;

&lt;p&gt;You write files to the Cryptomator vault -&amp;gt; Cryptomator encrypts them and writes them in a folder which is synced up to your cloud provider -&amp;gt; Your cloud provider application uploads the encrypted files to the cloud.&lt;/p&gt;

&lt;p&gt;When you want to access your files, you simply access them from your mounted vault and Cryptomator will automatically decrypt them for you...&lt;/p&gt;

&lt;p&gt;You can find the rest of this post here: &lt;a href="https://www.andreagrandi.it/posts/cryptomator-end-to-end-encrypt-files-in-cloud/" rel="noopener noreferrer"&gt;https://www.andreagrandi.it/posts/cryptomator-end-to-end-encrypt-files-in-cloud/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cryptomator</category>
      <category>encryption</category>
      <category>cloud</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Using pyenv to install Python and create a virtual environment</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Sun, 11 Oct 2020 10:21:26 +0000</pubDate>
      <link>https://forem.com/andreagrandi/using-pyenv-to-install-python-and-create-a-virtual-environment-2ang</link>
      <guid>https://forem.com/andreagrandi/using-pyenv-to-install-python-and-create-a-virtual-environment-2ang</guid>
      <description>&lt;p&gt;A few days ago &lt;a href="https://docs.python.org/3/whatsnew/3.9.html" rel="noopener noreferrer"&gt;Python 3.9.0&lt;/a&gt; has been released and I really wanted to test ist latest features (maybe I will do a separate post to talk about them) without messing my system with another Python version.&lt;/p&gt;

&lt;p&gt;To manage my Python versions I've been using &lt;a href="https://github.com/pyenv/pyenv" rel="noopener noreferrer"&gt;pyenv&lt;/a&gt; for a while and once configured, it's very easy to install a new Python version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make sure your pyenv is updated
&lt;/h2&gt;

&lt;p&gt;You should have at least &lt;strong&gt;pyenv 1.2.21&lt;/strong&gt; if you want to test Python 3.9.0&lt;/p&gt;

&lt;p&gt;In case you haven't updated it and you are using MacOS, you can do it with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew update &amp;amp;&amp;amp; brew upgrade pyenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;once installed you should see the latest version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pyenv --version
pyenv 1.2.21
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install Python 3.9.0
&lt;/h2&gt;

&lt;p&gt;To install Python 3.9.0 you only need &lt;code&gt;pyenv install 3.9.0&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pyenv install 3.9.0
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Downloading Python-3.9.0.tar.xz...
-&amp;gt; https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tar.xz
    Installing Python-3.9.0...
    python-build: use readline from homebrew
    python-build: use zlib from xcode sdk
    Installed Python-3.9.0 to /Users/andrea/.pyenv/versions/3.9.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Set Python 3.9.0 as the local version
&lt;/h2&gt;

&lt;p&gt;Now that the version you want has been installed, you need to tell pyenv you want to use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pyenv local 3.9.0
pyenv which python
/Users/andrea/.pyenv/versions/3.9.0/bin/python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find the rest of the tutorial on my blog &lt;a href="https://www.andreagrandi.it/posts/install-python-with-pyenv-create-virtual-environment-with-specific-python-version/" rel="noopener noreferrer"&gt;https://www.andreagrandi.it/posts/install-python-with-pyenv-create-virtual-environment-with-specific-python-version/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>development</category>
      <category>pyenv</category>
      <category>virtualenv</category>
    </item>
    <item>
      <title>How to deploy a static website to Github Pages using CircleCI</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Sun, 24 Feb 2019 21:11:31 +0000</pubDate>
      <link>https://forem.com/andreagrandi/how-to-deploy-a-static-website-to-github-pages-using-circleci-2bfe</link>
      <guid>https://forem.com/andreagrandi/how-to-deploy-a-static-website-to-github-pages-using-circleci-2bfe</guid>
      <description>&lt;p&gt;Since I created my blog with a static pages generator, I've been using TravisCI to automate the pages build and deployment.&lt;br&gt;
My desire to learn something new (we are using CircleCI at work, but I never configured it from scratch) and the recent news about&lt;br&gt;
TravisCI &lt;a href="https://blog.travis-ci.com/2019-01-23-travis-ci-joins-idera-inc" rel="noopener noreferrer"&gt;acquisition&lt;/a&gt; and employees &lt;a href="https://twitter.com/alicegoldfuss/status/1098604563664420865" rel="noopener noreferrer"&gt;layoff&lt;/a&gt;, led me to think about moving to a different service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Github Pages
&lt;/h2&gt;

&lt;p&gt;Every account on Github can use a special repository to publish static pages. In my case, since I have &lt;code&gt;github.com/andreagrandi&lt;/code&gt;, my special repository is&lt;br&gt;
named &lt;code&gt;github.com/andreagrandi.github.io&lt;/code&gt;. Once I publish my pages there, they will be accessible from &lt;code&gt;https://andreagrandi.github.io&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You will need to use the &lt;strong&gt;master&lt;/strong&gt; branch of the special repository directly and not the &lt;strong&gt;gh-pages&lt;/strong&gt; branch which is available to each repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  CircleCI
&lt;/h2&gt;

&lt;p&gt;CircleCI is a very flexible and powerful continuous integration tool, which is also &lt;strong&gt;free&lt;/strong&gt; for open source projects. As long as your static website is located on a public repository on Github, you won't have to pay anything to use it. In my case, the surce code of this website is available at &lt;a href="https://github.com/andreagrandi/andreagrandi.it" rel="noopener noreferrer"&gt;https://github.com/andreagrandi/andreagrandi.it&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;You can find the complete configuration at &lt;a href="https://github.com/andreagrandi/andreagrandi.it/blob/master/.circleci/config.yml" rel="noopener noreferrer"&gt;this address&lt;/a&gt;.&lt;br&gt;
The only value you won't find is &lt;strong&gt;GH_TOKEN&lt;/strong&gt;. You need to generate this token on Github, at this address: &lt;a href="https://github.com/settings/tokens" rel="noopener noreferrer"&gt;https://github.com/settings/tokens&lt;/a&gt;. Give it a nice description like "CircleCI deployment token", select &lt;strong&gt;repo&lt;/strong&gt; scope and finally click &lt;strong&gt;Generate token&lt;/strong&gt; button. This token will be used to &lt;code&gt;git push...&lt;/code&gt;&lt;br&gt;
your pages once they are built. Please remember to keep this token &lt;strong&gt;secret&lt;/strong&gt; and not to publish it anywhere.&lt;/p&gt;

&lt;p&gt;In my configuration you may notice that I'm using &lt;a href="https://blog.getpelican.com/" rel="noopener noreferrer"&gt;Pelican&lt;/a&gt; static websites generator, but apart from a few changes, the structure of the configuration should be very similar even if you use Jekill, Hugo etc... it doesn't really matter how you generate the pages, the &lt;strong&gt;deployment phase will be the same&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;You will notice that there is a complete bash script embedded in the CircleCI configuration. This script configures git, fetches the existing &lt;code&gt;andreagrandi.github.io&lt;/code&gt; repository,&lt;br&gt;
and sync the built pages with the existing ones (this avoid creating a commit which contains all the pages so it will contain just the added content). Once the commit is made, the script will finally push the changes to the repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Please note:&lt;/strong&gt; regardless of CircleCI settings, the deployment will only happens if we are pushing (or merging a pull request) to &lt;strong&gt;master&lt;/strong&gt; (&lt;code&gt;if [ "${CIRCLE_BRANCH}" = "master" ]; then&lt;/code&gt;) and it will actually commit and push pages only if there is something new to commit (&lt;code&gt;if git commit -m "CircleCI build $CIRCLE_BUILD_NUM pushed to Github Pages" ; then&lt;/code&gt;). For example if I'm just updating something in the CircleCI configuration, which doesn't change anything in the content, the pages won't be deployed again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;My first impression of CircleCI is that is faster than TravisCI and this means that I can publish my content more quickly. The possibility of using Docker containers as base image is really powerful and in more complex scenarios we can reproduce the building environment locally on our machine. If you have any advices about how to improve my build script, feel free to leave a comment here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; this post first appeared on my personal blog at &lt;a href="https://www.andreagrandi.it/posts/how-to-deploy-static-website-github-pages-circleci/" rel="noopener noreferrer"&gt;https://www.andreagrandi.it/posts/how-to-deploy-static-website-github-pages-circleci/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ci</category>
      <category>static</category>
      <category>website</category>
      <category>deploy</category>
    </item>
    <item>
      <title>PyCon X Italy: submit a talk for the Italian Python conference (Florence May 2nd - 5th)</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Thu, 03 Jan 2019 13:44:30 +0000</pubDate>
      <link>https://forem.com/andreagrandi/pycon-x-italy-submit-a-talk-for-the-italian-python-conference-florence-may-2nd---5th-16f0</link>
      <guid>https://forem.com/andreagrandi/pycon-x-italy-submit-a-talk-for-the-italian-python-conference-florence-may-2nd---5th-16f0</guid>
      <description>&lt;p&gt;Even this year, the Italian Python conference will be organised in &lt;strong&gt;Florence&lt;/strong&gt; and will take place between &lt;strong&gt;May 2nd and May 5th&lt;/strong&gt; included.&lt;/p&gt;

&lt;p&gt;It's an amazing opportunity to meet a lot of Python developers, listen to very interesting talks and visit one of the best cities in the world (I may be slightly biased on this last point :P )!&lt;/p&gt;

&lt;p&gt;Subjects range from pure &lt;strong&gt;Python&lt;/strong&gt;, &lt;strong&gt;PyData&lt;/strong&gt;, &lt;strong&gt;Machine Learning&lt;/strong&gt;, &lt;strong&gt;web&lt;/strong&gt;, &lt;strong&gt;DevOps&lt;/strong&gt;, &lt;strong&gt;security&lt;/strong&gt; and &lt;strong&gt;community&lt;/strong&gt; related talks and there will be a good number (usually they are the majority) of talks available in &lt;strong&gt;english language&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This event wouldn't be possible without our wonderful speakers: not just experts but especially &lt;strong&gt;first time speakers are warmly encouraged to submit a proposal&lt;/strong&gt; for the conference.&lt;/p&gt;

&lt;p&gt;If you are interested, you can find all the information on the official website &lt;a href="https://www.pycon.it/en/call-for-proposals/" rel="noopener noreferrer"&gt;https://www.pycon.it/en/call-for-proposals/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please &lt;strong&gt;hurry up&lt;/strong&gt; because the &lt;strong&gt;deadline is January 6th&lt;/strong&gt;!&lt;/p&gt;

</description>
      <category>python</category>
      <category>pycon</category>
      <category>conference</category>
    </item>
    <item>
      <title>Installing Python and virtualenv on OSX</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Wed, 19 Dec 2018 15:53:18 +0000</pubDate>
      <link>https://forem.com/andreagrandi/installing-python-and-virtualenv-on-osx-3llm</link>
      <guid>https://forem.com/andreagrandi/installing-python-and-virtualenv-on-osx-3llm</guid>
      <description>&lt;p&gt;Every time I need to install Python on OSX or whenever a colleague asks for help, I have to search fo the most updated instructions on Google, and every time I find different ways of doing the exact same thing.&lt;/p&gt;

&lt;p&gt;Tired of this, I decided to write down my own notes. Please note that I don't claim this to be the best way of installing Python on OSX. It works fine for me so use it at your own risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;To follow these instructions you need to at least have installed &lt;strong&gt;brew&lt;/strong&gt; on OSX. Please follow the instructions on the official website: &lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;https://brew.sh&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Python 3.7.x and Python 2.7.x
&lt;/h2&gt;

&lt;p&gt;Even if I strongly suggest to start every new project with Python 3 (since Python 2 will only be supported until the end of 2019), there may be use cases when version 2 is still required, so I will give you the instructions to install both.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing Python 3.7.x
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install Python 3 by default.&lt;/p&gt;

&lt;p&gt;....&lt;/p&gt;

&lt;p&gt;You can find the rest of the post on my blog: &lt;a href="https://www.andreagrandi.it/posts/installing-python-and-virtualenv-on-osx/" rel="noopener noreferrer"&gt;https://www.andreagrandi.it/posts/installing-python-and-virtualenv-on-osx/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>osx</category>
      <category>development</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why I mentor on Exercism.io</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Sun, 04 Nov 2018 14:00:00 +0000</pubDate>
      <link>https://forem.com/andreagrandi/why-i-mentor-on-exercismio-542j</link>
      <guid>https://forem.com/andreagrandi/why-i-mentor-on-exercismio-542j</guid>
      <description>&lt;p&gt;Exercism (&lt;a href="https://exercism.io" rel="noopener noreferrer"&gt;https://exercism.io&lt;/a&gt;) is a platform that has been created to help people improving their coding skills, thanks to the volunteers mentoring the students. There are tracks for almost all the popular languages and each track has coding test that the students can download, solve offline using their preferred editor, and test the solution against the provided unit tests. Once the solution is ready to be reviewed (or even if it's not complete but the student needs help), it can be submitted to the website and it will go in a queue where the first available mentor will pick it and start mentoring.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;service is free&lt;/strong&gt; to use for all the students and &lt;strong&gt;the mentors are all volunteers&lt;/strong&gt; (this doesn't mean that the platform doesn't have any costs. If you are curious about the resources needed to keep the platform alive, you can give a look at &lt;a href="https://www.reddit.com/r/Python/comments/9tugvn/exercismio_needs_python_mentors/e8zy5mq/" rel="noopener noreferrer"&gt;this answer on Reddit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When I found out about the platform, I decided to use it (as student) to &lt;strong&gt;improve my Go coding skills&lt;/strong&gt;. I must say that I've been learning a lot from the mentors and some of them are putting a lot of effort to give you all the possible advices to improve your coding style. In a single exercise once, I learnt at least five things about Go I didn't know before!&lt;/p&gt;

&lt;p&gt;I've been a Python developer (professionally) for the last 5 years, but I've never considered myself an "expert". I decided to give it a try with mentoring, because I felt I wanted to &lt;strong&gt;give something back to the community&lt;/strong&gt;, so I registered as mentor too and started mentoring in the Python track.&lt;/p&gt;

&lt;p&gt;The first surprise has been that mentoring other students, I was probably learning more than how much I was teaching. First of all, once you already know how to solve a problem, it's always interesting to look at other possible solutions. I've found sometimes that students were providing better (more concise and readable) solutions than mine. Last but not least, before advising someone about conding style or a more idiomatic solution, I always double check things from different sources. There is nothing wrong making mistakes, especially if you are learning... but it would be damaging for the student if I was teaching them something wrong, so I need to be sure about what I say. This of course makes me study, even the basic things, again and again and at the end of the day, my skills are better too.&lt;/p&gt;

&lt;p&gt;Once you join the mentors group, you are invited to a private Slack where you can count on the help of other mentors (we have channels for each track/language) or ask questions. So, if you are not sure about something, you can always ask around.&lt;/p&gt;

&lt;p&gt;If my story and experience convinced you, &lt;strong&gt;Exercism is looking for more mentors!&lt;/strong&gt; The more we have available, the less time the students have to wait in a queue to be mentored. You can find all the instructions at this address &lt;a href="https://mentoring.exercism.io/" rel="noopener noreferrer"&gt;https://mentoring.exercism.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: this post appeared first on my blog at &lt;a href="https://www.andreagrandi.it/posts/why-i-mentor-on-exercism/" rel="noopener noreferrer"&gt;https://www.andreagrandi.it/posts/why-i-mentor-on-exercism/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mentoring</category>
      <category>programming</category>
      <category>coding</category>
      <category>learning</category>
    </item>
    <item>
      <title>Creating a production ready API with Python and Django Rest Framework - part 1</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Tue, 01 May 2018 13:09:08 +0000</pubDate>
      <link>https://forem.com/andreagrandi/creating-a-production-ready-api-with-python-and-django-rest-framework---part-1-l34</link>
      <guid>https://forem.com/andreagrandi/creating-a-production-ready-api-with-python-and-django-rest-framework---part-1-l34</guid>
      <description>&lt;p&gt;The aim if this tutorial is to show how to create a production ready solution for a &lt;strong&gt;REST API&lt;/strong&gt;, using &lt;strong&gt;Python&lt;/strong&gt; and &lt;a href="http://www.django-rest-framework.org" rel="noopener noreferrer"&gt;Django Rest Framework&lt;/a&gt;. I will show you how to first create a very basic API, how to handle the authentication and permissions and I will cover deployment and hosting of images. The full source code of the tutorial is available at: &lt;a href="https://github.com/andreagrandi/drf-tutorial" rel="noopener noreferrer"&gt;https://github.com/andreagrandi/drf-tutorial&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary of the complete tutorial
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Create the basic structure for the API&lt;/li&gt;
&lt;li&gt; &lt;a href="https://www.andreagrandi.it/2016/10/01/creating-a-production-ready-api-with-python-and-django-rest-framework-part-2/" rel="noopener noreferrer"&gt;Add Authentication and POST
methods&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://www.andreagrandi.it/2017/03/12/creating-a-production-ready-api-with-python-and-django-rest-framework-part-3/" rel="noopener noreferrer"&gt;Handling details and changes to existing
data&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://www.andreagrandi.it/2017/08/17/creating-a-production-ready-api-with-python-and-django-rest-framework-part-4/" rel="noopener noreferrer"&gt;Testing the API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; Switching from Sqlite to PostgreSQL&lt;/li&gt;
&lt;li&gt; Hosting the API on Heroku&lt;/li&gt;
&lt;li&gt; Add an Image field and save images to S3&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Create the basic structure for the API
&lt;/h3&gt;

&lt;p&gt;For this tutorial I will assume you have correctly installed at least &lt;strong&gt;Python&lt;/strong&gt; (I will use Python 2.7.x), &lt;a href="https://pypi.python.org/pypi/virtualenv" rel="noopener noreferrer"&gt;&lt;strong&gt;virtualenv&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://virtualenvwrapper.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;&lt;strong&gt;virtualenvwrapper&lt;/strong&gt;&lt;/a&gt; on your system and I will explain how to create everything else step by step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; at the time of writing, the tutorial has been based on &lt;strong&gt;Django 1.10.1&lt;/strong&gt; and &lt;strong&gt;Django Rest Framework 3.4.7&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the main project structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir drf-tutorial
mkvirtualenv drf-tutorial
cd drf-tutorial
pip install django djangorestframework
django-admin.py startproject drftutorial .
cd drftutorial
django-admin.py startapp catalog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Data Model
&lt;/h3&gt;

&lt;p&gt;We will create the API for a generic products catalog, using a very simple structure (to keep things simple). Edit the file &lt;strong&gt;catalog/models.py&lt;/strong&gt; adding these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;unicode_literals&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DecimalField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decimal_places&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="n"&gt;max_digits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find the rest of the tutorial on my blog &lt;a href="https://www.andreagrandi.it/2016/09/28/creating-production-ready-api-python-django-rest-framework-part-1/" rel="noopener noreferrer"&gt;https://www.andreagrandi.it/2016/09/28/creating-production-ready-api-python-django-rest-framework-part-1/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>rest</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Using Python ipdb from Jupyter</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Wed, 25 Apr 2018 09:40:08 +0000</pubDate>
      <link>https://forem.com/andreagrandi/using-python-ipdb-from-jupyter-5g3f</link>
      <guid>https://forem.com/andreagrandi/using-python-ipdb-from-jupyter-5g3f</guid>
      <description>&lt;p&gt;&lt;em&gt;(this blog post originally appeared on my blog &lt;a href="https://www.andreagrandi.it/posts/using-python-ipdb-from-jupyter/" rel="noopener noreferrer"&gt;https://www.andreagrandi.it/posts/using-python-ipdb-from-jupyter/&lt;/a&gt; )&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If we try to use the usual ipdb commands from a Jupyter (IPython notebook)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ipdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;ipdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we will get a similar error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--------------------------------------------------------------------------
MultipleInstanceError                     Traceback (most recent call last)
&amp;lt;ipython-input-1-f2b356251c56&amp;gt; in &amp;lt;module&amp;gt;()
    1 a=4
----&amp;gt; 2 import ipdb; ipdb.set_trace()
    3 b=5
    4 print a
    5 print b

/home/nnn/anaconda/lib/python2.7/site-packages/ipdb/__init__.py in &amp;lt;module&amp;gt;()
    14 # You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
    15 
---&amp;gt; 16 from ipdb.__main__ import set_trace, post_mortem, pm, run, runcall, runeval, launch_ipdb_on_exception
    17 
    18 pm                       # please pyflakes

/home/nnn/anaconda/lib/python2.7/site-packages/ipdb/__main__.py in &amp;lt;module&amp;gt;()
    71         # the instance method will create a new one without loading the config.
    72         # i.e: if we are in an embed instance we do not want to load the config.
---&amp;gt; 73         ipapp = TerminalIPythonApp.instance()
    74         shell = get_ipython()
    75         def_colors = shell.colors

/home/nnn/anaconda/lib/python2.7/site-packages/traitlets/config/configurable.pyc in instance(cls, *args, **kwargs)
    413             raise MultipleInstanceError(
    414                 'Multiple incompatible subclass instances of '
--&amp;gt; 415                 '%s are being created.' % cls.__name__
    416             )
    417

MultipleInstanceError: Multiple incompatible subclass instances of TerminalIPythonApp are being created.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The solution is to use Tracer instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;IPython.core.debugger&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Tracer&lt;/span&gt;
&lt;span class="nc"&gt;Tracer&lt;/span&gt;&lt;span class="p"&gt;()()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Source: &lt;a href="http://stackoverflow.com/questions/35613249/using-ipdb-to-debug-python-code-in-one-cell-jupyter-or-ipython" rel="noopener noreferrer"&gt;http://stackoverflow.com/questions/35613249/using-ipdb-to-debug-python-code-in-one-cell-jupyter-or-ipython&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Getting latest Ubuntu AMI with Terraform</title>
      <dc:creator>Andrea Grandi</dc:creator>
      <pubDate>Tue, 24 Apr 2018 15:21:05 +0000</pubDate>
      <link>https://forem.com/andreagrandi/getting-latest-ubuntu-ami-with-terraform-33gg</link>
      <guid>https://forem.com/andreagrandi/getting-latest-ubuntu-ami-with-terraform-33gg</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was originally published on my own blog:&lt;/em&gt; &lt;a href="https://www.andreagrandi.it/posts/getting-latest-ubuntu-ami-with-terraform/" rel="noopener noreferrer"&gt;https://www.andreagrandi.it/posts/getting-latest-ubuntu-ami-with-terraform/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we need to create an EC2 resource on AWS using Terraform, we need to specify the AMI id to get the correct image.&lt;/p&gt;

&lt;p&gt;The id is not easy to memorise and it changes depending on the zone we are working one. On every new release the id changes again.&lt;/p&gt;

&lt;p&gt;So, how can we be sure to get the correct ID for our region, of the latest image available for a given Linux distribution?&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting latest Ubuntu AMI id
&lt;/h3&gt;

&lt;p&gt;In this example I will show how to get the ID for the latest version of Ubuntu 16.04 server, for the London region and create an EC2 instance using that ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;variable &lt;span class="s2"&gt;"aws_region"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; default &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eu-west-2"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c"&gt;# London&lt;/span&gt;

provider &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    region &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.aws_region&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    access_key &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"youraccesskey"&lt;/span&gt;
    secret_key &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"yoursecretkey"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

data &lt;span class="s2"&gt;"aws_ami"&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    most_recent &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true

    &lt;/span&gt;filter &lt;span class="o"&gt;{&lt;/span&gt;
        name   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;
        values &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    filter &lt;span class="o"&gt;{&lt;/span&gt;
        name   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"virtualization-type"&lt;/span&gt;
        values &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hvm"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    owners &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"099720109477"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# Canonical&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

resource &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    ami           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.aws_ami.ubuntu.id&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    instance_type &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;

    tags &lt;span class="o"&gt;{&lt;/span&gt;
        Name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"HelloUbuntu"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

output &lt;span class="s2"&gt;"image_id"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    value &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.aws_ami.ubuntu.id&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After we have initialised our script using &lt;strong&gt;terraform init&lt;/strong&gt; if we run it, we will get the AMI id and the instance will be created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜  example1$: terraform apply
data.aws_ami.ubuntu: Refreshing state...
aws_instance.web: Creating...
    ami:                          "" =&amp;gt; "ami-03998867"
    associate_public_ip_address:  "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    availability_zone:            "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    ebs_block_device.#:           "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    ephemeral_block_device.#:     "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    instance_state:               "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    instance_type:                "" =&amp;gt; "t2.micro"
    ipv6_address_count:           "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    ipv6_addresses.#:             "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    key_name:                     "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    network_interface.#:          "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    network_interface_id:         "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    placement_group:              "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    primary_network_interface_id: "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    private_dns:                  "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    private_ip:                   "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    public_dns:                   "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    public_ip:                    "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    root_block_device.#:          "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    security_groups.#:            "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    source_dest_check:            "" =&amp;gt; "true"
    subnet_id:                    "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    tags.%:                       "" =&amp;gt; "1"
    tags.Name:                    "" =&amp;gt; "HelloUbuntu"
    tenancy:                      "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    volume_tags.%:                "" =&amp;gt; "&amp;lt;computed&amp;gt;"
    vpc_security_group_ids.#:     "" =&amp;gt; "&amp;lt;computed&amp;gt;"
aws_instance.web: Still creating... (10s elapsed)
aws_instance.web: Still creating... (20s elapsed)
aws_instance.web: Still creating... (30s elapsed)
aws_instance.web: Creation complete (ID: i-0f58f8bd55b3a7e38)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

image_id = ami-03998867
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all we need to spin up an EC2 instance on AWS using latest Ubuntu image available.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
