Other articles

  1. How to deploy a static website to Github Pages using CircleCI

    Since I created my blog with a static pages generator, I've been using TravisCI to automate the pages build and deployment. My desire to learn something new (we are using CircleCI at work, but I never configured it from scratch) and the recent news about TravisCI acquisition and employees layoff, led me to think about moving to a different service.

    Github Pages

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

    You will need to use the master branch of the special repository directly and not the gh-pages branch which is available to each repository.


    CircleCI is a very flexible and powerful continuous integration tool, which is also free 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 https://github.com/andreagrandi/andreagrandi.it


    You can find the complete configuration at this address. The only value you won't find is GH_TOKEN. You need to generate this token on Github, at this address: https://github.com/settings/tokens. Give it a nice description like "CircleCI deployment token", select repo scope and finally click Generate token button. This token will be used to git push... your pages once they are built. Please remember to keep this token secret and not to publish it anywhere.

    In my configuration you may notice that I'm using Pelican 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 deployment phase will be the same.

    Deployment script

    You will notice that there is a complete bash script embedded in the CircleCI configuration. This script configures git, fetches the existing andreagrandi.github.io repository, 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.

    Please note: regardless of CircleCI settings, the deployment will only happens if we are pushing (or merging a pull request) to master (if [ "${CIRCLE_BRANCH}" = "master" ]; then) and it will actually commit and push pages only if there is something new to commit (if git commit -m "CircleCI build $CIRCLE_BUILD_NUM pushed to Github Pages" ; then). 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.


    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.

    read more


  2. Skipping tests depending on the Python version

    Sometimes we want to run certain tests only on a specific version of Python.

    Suppose you are migrating a large project from Python 2 to Python 3 and you know in advance that certain tests won't run under Python 3.

    Chances are that during the migration you are already using the six library. The six libraries have two boolean properties which are initialised to True depending on the Python version which is being used: PY2 when running under Python 2 and PY3 when running under Python 3.

    This library, combined with the skipIf method of unittest library can be used to easily skip tests when using Python 3:

    import six
    import unittest
    class MyTestCase(unittest.TestCase):
        @unittest.skipIf(six.PY3, "not compatible with Python 3")
        def test_example(self):
            # This test won't run under Python 3


    Thanks to my colleague Nicola for giving me the inspiration to write this post.

    read more


  3. Installing Python and virtualenv on OSX

    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.

    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.


    To follow these instructions you need to at least have installed brew on OSX. Please follow the instructions on the official website: https://brew.sh

    Installing Python 3.7.x and Python 2.7.x

    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.

    Installing Python 3.7.x

    brew install python

    This will install Python 3 by default.

    Installing Python 2.7.x

    brew install [email protected]

    This will install version 2 of Python.

    Add the Python locations to PATH

    Edit your .bashrc or .zshrc and add this:

    export PATH="/usr/local/opt/python/libexec/bin:/usr/local/bin:$PATH"

    You will need to close your terminal and reopen it for the changes to be applied. Once you have done it, you can verify if Python 3 and Python 2 have been installed correctly:

    python --version
    Python 3.7.1


    python2 --version
    Python 2.7.15

    Install virtualenv and virtualenvwrapper

    When working with Python, it's a good thing not to install packages system wide, but confine them in virtual environments. A good and well tested way of doing that is to use virtualenv (and its companion virtualenvwrapper) which makes the most common operations easier.

    pip install virtualenv
    pip install virtualenvwrapper

    Those (and only those) two packages will be installed system wide, because we will need them to be available outside of a virtual environment.

    Configure virtualenv

    Edit again your .bashrc (or .zshrc) and add these lines:

    export WORKON_HOME=~/.virtualenvs
    [ -f /usr/local/bin/virtualenvwrapper.sh ] && source /usr/local/bin/virtualenvwrapper.sh

    This will configure the default location where to store your virtual environments and will run a command every time you open a new terminal, to make sure virtualenvwrapper can work correctly.

    Test if the installed tools are working

    To make sure everything has been configured correctly, please close and reopen your terminal and let's try to create a new virtual environment:

    mkvirtualenv test

    which should output something like this:

    Using base prefix '/usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7'
    New python executable in /Users/andrea/.virtualenvs/test/bin/python3.7
    Also creating executable in /Users/andrea/.virtualenvs/test/bin/python
    Installing setuptools, pip, wheel...
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/predeactivate
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/postdeactivate
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/preactivate
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/postactivate
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/get_env_details
    (test) ➜  ~

    If you see something similar, it means that the virtual environment has been created correctly. Please note that by default this command will create an environment base on Python 3. Do you need to create one for Python 2? No problem, you just need to do the following:

    mkvirtualenv -p /usr/local/bin/python2 test

    which should output this:

    Running virtualenv with interpreter /usr/local/bin/python2
    New python executable in /Users/andrea/.virtualenvs/test/bin/python2.7
    Also creating executable in /Users/andrea/.virtualenvs/test/bin/python
    Installing setuptools, pip, wheel...
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/predeactivate
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/postdeactivate
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/preactivate
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/postactivate
    virtualenvwrapper.user_scripts creating /Users/andrea/.virtualenvs/test/bin/get_env_details
    (test) ➜  ~


    That's all you have to do to install and configure Python and virtualenv on OSX. If you have problems, comments or questions, feel free to leave a comment on this post.

    read more


Page 1 / 51 »