Personal Website

My Web: MindEchoes.com

Monday, August 22, 2011

PyConAr 2011

El 23 y 24 de Septiembre se realiza en Argentina la PyCon, y la verdad que parece que se viene con todo!!

Así que si no te decidiste todavía, acá te dejo el afiche como incentivo para que veas los invitados que va a tener...
NO TE LO PODES PERDER!!


Sunday, August 21, 2011

PyDay San Luis

Bueno, recién vuelvo del PyDay San Luis!
La verdad una experiencia muy copada, muy buena onda la gente y le pusieron muchas pilas para organizar el evento!
Estuvo bueno ver como mucha gente se quedo hasta el último taller que termino recién por las 21hs y algo, se ve que la gente realmente se prendió con Python y da gusto! :D

Yo tuve la suerte de poder dar una charla de "Introducción a PyQt" y acompañar a Ramiro Algonzino en el taller de PyQt que dio él (que la gente realmente se engancho)!

También estuve tratando de lavarle el cerebro a la gente en una lightning talk para que usen NINJA-IDE! (infaltable), y me gane UN PENDRIVE DE 4 GB en el sorteo al final de las lightning talks!!

Acá dejo el material de la charla:
Acá les dejo algunas fotos que saco Emilio Ramirez durante el evento:





Lamentablemente la única foto que tenemos de la tremenda choripaneada que se hizo es la siguiente... ya que después estábamos todos demasiados ocupados comiendo :P

Servicio al consumidor: No vayan al "Hostel Quijadas" en San Luis!
Bastante mala onda para atender, nos alquilaban las toallas, no nos daban jabon, el desayuno fue ratonazo mal, y cuando terminamos de desayunar nos dicen: "chicos tienen que lavar lo que usaron"... ¬¬
Como protesta silenciosa... rotamos el cuadro de la pieza!!
TOMA ESO INJUSTICIA!

Esta es la escalera que paseando por la ciudad encontramos y fue denominada "escalera al suicidio"... era una escalera por donde subías hacia la NADA!

Y este es el Casino de San Luis por fuera, que esta muy bueno como lo decoraron todo onda New York (que es el nombre)! (hay más fotos copadas del casino, pero no las tengo :P)


Tuesday, August 16, 2011

Algunos Adelantos de NINJA-IDE 2.0

Actualmente nos encontramos trabajando en la versión 2.0 de NINJA-IDE, la cual incorpora muchísimos cambios con respecto a la 1.1 que fue la última versión liberada.
La arquitectura misma del IDE fue rediseñada para que sea más optima y se consiguió un mejor orden de las partes del programa y se gano un incremento importante en Performance! :D

A su vez, para esta nueva versión (que actualmente esta en desarrollo, pero es completamente usable) ya se han agregado muchas nuevas features, y todavía quedan varias más por agregar!

Algunas de las Nuevas Features son:

Recent Projects:
En la versión 1.1 se podían visualizar y abrir los proyectos recientes desde la página de inicio de NINJA-IDE, ahora estos proyectos pueden quitarse de la lista, y dockearlos a la misma para que queden siempre en los primeros puestos.


Soporte para Virtualenv:
Se agregó soporte para Virtualenv, el cual puede ser especificado en la creación del proyecto desde NINJA-IDE o sobre un proyecto ya existente.

Profiles:
A veces trabajamos con varios proyectos que están relacionados, y si les gusta tener abierto solo lo que es necesario, ahora en NINJA-IDE 2.0 se puede crear un perfil sobre los proyectos abiertos, agrupándolos bajo un nombre, de esta forma cuando abrimos un determinado perfil cierra todo lo que este abierto y carga todos los proyectos asociados a ese perfil, lo que nos permite cambiar de a varios grupos de proyectos en muy pocos clicks.

Import From Everywhere:
Hay casos donde estamos escribiendo código en un archivo que ya tiene varias lineas y empezamos a agregar clases que se encuentran en otros paquetes en nuestro código y el caso común probablemente sería scrollear hasta la cabecera del archivo, agregar nuestros imports y volver adonde estábamos. Para evitar tener que andar scrolleando de un lado a otro, NINJA-IDE nos permite incluir imports desde cualquier punto del código y automáticamente los inserta en la cabecera y los agrupa con otros imports que estén relacionados.

Code Locator:
Esta Feature nos permite tener acceso de forma rápida y directa a cualquier archivo, función o clase de cualquiera de los proyectos que tengamos cargados en NINJA-IDE con solo presionar un par de teclas!!
Al presionar "Ctrl+K", nos aparecerá un popup sobre un campo de texto, en el que podremos ir escribiendo y a medida que escribimos los resultados se irán filtrando en el popup. Es importante saber que si buscáramos la función: "obtain_editor", no sería necesario comenzar a escribir "obta...", sino que podemos escribir cualquier parte del nombre y será filtrada de todas formas, por ejemplo podríamos escribir: "_edit" y "obtain_editor" sería uno de los resultados en el filtro.
También una característica de esta Feature, es que cuando seleccionamos una Clase o Función, nos abre el archivo en el que se encuentra y nos ubica en la linea donde es definida dicha estructura.
Esta funcionalidad posee unos pre-filtros que se pueden aplicar para por ejemplo:

  • f: filtrar solo por archivos python.
  • m: filtrar solo por métodos.
  • c: filtrar solo por clases.
  • . filtrar solo por las clases y métodos contenidos en el archivo siendo visualizado.
  • n: filtrar solo por archivos no python.



Find Usages:
Desde la versión 1.1 contamos con "Find in Files", una Feature que nos permite buscar una o varias palabra, una expresioń regular, etc en todo el árbol del proyecto. Ahora para la versión 2.0 se ha mejorado esa funcionalidad, y a la vez se ha agregado "Find Usages", la cual se encuentra como una opción en el menu contextual del Editor y nos permite encontrar todas las ocurrencias de determinada palabra sobre la que estemos posicionados.

Show Errors and Pep8:
En la versión 1.1 estas funcionalidades estaban presentes, pero en la 2.0 se ha mejorado el rendimiento de las mismas, y se han agregado opciones adicionales en preferencias para poder configurarlas a gusto con la posibilidad de mejorar aún más la performance.
También podemos ver que en los archivos que contienen errores de pep8 nos muestra un icono de advertencia en la solapa donde se encuentra abierto ese archivo, y en los archivos que contienen errores estáticos de código nos muestra un icono de bug en esa solapa. De esta forma con solo abrir el archivo ya sabemos si hay algo a tener en cuenta en ese archivo y no es necesario tener que scrollear y ver si hay alguna notificación en alguna linea.


Menu Tabs:
Se ha agregado en los Tabs que contengan un Editor un menu contextual el cual permite splittear la ventana desde ahí mismo, realizar distintas operaciones de cerrado de tabs, reabrir  los últimos tabs cerrados, cambiar dinamicamente el tipo de resaltado de sintaxis, y algunas cosas más.

Web Inspector:
Para aquellos proyectos que utilizan la previsualización de una página web desde NINJA-IDE, se agregó un web inspector, el cual podría decirse que es un pseudo firebug, el cual nos permite ver la información del HTML siendo renderizado, y poder manipular en vivo el CSS, debuggearlo, etc.

Navigate Code:
En esta nueva versión se incorpora una funcionalidad que es de mucha ayuda, la cual nos permite presionar la tecla "Ctrl" y mover el mouse sobre las variables o funciones y ver como estas se pintan como si fuera links y al hacer click sobre una de ellas, NINJA-IDE nos llevara a la definición de dicha variable o función, de esta forma podemos saltar de un punto a otro del código con mucha facilidad.

Bookmarks, Breakpoints and Jumps:
Ahora es posible colocar breakpoints (para el debugger en desarrollo) y bookmarks sobre el Sidebar Widget del editor, sobre la misma area donde se ubican los indicadores de Code Folding. Y en la esquina superior derecha del manejador de Tabs de editores, podemos ver 2 flechas (izquierda-derecha), las cuales nos permiten navegar el historial de saltos en el código de la siguiente forma:
  • Flechas Naranja: permiten navegar el historial de los saltos que se hizo usando "Jump to Line", o Ctrl+Click sobre alguna función o variable en el editor.
  • Flechas Rojas: permiten navegar entre todos los breakpoints que hayamos agregado, de esta forma podemos con un simple click, ir recorriendo linea por linea y archivo por archivo donde se hayan colocado breakpoints.
  • Flechas Azules: permiten navegar entre todos los bookmarks que hayamos agregado, de esta forma podemos con un simple click, ir recorriendo linea por linea y archivo por archivo donde se hayan colocado bookmarks. Esto es muy util cuando estamos trabajando en varias partes de distintos archivos para una funcionalidad que engloba varias cosas, entonces colocando bookmarks podemos saltar precisamente a cada uno de estos lugares.

Hay varias Features más que se han agregado, pero este es un simple pantallazo de lo que se viene para NINJA-IDE 2.0, para más información se encuentran las Release Notes o nuestro Twitter: ninja_ide

Y como siempre, para cualquier consulta estan las listas de correo de NINJA-IDE y el canal de IRC:

ninja-ide@googlegroups.com
ninja-ide-dev@googlegroups.com

#ninja-ide (at Freenode)

Visitas a NINJA-IDE

Gráfico de las visitas a http://ninja-ide.org en el último mes!


Obtener Arbol Sintactico en Python

El fin de semana estuve de "paseo" en Buenos Aires, llegue el domingo como a las 7 de la mañana, pero recién tenia el check-in en el Hostel como a las 12... así que tenia que hacer tiempo!
Dije: "bueno... voy a pasear al shopping... debe ser lo único abierto y por ahí engancho una peli"... WRONG!!
Llegue al shopping como a las 8am... y recién abría a  las 10am... así que a buscar alguna confitería donde pudiera hacer un largooooooo desayuno... Y A PROGRAMAR NINJA-IDE!

Para mi sorpresa descubrí que Palermo (por donde estaba) es bastanteeeeeeeee caro!! (no, no tengo idea de nada de las zonas de BsAs)

Así que pedí mi desayuno:

Y a empezar a programar!
Lo que quise hacer fue agregar la parte de "Tree Symbols" de NINJA-IDE, básicamente la función es mostrarte un árbol con la información del archivo que se esta visualizando, es decir:

  • Variables del Módulo
  • Funciones del Módulo
  • Clases
  • Funciones de Clase
  • Atributos de Clase
Para la versión 1.1 de NINJA-IDE, habíamos hecho una implementación de esto pero obteniendo esos datos utilizando Rope, la cual es una muy buena librería, PERO genera bastante basura en el directorio del proyecto y la documentación es mala.... lo que si tiene son muchos tests, y básicamente podes aprender a usarla leyendo los tests, pero para la versión 2.0 estamos tratando de que la única dependencia que tenga el IDE sea con PyQt, de esta forma algunas libs que usamos (que no son muchas por el momento), las hemos incluido con el IDE mismo, y las hemos modificado para que se adapten mejor a ninja, funcionando más rápido para nuestras necesidades.

Entonces tenia que armar el Widget con el Árbol de Sintaxis, pero sin usar Rope que por el momento no la pensamos incluir... y que mejor que usar: AST (Abstract Syntax Trees)

Con AST se puede obtener mucha más información sobre el código, como los Imports, ImportsFrom, donde se están agregando For, Ifs, etc.
Y varios de los elementos (funciones, clases, for, etc), son nodos que pueden ser navegador internamente para seguir obteniendo información de las cosas que contienen.

En el caso de NINJA-IDE, solo me interesaba que obtuviera la info que se mencionó antes (Variables del Módulo, Funciones del Módulo, Clases, Funciones de Clase, Atributos de Clase), por lo que cree un método "obtain_symbols", que recibe un string con el código fuente (también podríamos modificar simplemente esta función para que recibiera un path de un archivo y trabajara con eso, pero en NINJA-IDE como se van a mostrar los símbolos sobre el archivo siendo visualizado, ya tengo el código cargado en un string, y me es más rápido que ir a leer a disco), y se encarga de parsear el cuerpo de ese código fuente, almacenando en un diccionario los atributos, funciones y clases que encuentra.
En el caso de las Clases, como sabemos que estas pueden llegar a contener Atributos o Métodos, al momento de parsear la clase, no solo guardamos en que linea del código esta declarada, sino que llamamos a un método para que ahora parsee el cuerpo de la clase (vamos un nodo más abajo): "_parse_class_body", la cual recorre las funciones y atributos de la clase almacenándolos en una nueva estructura de diccionario y sobre las funciones vuelve a realizarse una búsqueda interna sobre otros atributos de la clase que se encuentren definido dentro de las funciones llamando a: "_parse_cls_function_body".

El código de esto sería:

# -*- coding: utf-8 -*-
import ast


def _parse_cls_function_body(funcBody):
    attr = {}
    for at in funcBody:
        if type(at) is ast.Assign and \
        type(at.targets[0]) is ast.Attribute:
            attr[at.targets[0].attr] = at.targets[0].lineno
    return attr


def _parse_class_body(classBody):
    attr = {}
    func = {}
    for sym in classBody:
        if type(sym) is ast.Assign:
            attr[sym.targets[0].id] = sym.lineno
        elif type(sym) is ast.FunctionDef:
            func[sym.name] = sym.lineno
            moreAttr = _parse_cls_function_body(sym.body)
            for ma in moreAttr:
                attr[ma] = moreAttr[ma]
    return {'attributes': attr, 'functions': func}


def obtain_symbols(source):
    try:
        module = ast.parse(source)
    except:
        module = ast.parse(source[source.find('\n'):])
    symbols = {}
    globalAttributes = {}
    globalFunctions = {}
    classes = {}
    for sym1 in module.body:
        if type(sym1) is ast.Assign:
            if type(sym1.targets[0]) is ast.Attribute:
                globalAttributes[sym1.targets[0].attr] = sym1.lineno
            else:
                globalAttributes[sym1.targets[0].id] = sym1.lineno
        elif type(sym1) is ast.FunctionDef:
            globalFunctions[sym1.name] = sym1.lineno
        elif type(sym1) is ast.ClassDef:
            classes[sym1.name] = (sym1.lineno, _parse_class_body(sym1.body))
    if globalAttributes:
        symbols['attributes'] = globalAttributes
    if globalFunctions:
        symbols['functions'] = globalFunctions
    if classes:
        symbols['classes'] = classes

    return symbols



Al principio de la función "obtain_symbols" estoy haciendo un try-except porque los archivos que definían un encoding fallaban al tratar de ejecutarse el "parse", y obviando la linea del encoding podían ser parseados tranquilamente... obviamente voy a tener que hacer más pruebas para asegurarme que no tenga otros efectos secundarios :P
Esta fue la primera implementación y hace EXACTAMENTE lo que quiero, quizás después deba fijarme si sería conveniente usar algo como NodeVisitor o no.

Si llamaramos a la función "obtain_symbols" pasandole como código este mismo módulo, obtendríamos como resultado:

{'functions': {'_parse_class_body': 14, 'obtain_symbols': 28, '_parse_cls_function_body': 5}}

Lo cual no es una información muy loca que estemos obteniendo, pero cuando llamamos a esta función con el código del módulo "editor.py" de NINJA-IDE, los datos que obtenemos son los siguientes:

{'functions': {'_parse_class_body': 14, 'obtain_symbols': 28, '_parse_cls_function_body': 5}}
editor^[{'functions': {'create_editor': 733}, 'classes': {'Editor': (36, {'attributes': {'syncDocErrorsSignal': 72, 'errors': 67, '_mtime': 110, 'highlighter': 71, 'newDocument': 70, 'extraSelections': 599, 'textModified': 69, 'pep8': 66, 'ask_if_externally_modified': 82, '_sidebarWidget': 61, '__actionFindOccurrences': 92, '_patIsWord': 77, 'braces': 79}, 'functions': {'jump_to_line': 181, '_find_occurrences': 194, 'mousePressEvent': 524, 'get_text': 174, 'go_to_definition': 537, 'keyPressEvent': 374, '_sync_tab_icon_notification_signal': 130, 'dropEvent': 530, 'has_write_permission': 145, 'show_pep8_errors': 116, 'show_static_errors': 123, '__init__': 55, 'indent_more': 231, 'zoom_in': 204, 'get_parent_project': 220, '_text_under_cursor': 432, 'set_flags': 97, 'set_cursor_position': 226, 'keyReleaseEvent': 369, 'contextMenuEvent': 462, 'zoom_out': 212, 'check_external_modification': 138, 'find_match': 325, 'register_syntax': 168, 'indent_less': 272, 'mouseMoveEvent': 493, 'wheelEvent': 450, 'go_to_line': 198, 'get_cursor_position': 223, 'set_font': 177, '_match_braces': 563, 'get_selection': 551, '_file_saved': 161, 'highlight_current_line': 598, 'restyle': 150, 'replace_match': 339, 'paintEvent': 437, 'focusInEvent': 362, 'set_id': 108}})}}

Los cuales una vez parseado por el Widget del Árbol de Símbolos de NINJA-IDE, nos muestra la información de esta forma:

Y nos permite navegar hacia cualquiera de esos símbolos solo haciendo click en el.

Y ahora para el espacio cultural del Post, dejo algunas fotos que saque en Buenos Aires:




Y después al mediodia del Lunes cuando almorce en Aeroparque... descubrí que todos los lugares de comida eran sucursales del Restaurant "Uy, nos rompieron el orto" de Capussotto.


Ejemplo 1:
sandwich de jamon y queso + gaseosa = 52


Vale aclarar que se aceptan mejoras sobre el código las cuales seguramente terminarán incluidas en NINJA-IDE! :P