Bye bye vim powerline, hello airline

0

It is quite a pain to have some nice status line with vim.
For this, until now, I was using the powerline module, that was cool, but has major drawbacks.

Fonts replacement

You need to patch or replace your default system fonts to be able to see the nice little “icons” in that status line.
You can do this by replacing your default font, or patch it with powerline-fonts.
And if you connect remotely, your local system also needs to be patched ortherwise you’ll get some horrible results.

Really slow

Its slowness is due to the fact that each time you load it, it will load/create an instance of python (so it requires vim7.4+ wiht python support compiled in!).

The replacement: vim-airline

I found about vim-airline in the README on the github of vim-powerline.

It is easy to install, does not require a patch of your system fonts, and allows you to use unicode for the status bar which is, visually, nearly like the powerline version.

It supports a lot of extensions, especially one that I didn’t know, vim-bufferline, for example. It shows the name of the file corresponding to the buffer you have in the statusbar (can also be shown on the command line).

So to install it, it’s quite straightforward, especially if you use NeoBundle or Vundle. Just add a Bundle 'bling/vim-airline' in your .vimrc file, and run :BundleInstall to update you repository.

To make it even nicer, even if you haven’t installed the powerline font patches, you can add the following to your .vimrc:

if !exists(‘g:airlinesymbols’)
let g:airline
symbols = {}
endif
let g:airlineleftsep = ‘»’
let g:airlineleftsep = ‘?’
let g:airlinerightsep = ‘«’
let g:airlinerightsep = ‘?’
let g:airlinesymbols.linenr = ‘?’
let g:airline
symbols.linenr = ‘?’
let g:airlinesymbols.linenr = ‘¶’
let g:airline
symbols.branch = ‘? ‘
let g:airlinesymbols.paste = ‘?’
let g:airline
symbols.paste = ‘Þ’
let g:airlinesymbols.paste = ‘?’
let g:airline
symbols.whitespace = ‘?’

Combining jQuery Mobile and Flask-WTF may give you headaches, or why dashes suck in Python variable names

0

I thought developing using Flask on the backend and using jQuery on the front-end (navigator) would be quite easy. In fact it is, but there are some small traps that can take you time to resolve.

A regular case would be, when developing a form, to use Flask with WTForms (Flask-WTF to the rescue!). No problem, you end up with some Jinja2 templates like the following:

<form action="{{url_for('setup')}}" method="POST">
 {{form.channel}}
[...]

Here, you’re converting the variable “channel” which comes from a class defined in the Python Flask code, and thanks to WTForms will convert it to an HTML Select Box. You can also add arguments to that, which will be converted automatically to a pair key/value, for example, you can set {{form.channel(class=’foobar’)}}, which will translate in HTML to:

<select class="foobar" name="channel" [...]

The problem begins when you want to use the themes from jQuery, which are named like “data-theme”. Notice that cool dash (‘-’)! It prevents you from using the same syntax in Jinja2, as you can’t directly use dashes in variable names. Hopefully, Karol Kuczmarski gave me the answer in the WTForms related Google Group:

{{ form.channel(**{'data-theme': 'b'}) }}

Book Review: Tactics Time! 1001 Chess Tactics from the Games of Everyday Chess Players

0

1001tacticsI’ve been subscribed to Tim Brennan’s newsletter (sent out every week) for quite some time now, so when he wrote this cool book on chess tactics, I was really delighted.  I was even more delighted when I saw that it is written in collaboration with Anthea Carson. All my kids know her for her animal chess book and specifically for her penguin opening that makes them laugh every time they see it.

Tactics Time is a nicely formatted Kindle book (but you don’t need to have a Kindle tablet, you can use the android app which works really well), where you will find the exercises and the answers on each next page, which makes it really practical for reviewing the answer (no need to go to the end of the book to find the answer, if you didn’t figure it out :-) For each solution, an explanation is given to help remember which tactics it relates to.

What I also liked was that the exercises were not invented, but from real tournaments, so these positions are possible in real life, which is really a plus.

Fail2ban Configuration for NGINX anomalies

Fail2ban is a really cool log analyzer (mostly) that can block ips using several different methods (iptables, ipfw, ip route blackhole, etc.). The problem is that you have to define filters (regexes in fact) that will trigger the ban for each service, because each one has a different way to report anomalies. There are not so much given examples on the official wiki. On other websites I couldn’t find anything about nginx filters. Even worse, several websites report that you can use the filters defined  for Apache2, which is false, they will NOT work, the logs are very different.

For example, here is a trace for a non existent requested resource:

2011/12/29 16:13:33 [error] 3212#0: *241787 open() "/opt/foo/default/admin/phpmyadmin/index.php" failed (2: No such file or directory), client: 58.19.239.205, server: , request: "GET //admin/phpmyadmin/index.php HTTP/1.1", host: "88.191.135.71"

So, to be able to detect such hack tentative and block it, create a file named nginx-noscript.conf, and put:

[Definition]
failregex = open\(\) "/\S*(\.php|\.asp|\.exe|\.pl)\S*" failed.*client: <HOST>,.*
ignoreregex =

Then, add its definition in an entry in the /etc/fail2ban/jail.conf:

[nginx]
enabled = true
port = http,https
filter = nginx-noscript
logpath = /var/log/nginx*/*error.log
maxretry = 6

Here, if there are more than 6 occurences of a failed 404 request in less than 600 seconds (the default value, modifiable with the ‘findtime’ variable), the ip will be added to the ban list.

pdf-screen

New version of chess PGN to TeX to PDF converter

OK, I’m shameful. After fighting with Scid’s exporter, and then correcting bugs in pgn2ltx’s source, I finally decided to take a look at that PGN file format. And guess what? It’s already composed of FEN notation. And guess what? that super-über cool new skaknew module for LaTeX gets its input as FEN!!

(more…)

Updated mate-in-one document, now includes chess coordinates

Update: A new updated version of the PDF is available, which includes which side to play.

After a request to have coordinates on the board, to be able to write answers (a really nice idea, especially that Ido begins writing), I noticed I couldn’t do it so easily, because the LaTeX module (chess12) didn’t support that. What a disappointment!

And the only way I had for converting from PGN to TeX was through Scid (still cool, still being developed), but supporting only exports to TeX with chess12 module. Fortunately, Dirk Baechle wrote a tool to convert directly from PGN format to TeX, using his tool pgn2ltx. That tool, written in C++ hasn’t been updated since 2003, so after a small patch to the source, it worked!

And the best part, is that it generates TeX files for the skak module, the best alternative to the old, dead chess12 module.

(more…)

Auto-provisioning with Asterisk and ST2030 Technicolor/Thomson phones

An introduction to the ST2030

The ST2030 is one of the few SIP phones distributed by Thomson (now changed name to Technicolor). In fact there are only 2 models: the ST2020, and the ST2030, and also a new one, the TB30, which is the successor to the ST2030. The ST2030 is supposed to have an End-of-Life set to the end of this year (2010), but I read that its EOL has been extended to the end of 2012.
In my personal experience, I think the ST2030 has the best price/functionalities/quality ratio. It has features like:

  • PoE (Power over Ethernet).
  • Headphone plug with a button on the phone to pickup with the headphone (or if you have a compatible headphone, pickup directly with a button on the headphone).
  • XML based Directory support, that you can interface with a remote HTTP server.
  • 4 differents lines/profiles (but not at the same time).
  • BLF (Busy Lamp Fields) to monitor other’s phone status (if they are using their phone, and even possibility to intercept a call).
  • Full compatibilty with Asterisk (tested on Asterisk 1.6+ and 1.8+).
  • Auto-provisioning with support for TFTP but also for HTTP/HTTPS, which simplifies quite a lot the provisioning configuration.

In this document, we’ll see the auto-provisioning process through DHCP+HTTP.

(more…)

How to make the simplest unittests in Python

Testing your code is nearly a requirement (even more so in Ruby). Unittests are now the most vital elements for evaluating the quality/viability of a project.
I was a little jealous of Ruby where you don’t have so much to write to implement unittests. Here is a simple example:

1
2
3
4
5
6
7
8
9
require "mymodule"
require "test/unit"
 
class TestMyModule &lt; Test::Unit::TestCase
 
  def test_simple
     assert_equal(1, 1 )
  end
end

Now, using Nose, you can get even shorter code. If you do standard Python projects, you’ll use a setup.py file. To use nose, you do not even need to specify the path where to find the tests, just add two lines (tests_require and test_suite) to call nosetest:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from setuptools import setup, find_packages
import sys, os
import mymodule
 
version = mymodule.__version__
 
setup(name='myproject',
      version=version,
      description="Module to display blah blah blah.",
      long_description=""" """,
      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
      keywords='mymodule foobar',
      author='Luc Stepniewski',
      author_email='l...@gradstein.info',
      url='',
      license='GPL',
      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
      include_package_data=True,
      tests_require='nose',
      test_suite='nose.collector',
      zip_safe=False,
      install_requires=[
          # -*- Extra requirements: -*-
          'simplejson',
      ],
      entry_points="""
      # -*- Entry points: -*-
      [console_scripts]
      mymodule = mymodule.mainmodule:main
      """,
      )

Now, to add tests, you just have to create a directory named tests (in the root of your project, where your setup.py resides, and then add a python file()s. No need to add a __init__.py to set the directory as a module. Now just add simple python files, like my-tests.py :

1
2
3
4
5
6
7
8
9
10
11
import mymodule
 
class TestAstInfoCli(object):
    def setup(self):
        pass
 
    def teardown(self):
        pass
 
    def test_annuaire_inverse(self):
        assert 1 == 1

As you can see, no need to import anything for doing unittests, not even the standard python unittest module! That’s better than ruby! The downside of this is that nose is an ‘external’ package, so you’ll have to install it first (or set it as a dependency in your setup.py file, as shown above).

If you don’t use a setup.py, you can call nose directly from the command line, with ‘nosetest’.

Now, let’s find an equivalent to the really cool rspec ruby module!

Default behaviour in implementation of STOMP protocol in RabbitMQ with python

Why STOMP?

Why STOMP, and not directly AMQP, as I’m using RabbitMQ. No real reason, but the fact that there are less dependencies on a STOMP client, as it’s just a socket with text sent.

Implementations

There are several implementations of the STOMP protocol for Python. The module I chose is python-stomp (version 0.2.9), from Benjamin W. Smith. It’s simple and easy to understand.

Simple Code Examples

sto_send.py:

1
2
3
4
5
6
from stompy.simple import Client
 
stomp = Client(host='rabbitmq2')
stomp.connect(username='guest',password='noneofyourbusiness')
stomp.put('Thomas est une b*te à Tetris...', destination='/queue/jeuvideo')
stomp.disconnect()

sto_receive.py:

1
2
3
4
5
6
7
8
9
10
11
12
from stompy.simple import Client
 
stomp = Client(host='rabbitmq2')
stomp.connect(username='guest',password='noneofyourbusiness')
stomp.subscribe('/queue/jeuvideo')
message = stomp.get()
 
print message.body
 
#stomp.ack(message)
stomp.unsubscribe('/queue/video')
stomp.disconnect()

Everything is working fine, when launching sto_receive.py, I receive the message. But when I launched several receivers, I noticed, that ONLY ONE programs received the message! After some research, I found the answer: As documented in the RabbitMQ wiki, the default exchange is ‘direct’:

[...]when messages leave a queue for a consumer, they are not duplicated. One message, sitting on a queue, is delivered to only one of the available consumers. [...] If there are multiple clients, all SUBSCRIBEing to the same queue, then there will be multiple consumers all on the same queue, leading to round-robin delivery to those clients.

There is an explanation on how to change the behaviour, by changing the exchange type, and some of particular bits (like the id). I even found an example of modification for use in the equivalent STOMP Ruby module.

Here are the modifications. The good news is that there is no need to patch the stompy module, as the author provided the possibility to pass arbitrary parameters to the headers by the use of the ‘conf’ variable.

The important points are:

  • You need to define an exchange of type amq.topic
  • You need to set an id, which is different for each client
  • As you’re using topics, you’ll have to specify a routing_key

sto_receive.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from stompy.simple import Client
import uuid
 
unique_id = uuid.uuid4()
 
stomp = Client(host='rabbitmq2')
stomp.connect(username='guest',password='nonononono')
 
stomp.subscribe('',
                conf={'exchange': 'amq.topic',
                      'routing_key':'x.#',
                      'id': unique_id,
                      })
 
# Wait for a message to appear
while 1:
    message = stomp.get()
    print message.body
 
#stomp.ack(message)
stomp.unsubscribe('',conf={'id': unique_id})
stomp.disconnect()

sto_send.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from stompy.simple import Client
 
 
 
stomp = Client(host='rabbitmq2')
stomp.connect(username='guest',password='nonononono')
 
 
for i in range(10000):
 stomp.put('Thomas est une b*te au Tetris...', destination='x.y',
          conf={'exchange':'amq.topic',
                #  'routing_key':'x.y'
                })
 
stomp.disconnect()

Puppet: Files found in modules without specifying ‘modules’ in file path will be deprecated in the next major release

DEPRECATION NOTICE: Files found in modules without specifying ‘modules’ in file path will be deprecated in the next major release.

If you get this warning in your puppet logs, you should take action (only if you don’t have any Puppet agent with a version <= 0.24) and modify all you references to file resources.
For example, if you have a module named 'ssh', normally, up to puppet 0.25 you would reference a file to it as:

source => ["puppet:///ssh/authorized_keys",]

But now, you need to insert a ‘module’ identifier in between like this:

source => ["puppet:///modules/ssh/authorized_keys",]

Just a small note: It seems that the templates do not need any modification.

Go to Top