Improve everyday.

Using the right pip for your Python version

|

Context

When you install several versions of python on your machine, there might be some mixed issues when using pip.

For example, when using pip3, you see that the requirements are already satisfied, but for python2.7 :

tonio@mythe ~ » pip3 install --user neovim
Requirement already up-to-date: neovim in /usr/local/lib/python2.7/dist-packages

Solution

Run the python -m pip command to execute the right pip :

python -m pip install --user neovim
python3 -m pip install --user neovim

Create patches from commits and apply them

|

Create .patch files from commits

git format-patch \
    -k \
    -o $OUTPUT_DIR \
    REV1..REV2

Creates .patch files per commit, the options are:

  • -k: keep the commit message (do not add [PATCH] to it)
  • -o $OUTPUT_DIR: the patch files are written to this dir
  • REV1..REV2: commits ranging from REV1 (excluded) to REV2 (included) are used to created patches.

Example

git format-patch -k -o my_patches 79bfe71..b83f760

Apply .patch files

Checking for conflicts

You can check that the patch can be safely applied with:

git apply --check commit.patch

If no output, this can be applied without any conflicts.

Merging patch

git am -3 commit.patch

This will apply the patch, adding the commit using the info found in the file to your current history.

In case of conflicts, the same tool as for merge conflicts will be available.

Beautiful logging in Python

|

The logging module

Documentation

This module is extremely useful and has many unknown features.

Useful features (to be completed)

LogRecord attributes

  • Every message from the message is an object of type LogRecord.
  • This gives us access to very useful information, here are some of them:
Name Format Description
asctime %(asctime)s Human-readable time when the LogRecord was created. By default this is of the form ‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).
levelname %(levelname)s Text logging level for the message (‘DEBUG’, ‘INFO’, ‘WARNING’, ‘ERROR’, ‘CRITICAL’).
filename %(filename)s Filename portion of pathname.
lineno %(lineno)d Source line number where the logging call was issued (if available).

Source: LogRecord-attributes

Defining loggers from yaml file

Instead of going through a long list of calls to the logging API, configuring your logger can be done from files.

YAML example

logging_conf.yaml

version: 1                                                                               
disable_existing_loggers: False                                                          
formatters:                                                                              
    simple:                                                                              
        format: "[%(asctime)s]%(name)s %(levelname)s(%(module)s %(lineno)d): %(message)s"
        datefmt: "%Z %Y-%m-%d %H:%M:%S"                                                  
                                                                                         
handlers:                                                                                
    console:                                                                             
        class: logging.StreamHandler                                                     
        level: INFO                                                                      
        formatter: simple                                                                
        stream: ext://sys.stdout                                                         
                                                                                         
loggers:                                                                                 
    my-logger:                                                                            
        level: INFO                                                                      
        handlers: [console]                                                              
        propagate: no                                                                    

main.py

import yaml
import logging
import logging.config
with open("logging_conf.yaml") as f:                   
    logging.config.dictConfig(yaml.safe_load(f.read()))
LOGGER = logging.getLogger("my-logger")

LOGGER.info("Bonjour !")

Output:

$ python main.py

[CEST 2017-10-24 14:03:13]my-logger INFO(main 8): Bonjour !

Create a patch from a pull request

|

Bitbucket: create a git patch from a pull request

To create a patch from a pull request, so that the branch can be deleted, and the changes can be merged later if needed

curl -u user:password https://bitbucket.org/api/2.0/repositories/{user}/{repo}/pullrequests/{pull_no}/patch -L -o name.patch

You can then link the .patch file in a new pivotal ticket for example.

To apply the patch later, simply use

git apply name.patch

Reference

SSH config

|

This tip has three goals:

  • make ssh command shorter (ssh alex instead of ssh alex@alexComputer)
  • avoid having to type password when using ssh
  • forward you ssh keys so that you can use them while on another machine

Config file

Host alex
    HostName alexComputer
    User alex
    ForwardAgent yes

Host nick
    HostName nickComputer
    User nick
    ForwardAgent yes

Write this to .ssh/config.

Allow your ssh key on remote machines

For each machine you want to access, run the following command:

ssh-copy-id -i <path-to-my-key> <host>

In our case:

ssh-copy-id -i ~/.ssh/id_rsa alex
ssh-copy-id -i ~/.ssh/id_rsa nick

Note: since ~/.ssh/id_rsa is actually the default path for the ssh key, we can just use ssh-copy-id <host>

Check that agent forwarding works

SSH on one machine, and type SSH on one machine, and type ssh -T git@github.com, this should show you your Github username and not the host’s one. If this does not work, go back on your machine and type ssh-add -L, if you get no identity is available, try ssh-add .ssh/id_rsa and it should now work.