/dev/blah

things i want to remember, things i want to share

Développeur Python et adepte Linux depuis 2005, Core développeur Kivy, passionné par beaucoup trop de choses.
Profil Github gpg signature bitcoin address

Keyboard Kata

written by tshirtman, on 2/12/14 2:08 AM.

So i spent most of the evening copying texts on dactylotest, most of the time barely reading them, while listening to tv, to work on my typing speed and regularity, and it paid a little, for the first time, i passed the 70WPM mark, and i hit 60WPM most of the time, which is a progress from the 50WPM i considered normal not long ago.

70WPM

so yes, practice makes perfect…

Tip me if you like this :)

Using jinja2 outside of the web.

written by tshirtman, on 2/10/14 12:56 AM.

I may be the last person out there to do that, but i hadn’t actually gotten to that yet.

So here is the thing, sometime you want to produce a text file, with some complex structure, and string.format is not really up to the task, so you scratch your head and wonder what could be useful to… template an output.

Then a nice lib like jinja2 totally makes sense.

For my use case, i want to generate java source code, using info parsed from other java source code (thanks to the awesome plyj lib), so it’s easy to give the general form of the output file, and to pass the content after that.

{% if package %}package {{ package }};{% endif %}
import {{ module.package_declaration.name.value }}.*;
{{ imports }}\

public class {{ cls.name }}{{ suffix }} extends {{ cls.name }} {
    public interface I{{ cls.name }} {\
    {% for method in methods %}
    {{ method.return_type | get_type }} {{ method.name }}({{ method.parameters | render_params }});\
    {% endfor %}
    }

    private I{{ cls.name }} implem = null;

    public void setImplem(I{{ cls.name }} implem) {
    this.implem = implem;
    }

    {% for method in methods %}
    {{ method.return_type | get_type }} {{ method.name }}({{ method.parameters | render_params }}) {
    if (this.implem)
        return this.implem.{{ method.name }}({{ method.parameters | render_params_values }});
    }{% endfor %}
}

One problem i had, though, was when it turned out it would be convenient to use custom filters inside my template, it took me some time to find the relevant documentation about how to register functions as filters in this situation (since people usually use jinja2 in a framework, they document how to do so using the environment used by this framework).

So the answer was not to use jinja2.Template directly, but to build an environment before.

env = jinja2.Environment()

then to setup my filters in this environment:

env.filters['render_params'] = render_params
env.filters['render_params_values'] = render_params_values
env.filters['get_type'] = get_type

and to use env.template_from_string(template_string) to create a Template object from my string.

Tip me if you like this :)

Worthiness of effort

written by tshirtman, on 2/9/14 1:08 AM.

If it’s worth to be done, it’s worth to be done well. If you aren’t struggling, it’s not worth doing it.

Tip me if you like this :)

flappy bird is a stupid game.

written by tshirtman, on 2/7/14 1:54 AM.

No, seriously.

Difficulty is flat, once you got past a pole, you know you can get past any pole, if you got past a dozen, you know you can theoretically go “all the way” (and there is no difference between theory and practice, in theory), so it’s just a matter of being consistent, the challenge is just to avoid losing focus, or stressing (because you are getting near of your high-score), but each pole is just as easy as the first one in the game.

So getting past pole 1 is enough to “beat the game”, of course, then you’ll set other arbitrary limits, trying to push further and further, but it’s just a matter of how lucky you are at avoiding accidents. I decided to put the limit at 50, and got to it today, so that’s it for me, and i’ll resume more interesting activities :P (it was already to high a limit, but i think it’s enough to consider i didn’t “beat the game” by accident).

Tip me if you like this :)

Magnet: a widget to easily make your interface more lively

written by tshirtman, on 2/6/14 12:38 AM.

Kivy has a very nice Animation class, that allows you to move move widgets around (or other things), by updating any numeric property to a target value, just by setting a time and a transition function. Still, when you are building a complex interface, it can still be a bit cumbersome to manually trigger animations for all the elements, and to keep track of them.

After being frustrated about this issue for some time, i tried my luck some time ago, at doing a nicer, “90% use cases” interface, and the Magnet garden widget was born.

Its usage is simple, you simply use it to wrap your target widget, and give it rules about how to transition when the magnet is moved. As the magnet is moved or resized by the usual kivy logic, instead of making the wrapped widget immediately follow such constraints, it’ll create and keep track of animations to achieve a smooth transition to the new values for you.

As any garden “flower”, to install it, you need to install and use the garden project.

python setup.py install

(either in a virtualenv or system-wide)

then do:

garden install magnet

you can now import it a kivy application:

from kivy.garden.magnet import Magnet

Garden Magnet video

Tip me if you like this :)

git, show stash list after checkout.

written by tshirtman, on 2/4/14 12:13 AM.

Sometime you start doing something in your codebase, and then you have to go do something else on another branch, so you stash them, later you come back, and you may not remember you started, them, and you forget to check your stash list.

Git has a very general solution for these kind of things: hooks

hooks are actions that you can “hook” (heh!) to events, it’s common to use the pre-commit hook to check for various errors before validating it, or to update refs after a fetch. Here, we want to display the list of stashes done on the current branch, after you checkout it.

first, we need to take the current branch.

 branch=$(git branch | grep "^\*"|sed -s s/'* '//)

then, we get the list of stash, and filter it on this branch:

 git stash list | grep "WIP on $branch"

put that in .git/hooks/post-checkout of your repository, and make it executable.

 chmod +x .git/hooks/post-checkout

But now, you have to do that in all your git repositories, but then there is this nice trick that allow you to easily use that hook in all your repositories, with just an unintrusive git init each time.

edit 2014-03-13: adding the exit 0 at the end of the script, because it prevented rebase. the code is now:

#!/usr/bin/env sh
branch=$(git branch | grep "^\*"|sed -s s/'* '//)
git stash list | grep "WIP on $branch"
exit 0
Tip me if you like this :)

back from FOSDEM

written by tshirtman, on 2/2/14 8:24 PM.

So i’m back from fosdem, and there has been an obvious pause on the daily blogpost thing, not only the days where quite full, but internet access was not, because i don’t have tethering in belgium, and wifi works when it wants.

The hotel wifi locked access had some dns bug, by the way, redirection to
www.hotspot.local wasn’t working, although dig gave its correct ip, editing /etc/host’ was the easy solution, so i did that.

So, there was a lot of interesting conferences, and as usual, you just can’t see them all, and there are people to see too, so i’ll definitly watch some of
them later using online recordings.

In the Python track, which i gave quite some attention too on sunday, async solutions was probably the most popular theme, with talks about pypy and SMT, asyncio, offset (python port of go’s goroutine), etc. I’ll definitly have to
give some more time to this, trying to port kivy’s eventloop to asyncio may be
a good (and potentially useful) exercise in this direction.

I managed to get a seat in the javascript track for the Cute presentation, as
i had a recent second look at AngularJS and it’s self-evidently a very complex framework, having an understandable version, even if less performant, looks like a very good idea. I guess i’ll have to learn some more on the JS
fundamental before though, as i understand its scope and object model much less than Python’s.

Aside of that i managed to have some time with Mathieu Virbel to talk about exciting new features in PyOBJus and the best syntax for them, and to think about the kivy organisation, which still require some work.

Of course, i met a lot of other friends, and had very nice discussions, so it
was a good experience, although i had overlooked the basic consequences of
being abroad (that is, that my second brain is impaired by lack of permanent network access).

Tip me if you like this :)

I'm going to FOSDEM

written by tshirtman, on 1/31/14 1:34 AM.

Yep, totally short-notice, i know!

I’ll be in Bruxelles this week end for one of the biggest FOSS event in Europe, ping me if you want to meet me! (tshirtman in all the relevant networks ;)).

Oddly, it’s the first way i manage to go to the event, thanks to my company for being pretty open about sponsoring employees to go to such events, i’ll try to make the most of it!

Have a nice weekend! :).

Tip me if you like this :)

Short meetings

written by tshirtman, on 1/30/14 1:13 AM.

There is something to do meetings near the end of the day, you really get down to take decisions very fast, nobody wants to delay things, things that would have been planned for a two hours session can really be achieved in a matter of minutes.

Most meetings should be hard-constrained to 30 minutes, doing more should be considered a waste of the company’s money.

Tip me if you like this :)

Kivy image manipulations with Mesh and Textures

written by tshirtman, on 1/29/14 1:05 AM.

If you want to give a little life to interactive (or not) elements, it’s always nice to have more tricks to manipulate images for nifty effects.

One of such ways is mapping a Texture on a special canvas instruction, that will distort your texture based on the position of its points.

[kivy.graphics.Mesh](http://kivy.org/docs/api-kivy.graphics.html#kivy.graphics.Mesh) is such an instruction, and it has a simple interface, if not 100% straightforward, you basically call it this way.

Mesh:
vertices: (x1, y1, s1, v1, x2, y2, s2, v2, x3, y3, s3, v3...)
indices: (1, 2, 3...)
texture: some_texture
mode: some_mode

where all: x mean the horizontal coordinate of a point y mean the vertical coordinate of a point s mean the horizontal position of the texture attached to this point (between 0 and 1) v mean the vertical position of the texture attached to this point (between 0 and 1)

indices is useful if, for some (very good) reason, you don’t want to give the points in the order you’ll use them, or if you want to refer to a point multiple time (this won’t be demonstrated in this blog post, but try to think about a grid mapping, for example), now we will use it in the most simple way, just give the range of your number of points.

the texture needs to be a texture object, you can get such an object by getting the texture property of a [CoreImage](http://kivy.org/docs/api-kivy.core.image.html#kivy.core.image.Image) or an Image (or even a Label, if you want to).

Let’s say we have an image, for example, kivy logo.

from kivy.core.image import Image as CoreImage

texture = CoreImage('data/logo/kivy-icon-512.png').texture

(this will work wherever you are, because kivy look at his images anyway :))

This image is a circle, lets use that to cut it into a virtual pie and assign a part of the texture to each part, we’ll be using the triangle_fan mode of Mesh, that is a perfect fit for such an operation.

# the central point
points = [Window.width / 2, Window.height / 2, .5, .5]

# now go around
    i = 0
    while i < 2 * pi:
        i += 0.01 * pi
        points.extend([
    Window.width / 2 + cos(i) * 100,
    Window.height / 2 + sin(i) * 100,
    .5 + sin(i),
    .5 + cos(i)])

put that in a more complete program, and you get this:

from kivy.app import App
from kivy.lang import Builder
from kivy.core.image import Image as CoreImage
from kivy.properties import ListProperty, ObjectProperty
from kivy.clock import Clock
from kivy.core.window import Window
from math import sin, cos, pi


kv = '''
Widget:
    canvas:
        Color:
            rgba: 1, 1, 1, 1
        Mesh:
            vertices: app.mesh_points
            indices: range(len(app.mesh_points) / 4)
            texture: app.mesh_texture
            mode: 'triangle_fan'
'''


class MeshBallApp(App):
    mesh_points = ListProperty([])
    mesh_texture = ObjectProperty(None)

    def build(self):
        self.mesh_texture = CoreImage('data/logo/kivy-icon-512.png').texture
        Clock.schedule_interval(self.update_points, 0)
        return Builder.load_string(kv)

    def update_points(self, *args):
        points = [Window.width / 2, Window.height / 2, .5, .5]
        i = 0
        while i < 2 * pi:
            i += 0.01 * pi
            points.extend([
                Window.width / 2 + cos(i) * 100,
                Window.height / 2 + sin(i) * 100,
                .5 + cos(i),
                .5 + sin(i)])

        self.mesh_points = points

if __name__ == '__main__':
    MeshBallApp().run()

Now, this is not very impressive, we just have an image, there were much simpler ways to do that!

But now, we can tweek the rendering a lot, lets add some offseting of the texture, some radius change, and some wobbling, with sliders to control all this.

from kivy.app import App
from kivy.lang import Builder
from kivy.core.image import Image as CoreImage
from kivy.properties import ListProperty, ObjectProperty, NumericProperty
from kivy.clock import Clock
from kivy.core.window import Window
from math import sin, cos, pi


kv = '''
BoxLayout:
    Widget:
        canvas:
            Color:
                rgba: 1, 1, 1, 1
            Mesh:
                vertices: app.mesh_points
                indices: range(len(app.mesh_points) / 4)
                texture: app.mesh_texture
                mode: 'triangle_fan'
    BoxLayout:
        orientation: 'vertical'
        size_hint_x: None
        width: 100
        Slider:
            value: app.offset_x
            on_value: app.offset_x = args[1]
            min: -1
            max: 1
        Slider:
            value: app.offset_y
            on_value: app.offset_y = args[1]
            min: -1
            max: 1
        Slider:
            value: app.radius
            on_value: app.radius = args[1]
            min: 10
            max: 1000
        Slider:
            value: app.sin_wobble
            on_value: app.sin_wobble = args[1]
            min: -50
            max: 50
        Slider:
            value: app.sin_wobble_speed
            on_value: app.sin_wobble_speed = args[1]
            min: 0
            max: 50
            step: 1
'''


class MeshBallApp(App):
    mesh_points = ListProperty([])
    mesh_texture = ObjectProperty(None)
    radius = NumericProperty(500)
    offset_x = NumericProperty(.5)
    offset_y = NumericProperty(.5)
    sin_wobble = NumericProperty(0)
    sin_wobble_speed = NumericProperty(0)

    def build(self):
        self.mesh_texture = CoreImage('data/logo/kivy-icon-512.png').texture
        Clock.schedule_interval(self.update_points, 0)
        return Builder.load_string(kv)

    def update_points(self, *args):
        points = [Window.width / 2, Window.height / 2, .5, .5]
        i = 0
        while i < 2 * pi:
            i += 0.01 * pi
            points.extend([
                Window.width / 2 + cos(i) * (self.radius + self.sin_wobble * sin(i * self.sin_wobble_speed)),
                Window.height / 2 + sin(i) * (self.radius + self.sin_wobble * sin(i * self.sin_wobble_speed)),
                self.offset_x + sin(i),
                self.offset_y + cos(i)])

        self.mesh_points = points

if __name__ == '__main__':
    MeshBallApp().run()

which gives us:

Kivy image manipulations with Mesh and Text

Now we are talking!

Tip me if you like this :)

Tags

#FIXME 3G absurd ad_sense alterway aléatoire android animation anonymity atheism bach backlog bash bitcoins blog blogging boldness book books boulot bricolage bépo C canvas captcha captures carte SD censure christianity chroot CLI cli cloudwatt code colors comfort zone command line community company life conferences contest copwatch copwatchnord-idf core-devs cours ct705 culture deb debian debug deformation dehors dessin dev distribute distribution débutant déploiement développement ebooks eeepad eeepc effect ego empty en escher event firefly flappy bird flask fosdem foss fr fun game garden gdb geek culture git github goals graphics grrr gödel hack hackathon hacked hacking health hooks i3 images IMAP inspirational install isync java jeu jeu video jinja2 jni keyboard keynav kivy kv lame learning lib libre life linux lol macosx magnet mail mailing-list mails maths mbsync meetings memory leak mesh meta mint mirroir MIT module motivational mouse museomix mutt nexus7 no-mouse notmuch nottoomuch offlineimap onycroit opencourseware osc packaging paris passphrase password patch pentacatyl people perte de données ping pip planning plugin positioning pr procrastination programmation progress project projet property proudhon proxy psf publisher/consumer pull-down pygame pyjnius pypi python pythonar qtile raid rapsberry pi reading recorder references release religion responsive review reviews réseau réseaux sociaux résurection salon screenshots script self service shows shutil shyness sizing solib sortie sousous!!! spam spritz stash status systeme système templating terminal texture texture coordinates Thomas Paine thread thème tiling time time management. tip tips tools transformer tutorial tv twitter typematrix typing ubuntu ubuntu-fr ultimate-smash-friends unity update upload images useless usf utils value VDM video vie/mort vim virtualenv visite widget windows wm wmii work workflow workflow. zine études