Martín Gaitán: Sergio Massa y #LaGente

Anoche me reí mucho con el hashtag #LaGente, que se viralizó mientras Alejandro Fantino entrevistaba, una vez más, al inefable candidato presidencial Sergio Massa.

Me acordé entonces de un post de Zulko, cuyo blog es un compilado de gemas ñoñamente divertidas. Allí muestra cómo recortar automáticamente los pedacitos de un video que mencionen una palabra o frase, basándose en las marcas de tiempo del archivo de subtítulos, utilizando su maravillosa biblioteca Moviepy y un poco de Python. Más o menos lo que hace videogrep, pero más prolijo.

La herramienta youtube-dl (que también es genial y hecha en Python), permite no sólo bajar videos de youtube y los subtitulos existentes, sino que también puede bajar el "subtitulo automático". En general son bastante malos pero es suficientemente efectivo para encontrar pequeñas frases.

Todo sea por "la gente": manos a la obra

Lo primero que necesitamos es una lista de videos donde Sergio Massa hable. Hice una búsqueda, decidí ignorar algunos (parodias, por ejemplo) y generé una lista. Hay varias maneras de obtener este listado de las primeras paginas de resultados, yo utilicé el rústico y efectivo webscrapping:

In [1]:
from pyquery import PyQuery
links = []
skip = ('M0yuFHbhYLY','TLmMh9Qvmic', 'rY4Hwvn6GlA')

for page in range(1, 5):
    pq = PyQuery('https://www.youtube.com/results?search_query=entrevista+sergio+massa&page=%s' % page)
    pq.make_links_absolute()
    links.extend([pq(a).attr('href') for a in pq('a.yt-uix-tile-link') if pq(a).attr('href').split('v=')[1] not in skip])
links
Out[1]:
['https://www.youtube.com/watch?v=8pP8G3fSAcY',
 'https://www.youtube.com/watch?v=g6QSwxUo1aw',
 'https://www.youtube.com/watch?v=_9FN6CI8fD4',
 'https://www.youtube.com/watch?v=5wqwNDpkZOo',
 'https://www.youtube.com/watch?v=V865E4mBiHU',
 'https://www.youtube.com/watch?v=TPrGNJnMS9U',
 'https://www.youtube.com/watch?v=SVTl11hG9Gs',
 'https://www.youtube.com/watch?v=Df_dwb5XHQM',
 'https://www.youtube.com/watch?v=sptBkyfq1VU',
 'https://www.youtube.com/watch?v=tzjz1xrNu3k',
 'https://www.youtube.com/watch?v=k-CGbuOo8do',
 'https://www.youtube.com/watch?v=_L-B_wHsEec',
 'https://www.youtube.com/watch?v=iFOABIQdo9Q',
 'https://www.youtube.com/watch?v=WOlRIKGrBWY',
 'https://www.youtube.com/watch?v=a-mCgN6W9ek',
 'https://www.youtube.com/watch?v=x5vhchv3zAY',
 'https://www.youtube.com/watch?v=bi5eK7i59w0',
 'https://www.youtube.com/watch?v=VNHV3D_6o4E',
 'https://www.youtube.com/watch?v=MWVZ6JDU9V8',
 'https://www.youtube.com/watch?v=v-JmdgVZqVc',
 'https://www.youtube.com/watch?v=FBFHpdxsyYU',
 'https://www.youtube.com/watch?v=WXmTc83l1sQ',
 'https://www.youtube.com/watch?v=GfNgds5vS60',
 'https://www.youtube.com/watch?v=UHRa34A6rDg',
 'https://www.youtube.com/watch?v=xVU-EjnuksU',
 'https://www.youtube.com/watch?v=-IXymTZZM6o',
 'https://www.youtube.com/watch?v=tzvwDTPyTHQ',
 'https://www.youtube.com/watch?v=a19z6EVWpQ4',
 'https://www.youtube.com/watch?v=rAOvF8X_nzM',
 'https://www.youtube.com/watch?v=wtvl4esdMGU',
 'https://www.youtube.com/watch?v=1YPHDDH1Az0',
 'https://www.youtube.com/watch?v=w7TnghsrJUo',
 'https://www.youtube.com/watch?v=qBT-6HpSrwc',
 'https://www.youtube.com/watch?v=JM-xblTxLGc',
 'https://www.youtube.com/watch?v=kMymsVsmETY',
 'https://www.youtube.com/watch?v=K1-dfiVfbOI',
 'https://www.youtube.com/watch?v=VnoiHVlR-So',
 'https://www.youtube.com/watch?v=hMTzJyLiXE4',
 'https://www.youtube.com/watch?v=VGQPNQ1Bhkg',
 'https://www.youtube.com/watch?v=0oR4z7SsY14',
 'https://www.youtube.com/watch?v=Cl4r8h_Hlak',
 'https://www.youtube.com/watch?v=gJFmek-YgYo',
 'https://www.youtube.com/watch?v=9VQ7Ov5W_tM',
 'https://www.youtube.com/watch?v=rKwKImVrYu4',
 'https://www.youtube.com/watch?v=LJwj9SHC9EU',
 'https://www.youtube.com/watch?v=-08OEpFThiw',
 'https://www.youtube.com/watch?v=BPJBl5y2P2g',
 'https://www.youtube.com/watch?v=MvkXlg9ZbL4',
 'https://www.youtube.com/watch?v=7KgIa4fX_Ng',
 'https://www.youtube.com/watch?v=upNLrHtzeBI',
 'https://www.youtube.com/watch?v=Y-norf1BKAs',
 'https://www.youtube.com/watch?v=QMvAl_fxQSA',
 'https://www.youtube.com/watch?v=3os_uXUOvcM',
 'https://www.youtube.com/watch?v=ZE_aChIEELo',
 'https://www.youtube.com/watch?v=iKI-8ceuR-A',
 'https://www.youtube.com/watch?v=CASdYLquQII',
 'https://www.youtube.com/watch?v=5cvyi1CcpYs',
 'https://www.youtube.com/watch?v=NVEw-YIAy5A',
 'https://www.youtube.com/watch?v=yMXn04-GQTY',
 'https://www.youtube.com/watch?v=RCCzZGcGg5k',
 'https://www.youtube.com/watch?v=FqMFKGsXLOE',
 'https://www.youtube.com/watch?v=MVOvQb8KBm0',
 'https://www.youtube.com/watch?v=ENvWfMwnJ_0',
 'https://www.youtube.com/watch?v=bs7xGm293Vs',
 'https://www.youtube.com/watch?v=7OvrK-U-axI',
 'https://www.youtube.com/watch?v=VHeWqPqs4vo',
 'https://www.youtube.com/watch?v=nVOEi9FESn8',
 'https://www.youtube.com/watch?v=eikTWAvFwTE',
 'https://www.youtube.com/watch?v=BU2amn3QdWk',
 'https://www.youtube.com/watch?v=GiB1pOuEvqg',
 'https://www.youtube.com/watch?v=GAPN17lTJ9c',
 'https://www.youtube.com/watch?v=4Ja1uZbMM8E',
 'https://www.youtube.com/watch?v=F1dAfCR4rc0',
 'https://www.youtube.com/watch?v=334O9xh-CQY',
 'https://www.youtube.com/watch?v=KgNmw3sJ0g8',
 'https://www.youtube.com/watch?v=-SQSue4-PLk',
 'https://www.youtube.com/watch?v=HPE4PHlYySo']

Luego, el paso lento: bajar los videos. Al parecer, Youtube no genera un subtitulo automático para videos demasiado largo, así que limité hasta 30 minutos.

In [2]:
for link in links:
    !youtube-dl --write-auto-sub --sub-lang es --max-filesize 30.00m {link}

Con el material crudo disponible (aunque puede ser que no se hayan encontrado subtitulos para todos los videos), podemos copiar descaradamente partes del código de Zulko (levemente adaptado)

In [3]:
import re
import os
import glob
import random
from moviepy.editor import VideoFileClip, concatenate, TextClip, CompositeVideoClip


def convert_time(timestring):
    """ Converts a string into seconds """
    nums = [float(t) for t in re.findall(r'\d+', timestring)]
    return 3600 * nums[0] + 60*nums[1] + nums[2] + nums[3]/1000


def get_time_texts(file):
    with open(file) as f:
        lines = f.readlines()

    times_texts = []
    current_times , current_text = None, ""
    for line in lines:
        times = re.findall("[0-9]*:[0-9]*:[0-9]*,[0-9]*", line)
        if times != []:
            current_times = [convert_time(t) for t in times]
        elif line == '\n':
            times_texts.append((current_times, current_text))
            current_times, current_text = None, ""
        elif current_times is not None:
            current_text = current_text + line.replace("\n"," ")
    return times_texts

def find_word(word, times_texts, padding=.4):
    """ Finds all 'exact' (t_start, t_end) for a word """
    matches = [re.search(word, text)
               for (t,text) in times_texts]
    return [(t1 + m.start()*(t2-t1)/len(text) - padding,
             t1 + m.end()*(t2-t1)/len(text) + padding)
             for m,((t1,t2),text) in zip(matches, times_texts)
             if (m is not None)]


def get_subclips(video_path, cuts):
    video = VideoFileClip(video_path)
    return [video.subclip(start, end) for (start,end) in cuts]


def get_all_subclips_for(word, pattern='*.mp4', sub_ext='.es.srt', shuffle=True):
    subclips = []
    for mp4 in glob.glob(pattern):
        sub = os.path.splitext(mp4)[0] + sub_ext
        try:
            times = find_word(word, get_time_texts(sub))
        except IOError:
            # ignore video if it hasn't subtitle
            continue
        cuts = get_subclips(mp4, times)
        subclips.extend(cuts)
    if shuffle:
        random.shuffle(subclips)
    return subclips

La función get_all_subclip recibe la frase a buscar y devuelve un listado de segmentos donde, muy probablemente, se pronuncia.

In [4]:
gente = get_all_subclips_for('la gente')
len(gente)
Out[4]:
77

El problema es que aunque es muy probable que sea Sergio Massa el que diga "la gente" en sus entrevistas, a veces es el entrevistador, a veces youtube entendió mal al desgrabar y a veces el código recortador la pifia. Por este motivo hay que descartar los segmentos que no sirven.

Se me ocurrió hacerlo visualmente: los pegué todos, superponiendo el índice al que corresponde cada segmento, para luego anotar los que no sirven y filtrarlos en otra pasada.

In [5]:
def make_preview(subclips):
    subclips_ = []
    for (i, clip) in enumerate(subclips):
        txt_clip = TextClip(str(i),fontsize=70, color='white')
        txt_clip = txt_clip.set_pos('center').set_duration(clip.duration)
        clip = CompositeVideoClip([clip, txt_clip])
        subclips_.append(clip)

    final = concatenate(subclips_, method='compose')
    final.write_videofile('preview.webm', codec='libvpx', fps=24)
In [6]:
make_preview(gente)
[MoviePy] >>>> Building video preview.webm
[MoviePy] Writing audio in previewTEMP_MPY_wvf_snd.ogg
[MoviePy] Done.
[MoviePy] Writing video preview.webm
[MoviePy] Done.
[MoviePy] >>>> Video ready: preview.webm

El resultado me permitió hacer el tamizado

In [7]:
ignore = [2, 3, 8, 12, 17, 19, 25, 28, 32, 36, 38, 40, 41, 44, 49, 55, 56, 61, 62, 66, 73, 74]
subclips_cleaned = [i for j, i in enumerate(gente) if j not in ignore]

Aunque no tengo idea de edición de videos, y porque de verdad creo que es un demamogo impresentable que no debería presidir ni una junta vecinal, quería darle un toque final, con una pequeña frase

In [8]:
import numpy as np
from moviepy.video.tools.segmenting import findObjects

def arrive(screenpos,i,nletters):
    v = np.array([-1,0])
    d = lambda t : max(0, 3-3*t)
    return lambda t: screenpos-400*v*d(t-0.2*i)

screensize = (640,360)
txtClip = TextClip('Yn tragr ab rf obyhqn'.decode('rot13'), color='white', font="Amiri-Bold", kerning=5, fontsize=50)
cvc = CompositeVideoClip( [txtClip.set_pos('center')],
                        size=screensize)

letters = findObjects(cvc) # a list of ImageClips

def moveLetters(letters, funcpos):
    return [ letter.set_pos(funcpos(letter.screenpos,i,len(letters)))
              for i,letter in enumerate(letters)]

ending = CompositeVideoClip(moveLetters(letters, arrive), size=screensize).subclip(0, 10)
In [9]:
# le damos una mezcladita más
random.shuffle(subclips_cleaned)
subclips_cleaned.append(ending)
make_final(subclips_cleaned, 'massa_lagente_final.webm')
[MoviePy] >>>> Building video massa_lagente_final.webm
[MoviePy] Writing audio in massa_lagente_finalTEMP_MPY_wvf_snd.ogg
[MoviePy] Done.
[MoviePy] Writing video massa_lagente_final.webm
[MoviePy] Done.
[MoviePy] >>>> Video ready: massa_lagente_final.webm

Y este es el resultado:

In [ ]:

Facundo Batista: Metaclasses in Python, the easy way (a real life example)


They say that metaclasses make your head explode. They also say that if you're not absolutely sure what are metaclasses, then you don't need them.

And there you go, happily coding through life, jumping and singing in the meadow, until suddenly you get into a dark forest and find the most feared enemy: you realize that some magic needs to be done.


The necessity

Why you may need metaclasses? Let's see this specific case, my particular (real life) experience.

It happened that at work I have a script that verifies the remote scopes service for the Ubuntu Phone, checking that all is nice and crispy.

The test itself is simple, I won't put it here because it's not the point, but it's isolated in a method named _check, that receives the scope name and returns True if all is fine.

So, the first script version did (removed comments and docstrings, for brevity):

    class SuperTestCase(unittest.TestCase):

        def test_all_scopes(self):
            for scope in self._all_scopes:
                resp = self._check(scope)
                self.assertTrue(resp)

The problem with this approach is that all the checks are inside the same test. If one check fails, the rest is not executed (because the test is interrupted there, and fails).

Here I found something very interesting, the (new in Python 3) subTest call:

    class SuperTestCase(unittest.TestCase):

        def test_all_scopes(self):
            for scope in self._all_scopes:
                with self.subTest(scope=scope):
                    resp = self._check(scope)
                    self.assertTrue(resp)

Now, each "sub test" internally is executed independently of the other. So, they all are executed (all checks are done) no matter if one or more fail.

Awesome, right? Well, no.

Why not? Because even if internally everything is handled as independent subtest, from the outside point of view it still is one single test.

This has several consequences. One of those is that the all-inside test takes too long, and you can't know what was going on (note that each of these checks hit the network!), as the test runner just show progress per test (not subtest).

The other inconvenient is that there is not a way to call the script to run only one of those subtests... I can tell it to execute only the all-inside test, but that would mean to execute all the subtests... which, again, takes a lot of time.

So, what I really needed? Something that allows me to express the assertion in one test, but that in reality it were several methods. So, I needed something that, from a single method, reproduce them so the class actually had several ones. This is, write code for a class that Python would find different. This is, metaclasses.


Metaclasses, but easy

Luckily, since a couple of years ago (or more), Python provides a simpler way to achieve the same that could be done with metaclasses. This is: class decorators.

Class decorators, very similar to method decorators, receive the class that is defined below itself, and its response is considered by Python the real definition of the class. If you don't have the concept, you may read a little here about decorators, and a more deep article about decorators and metaclasses here, but it's not mandatory.

So, I wrote the following class decorator (explained below):

    def test_multiplier(klass):
        """Multiply those multipliable tests."""
        for meth_name in (x for x in dir(klass) if x.startswith("test_")):
            meth = getattr(klass, meth_name)
            argspec = inspect.getfullargspec(meth)

            # only get those methods that are to be multiplied
            if len(argspec.args) == 2 and len(argspec.defaults) == 1:
                param_name = argspec.args[1]
                mult_values = argspec.defaults[0]

                # "move" the usefult method to something not automatically executable
                delattr(klass, meth_name)
                new_meth_name = "_multiplied_" + meth_name
                assert not hasattr(klass, new_meth_name)
                setattr(klass, new_meth_name, meth)
                new_meth = getattr(klass, new_meth_name)

                # for each of the given values, create a new method which will call the given method
                # with only a value at the time
                for multv in mult_values:
                    def f(self, multv=multv):
                        return new_meth(self, **{param_name: multv})

                    meth_mult_name = meth_name + "_" + multv.replace(" ", "_")[:30]
                    assert not hasattr(klass, meth_mult_name)
                    setattr(klass, meth_mult_name, f)

        return klass

The basics are: it receives a class, it returns a slightly modified class ;). For each of the methods that starts with "test_", I checked those that had two args (not only 'self'), and that the second argument were named.

So, it would actually get the method defined in the following structure and leave the rest alone:

    @test_multiplier
    class SuperTestCase(unittest.TestCase):

        def test_all_scopes(self, scope=_all_scopes):
            resp = self.checker.hit_search(scope, '')
            self.assertTrue(resp)

For that kind of method, the decorator will move it to something not named "test_*" (so we can call it but it won't be called by automatic test infrastructure), and then create, for each value in the "_scopes" there, a method (with a particular name which doesn't really matter, but needs to be different and is nice to be informative to the user) that calls the original method, passing "scope" with the particular value.

So, for example, let's say that _all_scopes is ['foo', 'bar']. Then, the decorator will rename test_all_scopes to _multiplied_test_all_scopes, and then create two new methods like this::

    def test_all_scopes_foo(self, multv='foo'):
        return self._multiplied_test_all_scopes(scope=multv)

    def test_all_scopes_foo(self, multv='bar'):
        return self._multiplied_test_all_scopes(scope=multv)

The final effect is that the test infrastructure (internally and externally) finds those two methods (not the original one), and calls them. Each one individually, informing progress individually, the user being able to execute them individually, etc.

So, at the end, all gain, no loss, and a fun little piece of Python code :)

Manuel Kaufmann (Humitos): PyDay en Asunción, Paraguay

Hace un poco más de una semana que estamos en Paraguay con @EllaQuímica y hemos conocido gente hermosa a través de las calles, la comunidad de CouchSurfing y también Python. Nuestro primer contacto por estos lares fue Javier, con quien hablé en la Python Conference Argentina 2014 y quedamos de juntarnos si es que mi viaje me llevaría por Asunción.

Una vez cerca de Asunción, me puse en contacto con él y también hice un poco de ruido en diferentes listas de correo de la zona (MiSol y Python Argentina) donde me pusieron en contacto con Mauro también. Así, se fue sumando gente y hoy somos un grupo de 13 personas con muchas ganas de formar (y formando) una comunidad "Python Paraguay".

organizadores.thumbnail.jpeg

Parte del comitée de organizadores

Como primer evento de esta comunidad emergente, estamos organizando, junto a SENATICs, un #PyDay en Asunción, Paraguay el Sábado 28 de Marzo desde las 9:30hs en L'Office Santos, ubicado en Gral. Santos 1170.

Difusión del evento y de la comunidad "Python Paraguay":

GiLgAmEzH: Día internacional de la Mujer Trabajadora

El 8 de marzo se festeja justamente lo que dice el titulo de este post. no es el día de las Legrand, las thatcher, las Alfano, etc. Es un buen momento también para recordar que no es únicamente una cuestión de género.

Feliz día!

Si Dios fuera una mujer

¿Y si Dios fuera mujer?
pregunta Juan sin inmutarse,
vaya, vaya si Dios fuera mujer
es posible que agnósticos y ateos
no dijéramos no con la cabeza
y dijéramos sí con las entrañas.

Tal vez nos acercáramos a su divina desnudez
para besar sus pies no de bronce,
su pubis no de piedra,
sus pechos no de mármol,
sus labios no de yeso.

Si Dios fuera mujer la abrazaríamos
para arrancarla de su lontananza
y no habría que jurar
hasta que la muerte nos separe
ya que sería inmortal por antonomasia
y en vez de transmitirnos SIDA o pánico
nos contagiaría su inmortalidad.

Si Dios fuera mujer no se instalaría
lejana en el reino de los cielos,
sino que nos aguardaría en el zaguán del infierno,
con sus brazos no cerrados,
su rosa no de plástico
y su amor no de ángeles.

Ay Dios mío, Dios mío
si hasta siempre y desde siempre
fueras una mujer
qué lindo escándalo sería,
qué venturosa, espléndida, imposible,
prodigiosa blasfemia.

Facundo Batista: Novedades pythónicas: fades, CDPedia, Django y curso


Algunas, varias y sueltas.

A nivel de proyectos, le estuvimos metiendo bastante con Nico a fades. La verdad es que la versión 2 que sacamos la semana pasada está piolísima... si usás virtualenvs, no dejes de pegarle una mirada.

Otro proyecto con el que estuve es CDPedia... la parte de internacionalización está bastante potable, y eso también me llevó a renovar la página principal que te muestra cuando la abrís, así que puse a tirar una nueva versión de la de español, y luego seguirá una de portugués (¡cada imagen tarda como una semana!).

Hace un rato subí a la página de tutoriales de Python Argentina el Tutorial de Django en español (¡gracias Matías Bordese por el material!). Este tuto antes estaba en un dominio que ahora venció, y nos pareció interesante que esté todo en el mismo lugar, facilita que la gente lo encuentre.

Finalmente, empecé a organizar mi Segundo Curso Abierto de Python. Esta vez lo quiero hacer por la zona de Palermo, o alrededores (la vez pasada fue en microcentro). Todavía no tengo reservado un lugar, y menos fechas establecidas, pero el formato va a ser similar al anterior. Con respecto al sitio, si alguien conoce un buen lugar para alquilar "aulas", me avisa, :)

Manuel Kaufmann (Humitos): Verduras y precios paraguayos

Más allá de todo lo nuevo que tiene un país diferente a donde uno ha nacido, sus costumbre, sus ideas y su cultura en general. También está el tema de los precios y su moneda.

Es un poco complicado al principio acostumbrarse a una moneda en donde todo se maneja en miles y por otro lado todo el mundo es millonario (el salario mínimo es de 1.800.000 gs) ;)

Además, para nosotros, que llevamos moneda Argentina todo nos sale mucho más caro. Así que, hacer esa conversión de Guaraníes, Dólares y luego a Pesos es bastante frustrante. Más vale pagar con los ojos cerrados y disfrutar de todos los días. Pero claro, ¿cuánto tiempo puede durar esa dinámica? Un poco hay que pensar, por lo menos, no comer nada de lo que es extremadamente caro: ¡Lechuga!.

¿Quién hubiera pensado que la lechuga común iba a ser tan cara en algún momento?

Para poder hacer un análisis de qué cosas nos conviene comer / comprar, empecé a tomar algunas fotografías de los precios de las frutas y las verduras en el Supermecado Stock de Paraguay:

IMG_20150304_194103.thumbnail.jpg

Pimiento, repollo, coliflor, cebolla colorada, zapallo, remolacha, etc

IMG_20150304_194116.thumbnail.jpg

Puerro, achicoria, apio, espinaca, remedio, cebollita de hoja, lechuga, etc

IMG_20150304_194124.thumbnail.jpg

Manzana, durazno, mburucuya, melon, uva, etc

IMG_20150304_194148.thumbnail.jpg

Mandioca, papa, cebolla, etc

IMG_20150304_194337.thumbnail.jpg

Repollo, zanahoria, locote, tomate

Nota

Acá hierven la mandioca y la usan como acompañamiento de las carnes, como si fuera un pan. Y comen muchísima mandioca, está por todos lados.

IMG_20150304_194226.thumbnail.jpg

Naranja, limón, manzana coleg, banana

IMG_20150304_194238.thumbnail.jpg

Mandarina, pomelo, batata, banana de oro, piña brasil, batata

Saquen sus propias conclusiones y, si llegan a algún algoritmo para reducir los gastos, me avisan que lo implementamos de toque.

Manuel Kaufmann (Humitos): El tereré Paraguayo

El fin de semana nos llamó mucho la atención un puestito de venta de "yuyos" que había en la plaza Uruguaya de Asunción, Paraguay. Una cantidad impresionante de gente se acercaba, abría su termo y una señora muy amable machacaba unas hierbas y las volcaba en el termo. Luego, se retiraban...

Como somos muy inquietos, no podíamos dejar de probar ese tereré tan raro (para nosotros) y charlar un poco con la señora del lugar. Aquí está el registro audiovisual:

Roberto Alsina: Escuchas

Ha­ce po­co In­fo­bae pu­bli­có, di­ce "To­das las es­cu­chas de la cau­sa Nis­man so­bre el pre­sun­to en­cu­bri­mien­to del aten­ta­do a la AMIA"

¿Po qué di­go "di­ce"? Por­que no es cier­to. Lo que pu­bli­ca­ron son to­das las es­cu­chas que se hi­cie­ron a los te­lé­fo­no­s ­de Kha­li­l, que se in­ter­vino por la cau­sa AMIA. Son es­cu­chas de la cau­sa AMIA, no de la cau­sa del en­cu­bri­mien­to.

La cau­sa so­bre en­cu­bri­mien­to sur­ge de que Nis­man, al re­ci­bir es­tas es­cu­cha­s, y vien­do el me­mo­ran­dum de en­ten­di­mien­to, de­ci­de que hay un en­cu­bri­mien­to en cur­so, re­ú­ne evi­den­cia, y lo de­nun­cia. Pe­ro las es­cu­chas de la cau­sa de­l en­cu­bri­mien­to son mu­chas me­no­s, son las que pre­sen­tó co­mo evi­den­cia Po­lli­ci­ta, o sea 15 CD­s, que fue­ro­n a­na­li­za­dos por Ra­fe­ca­s, que es (o era, a es­ta al­tu­ra) el juez en la cau­sa del en­cu­bri­mien­to.

Los que se que­jan de que Ra­fe­cas no re­vi­só es­tas otras mi­les de es­cu­chas an­tes de ex­pe­dir­se de­be­rían pen­sar ­res­pues­tas pa­ra un par de pre­gun­tas bá­si­ca­s:

  1. Si Nis­man te­nía es­cu­chas más in­cri­mi­na­do­ra­s, que no es­tán en esos 15 CD­s... ¿Por qué no las agre­gó?
  2. Si Ra­fe­cas no ac­túa en la cau­sa AMIA... ¿Có­mo po­dría ac­ce­der a es­tas es­cu­cha­s?

La pri­me­ra ha­bla mal de Nis­man. Un fis­cal no se guar­da la evi­den­cia. Un fis­cal la pre­sen­ta.

La se­gun­da ha­bla mal de los que du­dan de Ra­fe­ca­s, por­que asu­men que un juez pue­de sim­ple­men­te ac­ce­der a es­cu­chas de otras cau­sas. O tal vez ha­bla mal de la jus­ti­cia por­que la gen­te asu­me que eso es po­si­ble.

La otra co­sa in­te­re­san­te de es­tas es­cu­chas es que, por ejem­plo, se pue­de es­cu­char al "es­pía" Bo­ga­do di­cien­do­ ­co­sas que, a sim­ple vis­ta, no pa­re­cen ser cier­ta­s. Por ejem­plo, di­ce que el 13/1/2013 Bou­dou es­ta­ba in­ter­na­do­ ­con un in­far­to, y que co­mo CFK es­ta­ba de via­je, lo es­con­die­ron pa­ra que no asu­ma Ro­jké­s.

Si fue un in­far­to fue asom­bro­sa­men­te le­ve, por­que el día an­tes Bou­dou re­ci­bió gen­te en el sena­do, y dos días des­pués es­ta­ba inau­gu­ran­do una plan­ta en Be­ra­zate­gui. De he­cho­, hay re­por­tes de que esa mis­ma no­che le pu­sie­ron una mul­ta a su au­to en la AU 25 de ma­yo, pe­ro po­ne­le que eso no es­to­y ­se­gu­ro por­que ca­paz que ma­ne­ja­ba otro.

Si era un pro­ble­ma que asu­ma Ro­jké­s, qué ra­ro que no fue un pro­ble­ma cuan­do asu­mió me­ses an­tes, en ma­yo­. ­Si era tan­to pro­ble­ma to­do, que ra­ro que CFK si­guió de gi­ra un par de se­ma­nas má­s. O se­rá que Bo­ga­do de­cía cual­quie­ra por­que es un fi­gu­re­ti.

Ha­y, sí, co­sas in­te­re­san­tes en las es­cu­cha­s. Co­mo cuan­do pi­den "pi­z­za na­po­li­ta­na sin ja­mó­n", de­mos­tran­do fe­ha­cien­te­men­te su ca­rác­ter de is­la­mis­tas fa­ná­ti­co­s.

Y hay otras que so­n, tal ve­z, re­le­van­tes pa­ra la cau­sa AMIA, co­mo cuan­do al­guien di­ce te­ner un vi­deo del aten­ta­do­. ­Pe­ro eso no es re­le­van­te pa­ra la cau­sa del en­cu­bri­mien­to. Es re­le­van­te pa­ra la cau­sa AMIA. La cau­sa pa­ra la que ­se hi­cie­ron las es­cu­cha­s. La cau­sa que lle­vó Nis­man por 10 año­s. El Nis­man que se su­po­ne oyó es­ta­s es­cu­cha­s, en la cau­sa que él mis­mo in­ves­ti­ga­ba. Y que al pa­re­cer no hi­zo na­da al res­pec­to.

La pre­gun­ta im­por­tan­te acá no es "¿­Por qué Ra­fe­cas no hi­zo na­da con es­tas es­cu­cha­s?". La pre­gun­ta im­por­tan­te es "¿­Por qué NIS­MAN no hi­zo na­da con es­tas es­cu­cha­s?".

Y esa es la pre­gun­ta que na­die pa­re­ce ha­cer­se.